Skip to content

Commit

Permalink
Merge pull request #1 from WDGPH/initial-version
Browse files Browse the repository at this point in the history
Initial version
  • Loading branch information
jangevaare authored Jul 3, 2024
2 parents 1de5fc2 + 3febad4 commit 5769455
Show file tree
Hide file tree
Showing 14 changed files with 2,841 additions and 0 deletions.
1 change: 1 addition & 0 deletions .Rprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
source("renv/activate.R")
55 changes: 55 additions & 0 deletions .github/workflows/test-R.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Run test.R

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup R
uses: r-lib/actions/setup-r@v2

- name: Setup renv
uses: r-lib/actions/setup-renv@v2

- name: Setup pandoc
uses: r-lib/actions/setup-pandoc@v2

- name: Install Arial font
run: |
sudo apt-get update
echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
sudo apt-get install -y ttf-mscorefonts-installer
sudo fc-cache -fv
sudo fc-list
- name: Setup TinyTex
uses: r-lib/actions/setup-tinytex@v2

- name: Run test.R
run: |
Rscript test.R
- name: Save input artifact
uses: actions/upload-artifact@v4
with:
name: test-input
path: input/
if-no-files-found: error

- name: Save output artifact
uses: actions/upload-artifact@v4
with:
name: test-output
path: output/
if-no-files-found: error
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.Rproj.user
.Rhistory
.RData
.Ruserdata
input
output
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Immunization Charts

## Introduction
This project provides an approach to the creation of custom immunization history charts. These charts can be generated as part of notice letters for overdue Immunization of School Pupils Act (ISPA)-mandated or Child Care and Early Years Act (CCEYA)-mandated immunizations.

## Usage
### Environment
[R](https://www.r-project.org/) is used with [LaTeX](https://www.latex-project.org/) (via [rmarkdown](https://pkgs.rstudio.com/rmarkdown/index.html)) for PDF generation. [renv](https://rstudio.github.io/renv/index.html) is used in this repository to assist with accurately reproducing the R project environment.

### Data
This project is intended to be used with data extracts from [Panorama PEAR](https://accessonehealth.ca/).

Input files, in `xlsx` format should be organized in a subfolder `input` (out of caution, input and output folders are `.gitignore`d, and need to be recreated by the user). Each `xlsx` file should have a shared format. It's suggested that `xlsx` exports from Panorama PEAR are batched by client birth year. The report must at minimum include "Client ID", "Date of Birth", and a string representation of the immunization history, in a column "Received Agents". To create this immunization history string, a "Repeater" Data Container must be used in the Panorama PEAR report builder. The repeater will be formatted as:
1. `[PresentationView].[Immunization Received].[Date Administered]`
2. Text box with space, dash, and a space (` - `)
3. `[PresentationView].[Immunization Received].[Immunizing Agent]`

### Functionality
`make_charts.R` contains data processing steps, with some functions relating specifically to formatting information for use in LaTeX code separated out into `latex_utilities.R`. Based on your particular report, adjust the `col_types` and `select`ed columns for your particular data file(s) in `make_charts.R`.

`chart_template.Rmd` allows for generation of PDF files using LaTeX, by inserting processed data elements into LaTeX code. This LaTeX code can be customized and expanded upon such that the immunization chart is an element in a larger letter with:
- Addressee information that can be shown in the window of an envelope
- Public Health Unit branding
- List of overdue diseases
- Public Health Unit-specific instructions for updating vaccination records or consultation on vaccination
- Any other customizations that can enhance client experience or streamline vaccine record management operations

This project currently supports charts that include any combination of CCEYA and ISPA-mandated vaccinations, in addition to HPV and Hepatitis B recommended vaccines.

These diseases can be re-ordered to suit your application, through modifications in the parameters section in `make_charts.R`. Any diseases left off generated charts will be collapsed into the 'Other' diseases column.

`vaccine_reference.xlsx` includes the specific vaccine values currently supported, and the diseases they immunize against for the purposes of indicator dots on the immunization history chart output. Create an issue or pull request to add more vaccines.

An `output` subfolder should also be created for generated PDFs, and a leger of vaccines detected in the `Received Agents` in your data file(s).

Note that immunization history for a single client can exceed a single page. For large mailing campaigns utilizing a envelope stuffing machine, you will need to separate these clients out from those with records that fit on a single page.

### Testing
`test.R` generates a data file with vaccination history for a single client, which can be used with `make_charts.R` with default parameters. This client receives every vaccine in `vaccine_reference.xlsx` (one per week). Running `test.R` will create `input` and `output` subdirectories, create the test data, and generate a PDF notice for the client.

## Contributing
Fixes or additions to the `vaccine_reference.xlsx`, dependency updates, documentation improvements, and additions of tests will enhance the usability and reliability of this project and are welcome contributions.
91 changes: 91 additions & 0 deletions chart_template.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
output:
pdf_document:
latex_engine: xelatex
keep_tex: false
documentclass: article
header-includes:
- \usepackage{amssymb}
- \usepackage[margin=2cm]{geometry}
- \usepackage{ragged2e} # text alignment utilities
- \usepackage{ltablex} # tabularx with longtable functionality
- \usepackage{rotating} # rotating table cells
- \usepackage{fancyhdr} # custom page numbering
- \usepackage{lastpage} # support custom page number
- \usepackage{fontspec} # font utilities
- \setmainfont{Arial} # default font type
params:
client_data: NULL
chart_num_diseases: NULL
chart_col_header: NULL

---

```{=latex}
% Custom circle indicator for vaccination history charts
\newcommand{\mycircle}{\raisebox{-0.2\height}{\resizebox{1em}{!}{$\bullet$}}}
% Removes the horizontal line under the header when using fancyhdr
\renewcommand{\headrulewidth}{0pt}
% Define a command to reset page counter and update last page reference
\newcommand{\newdocument}{
\setcounter{page}{1}
\pagestyle{fancy}
\fancyhf{}
\fancyfoot[C]{Page \thepage\ of \pageref{LastPage}}
% ltablex setting
\keepXColumns
}
```

```{r, results='asis', echo=FALSE}
# One client per row
for (j in seq_len(nrow(params$client_data))) {
# Extract single row of data
client = as.list(params$client_data[j,])
client$`Page LaTeX` = c(
"
\\newdocument
\\huge \\textbf{Immunization Record}
\\normalsize Client ID: \\textbf{", client$`Client ID`, "}
\\vspace{0.25cm}
\\normalsize Below is a record of all immunizations received by the client on file with Public Health, excluding seasonal vaccinations against influenza and COVID-19.
\\setlength{\\arrayrulewidth}{1pt}
\\renewcommand{\\arraystretch}{1.25}
\\setlength{\\tabcolsep}{1pt}
\\begin{tabularx}{\\textwidth}{|l|l", rep("|>{\\centering\\arraybackslash}p{0.35cm}", params$chart_num_diseases + 1L), "|>{\\raggedright\\arraybackslash}X|}
\\hline
", params$chart_col_header, "\\\\
\\hline
\\endfirsthead
\\multicolumn{", params$chart_num_diseases + 4L, "}{c}{{Continuation of immunization record}} \\\\
\\hline
", params$chart_col_header, "\\\\
\\hline
\\endhead
\\multicolumn{", params$chart_num_diseases + 4L, "}{c}{{Immunization record continued on next page}} \\\\
\\endfoot
\\multicolumn{", params$chart_num_diseases + 4L, "}{c}{{End of immunization record}} \\\\
\\endlastfoot
",
client$`Vaccine History LaTeX`[[1]],
"
\\end{tabularx}
\\clearpage")
cat(client$`Page LaTeX`, sep = "")
}
```
13 changes: 13 additions & 0 deletions immunization-charts.Rproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX
61 changes: 61 additions & 0 deletions latex_utilities.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Trim specified number of lines from a string (application to generated LaTeX)
LaTeX_trim_lines = function(x, drop_top = 0L, drop_bottom = 0L){
xlines = x |>
str_split("\n")|>
unlist()

if(drop_bottom > 0L){
tlines = length(xlines)
xlines = xlines |>
extract(-((tlines - drop_bottom + 1L):tlines))
}

if(drop_top > 0L){
xlines = xlines |>
extract(-(1:drop_top))
}

xlines |>
paste0(collapse = "\n")
}


# Add rows to a LaTeX table
LaTeX_pad_rows = function(x, n, m){
# Detect how many rows in x
current_rows = str_count(x, pattern = "\\\\\\\\\\n\\\\hline")

if(current_rows == 0L){
# Blank table
paste(c(
rep(
paste(c(
rep(
" &",
times = m - 1L),
"\\\\\n\\hline\n"),
collapse = ""),
times = n)),
collapse = "")


} else if(current_rows |> between(1L, n - 1L)){
# Add empty rows to achieve n rows
# where m is number of columns
paste(c(
x,
rep(
paste(c(
rep(
" &",
times = m - 1L),
"\\\\\n\\hline\n"),
collapse = ""),
times = n - current_rows)),
collapse = "")

} else if(current_rows >= n){
# Return x if already meets minimum row requirement
x
}
}
Loading

0 comments on commit 5769455

Please sign in to comment.