API Reference¶
Auto-generated from NumPy-format docstrings in the pipeline/ package.
Orchestrator¶
pipeline.orchestrator
¶
VIPER Pipeline Orchestrator.
This script orchestrates the end-to-end immunization notice generation pipeline. It executes each step in sequence, handles errors, and provides detailed timing and progress information.
Error Handling Philosophy:
The pipeline distinguishes between critical and optional steps:
-
Critical Steps (Notice generation, Compilation, PDF validation) implement fail-fast:
- Any error halts the pipeline immediately
- No partial output; users get deterministic results
- Pipeline exits with code 1; user must investigate and retry
-
Optional Steps (QR codes, Encryption, Bundling) implement per-item recovery:
- Individual item failures (PDF, client, bundle) are logged and skipped
- Remaining items continue processing
- Pipeline completes successfully even if some items failed
- Users are shown summary of successes, skipped, and failed items
-
Infrastructure Errors (missing files, config errors) always fail-fast:
- Caught and raised immediately; no recovery attempts
- Prevents confusing partial output caused by misconfiguration
- Pipeline exits with code 1
Exit Codes:
- 0: Pipeline completed successfully
- 1: Pipeline failed (critical step error or infrastructure error)
- 2: User cancelled (output preparation step)
parse_args
¶
Parse command-line arguments.
Source code in pipeline/orchestrator.py
validate_args
¶
Validate command-line arguments and raise errors if invalid.
Source code in pipeline/orchestrator.py
main
¶
Run the pipeline orchestrator.
Source code in pipeline/orchestrator.py
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | |
Configuration¶
pipeline.config_loader
¶
Configuration loading utilities for the immunization pipeline.
Provides a centralized way to load and validate the parameters.yaml configuration file across all pipeline scripts.
load_config
¶
Load and parse the parameters.yaml configuration file.
Automatically validates the configuration after loading. Raises clear exceptions if validation fails, enabling fail-fast behavior for infrastructure errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config_path
|
Path
|
Path to the configuration file. If not provided, uses the default location (config/parameters.yaml in the project root). |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Parsed and validated YAML configuration as a nested dictionary. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the configuration file does not exist. |
YAMLError
|
If the configuration file is invalid YAML. |
ValueError
|
If the configuration fails validation (see validate_config). |
Source code in pipeline/config_loader.py
validate_template_fields
¶
Validate that all placeholders in a template are supported fields.
Checks template string placeholders against the centralized whitelist of allowed template fields (TemplateField enum). Raises ValueError if any unsupported placeholders are found.
This validation catches configuration errors early (at config load time) instead of failing silently during QR generation or PDF encryption.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
str
|
Template string with placeholders (e.g., "{client_id}_{invalid_field}") |
required |
context_name
|
str
|
Human-readable name for error messages (e.g., "QR code payload", "encryption password") |
required |
config_key
|
str
|
Configuration key path for error messages (e.g., "qr.payload_template") |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If template contains unsupported placeholder fields with detailed error message listing invalid fields and available options. |
Examples:
>>> validate_template_fields(
... "{client_id}_{invalid_field}",
... "QR code payload",
... "qr.payload_template"
... )
ValueError: QR code payload template contains unsupported placeholder(s): ['invalid_field']
Config key: qr.payload_template
Supported fields: client_id, first_name, last_name, ...
Source code in pipeline/config_loader.py
validate_config
¶
Validate the entire configuration for consistency and required values.
Validates all conditional and required configuration keys across the entire config. Raises clear exceptions if validation fails, allowing the pipeline to fail-fast with actionable error messages.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Dict[str, Any]
|
Configuration dictionary (result of load_config). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If required configuration is missing or invalid. |
Notes
Validation checks:
- QR Generation: If qr.enabled=true, requires qr.payload_template (non-empty string)
- Typst Compilation: If typst.bin is set, must be a string
- PDF Bundling: If bundle_size > 0, must be positive integer; group_by must be valid enum
- Encryption: If encryption.enabled=true, requires password.template
- Cleanup: If delete_unencrypted_pdfs is set, must be boolean
Validation philosophy: - Infrastructure errors (missing config) raise immediately (fail-fast) - All error messages are clear and actionable - Config is validated once at load time, not per-step
Source code in pipeline/config_loader.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | |
Data Models¶
pipeline.data_models
¶
Unified data models for the immunization pipeline.
This module provides all core dataclasses used throughout the pipeline, ensuring consistency and type safety across processing steps.
ClientRecord
dataclass
¶
Unified client record across all pipeline steps.
This dataclass represents a single client (student) record passed through the entire pipeline. It contains all necessary information for: - Generating personalized notices - Creating QR codes - Encrypting PDFs - Batching outputs
Fields
sequence : str Zero-padded sequence number for the client (e.g., '00001').
client_id : str Unique client identifier.
language : str ISO 639-1 language code ('en' or 'fr'). Must be a valid Language enum value (see pipeline.enums.Language). Validated using Language.from_string() at entry points (CLI, configuration loading, preprocessing). All functions assume this field contains a valid language code; invalid codes should be caught before ClientRecord instantiation.
person : Dict[str, Any]
- Person details:
- full_name: Combined first and last name
- first_name: Given name (optional)
- last_name: Family name (optional)
- date_of_birth: Display format (e.g., "Jan 8, 2025")
- date_of_birth_iso: ISO format (YYYY-MM-DD)
- date_of_birth_display: Localized display format
- age: Calculated age in years
- over_16: Boolean flag for age >= 16
school : Dict[str, Any] School information: name, id, code, type.
board : Dict[str, Any] School board information: name, id, code.
contact : Dict[str, Any] Contact address: street, city, province, postal_code.
vaccines_due : Optional[str] Comma-separated string of vaccines due (display format).
vaccines_due_list : Optional[List[str]] List of vaccine names/codes due.
received : Optional[Sequence[Dict[str, object]]] List of vaccine records already received (structured data).
metadata : Dict[str, object] Custom pipeline metadata (warnings, flags, etc.).
qr : Optional[Dict[str, Any]]
- QR code information (if generated):
- payload: URL encoded in QR code (same string that becomes QR PNG data)
- filename: PNG filename (e.g., "qr_code_00001_1234567890.png")
- path: Relative path to PNG file
Source code in pipeline/data_models.py
PreprocessResult
dataclass
¶
Result of preprocessing step.
The output of Step 2 (preprocessing) that contains normalized client data and any warnings generated during processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clients
|
List[ClientRecord]
|
Processed and validated client records. |
required |
warnings
|
List[str]
|
Non-fatal warnings encountered during preprocessing (e.g., missing optional fields, unrecognized vaccine codes). |
required |
Source code in pipeline/data_models.py
ArtifactPayload
dataclass
¶
Preprocessed artifact with metadata.
The JSON artifact written by Step 2 (preprocessing) and read by downstream steps. Contains all normalized client data and provenance information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_id
|
str
|
Unique pipeline run identifier (timestamp-based). |
required |
language
|
str
|
ISO 639-1 language code ('en' or 'fr'). Must be a valid Language enum value (see pipeline.enums.Language). All clients in the artifact must have language codes that match this field; validation ensures consistency across all notices generated in a single run. |
required |
clients
|
List[ClientRecord]
|
All processed client records. |
required |
warnings
|
List[str]
|
All preprocessing warnings. |
required |
created_at
|
str
|
ISO 8601 timestamp when artifact was created. |
required |
input_file
|
Optional[str]
|
Name of the input file processed (for audit trail). |
None
|
total_clients
|
int
|
Total number of clients in artifact (convenience field). |
0
|
Source code in pipeline/data_models.py
PdfRecord
dataclass
¶
Compiled PDF with client metadata.
Represents a single generated PDF notice with its associated client data and page count. Used during batching (Step 8) to group PDFs and generate manifests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sequence
|
str
|
Zero-padded sequence number matching the PDF filename. |
required |
client_id
|
str
|
Client identifier matching the PDF filename. |
required |
pdf_path
|
Path
|
Absolute path to the generated PDF file. |
required |
page_count
|
int
|
Number of pages in the PDF (usually 2 for immunization notices). |
required |
client
|
Dict[str, Any]
|
Full client data dict for manifest generation and batching. |
required |
Source code in pipeline/data_models.py
Enumerations¶
pipeline.enums
¶
Enumerations for the immunization pipeline.
BundleStrategy
¶
Bases: Enum
Bundle grouping strategy.
Source code in pipeline/enums.py
from_string
classmethod
¶
Convert string to BundleStrategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str | None
|
Bundle strategy name ('size', 'school', 'board'), or None for default. |
required |
Returns:
| Type | Description |
|---|---|
BundleStrategy
|
Corresponding BundleStrategy enum, defaults to SIZE if value is None. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not a valid strategy name. |
Source code in pipeline/enums.py
BundleType
¶
Language
¶
Bases: Enum
Supported output languages for immunization notices.
Each language corresponds to:
- A template renderer in templates/ (en_template.py, fr_template.py, etc.)
- Localization of dates, disease names, and notice formatting
- An artifact language code stored in preprocessed data
Currently supports English and French; extensible for future languages.
Attributes:
| Name | Type | Description |
|---|---|---|
ENGLISH |
str
|
English language code ('en'). Templates: templates/en_template.py |
FRENCH |
str
|
French language code ('fr'). Templates: templates/fr_template.py |
See Also
get_language_renderer : Map Language enum to template rendering function
Source code in pipeline/enums.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | |
from_string
classmethod
¶
Convert string to Language enum.
Provides safe conversion from user input or configuration strings to Language enum values. Used at CLI entry point and configuration loading to fail fast on invalid language codes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str | None
|
Language code ('en', 'fr'), or None for default (ENGLISH). Case-insensitive (normalizes to lowercase). |
required |
Returns:
| Type | Description |
|---|---|
Language
|
Corresponding Language enum value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not a valid language code. Error message lists all available options. |
Examples:
>>> Language.from_string('es') # Unsupported
ValueError: Unsupported language: es. Valid options: en, fr
Source code in pipeline/enums.py
all_codes
classmethod
¶
Get set of all supported language codes.
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of all language codes (e.g., {'en', 'fr'}). |
Examples:
Source code in pipeline/enums.py
TemplateField
¶
Bases: Enum
Available placeholder fields for template rendering (QR codes, PDF passwords).
These fields are dynamically generated from client data by build_client_context() and can be used in configuration templates for:
- QR code payloads (qr.payload_template in parameters.yaml)
- PDF password generation (encryption.password.template in parameters.yaml)
All fields are validated by validate_and_format_template() to catch config errors early and provide clear error messages.
Fields
CLIENT_ID : str Unique client identifier
FIRST_NAME : str Client's given name.
LAST_NAME : str Client's family name.
NAME : str Full name (first + last combined).
DATE_OF_BIRTH : str Display format (e.g., "Jan 8, 2025" or "8 janvier 2025").
DATE_OF_BIRTH_ISO : str ISO 8601 format: YYYY-MM-DD (e.g., "2015-03-15").
DATE_OF_BIRTH_ISO_COMPACT : str Compact ISO format without hyphens: YYYYMMDD (e.g., "20150315").
SCHOOL : str School name.
BOARD : str School board name.
STREET_ADDRESS : str Full street address.
CITY : str City/municipality.
PROVINCE : str Province/territory.
POSTAL_CODE : str Postal/ZIP code.
LANGUAGE_CODE : str ISO 639-1 language code: 'en' or 'fr'.
See Also
build_client_context : Generates context dict with all available fields validate_and_format_template : Validates templates against allowed_fields set
Source code in pipeline/enums.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
all_values
classmethod
¶
Get set of all available field names for use as allowed_fields whitelist.
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of all field values (e.g., {'client_id', 'first_name', ...}). |
Examples:
Source code in pipeline/enums.py
Step 1 — Output Preparation¶
pipeline.prepare_output
¶
Utility to prepare the pipeline output directory.
This script ensures the output directory exists, optionally removes any existing contents (while preserving the logs directory), and creates the log directory if needed.
Note: This module is called exclusively from orchestrator.py. The internal functions handle all logic; CLI support has been removed in favor of explicit function calls from the orchestrator.
Input Contract:
- Receives output directory path and auto_remove_output flag from config
- Assumes configuration has been validated by load_config() at orchestrator startup
Output Contract:
- Creates output directory structure if it doesn't exist
- Optionally removes existing output while preserving logs
- Ensures log and artifact subdirectories are ready for pipeline output
Error Handling:
- File system permission errors raise immediately (infrastructure error)
- Missing directories are created automatically (no error)
- Fails fast on unrecoverable I/O errors
Validation Contract:
What this module validates:
- Output directory can be created if missing
- File system permissions allow write/delete operations
- Log directory can be preserved during cleanup
What this module assumes (validated upstream):
- Config keys (pipeline.auto_remove_output) have been validated by load_config()
- Output path is a valid directory path (basic format validation)
Note: This is a utility/setup step. Runs before the main pipeline; failures halt everything (fail-fast) since output directory is prerequisite for all steps.
is_log_directory
¶
Check if a path is the log directory or one of its ancestors.
Module-internal helper for purge_output_directory(). The pipeline stores logs
under a dedicated directory (output/logs). When cleaning the output directory
we must preserve the log directory and its contents. This check accounts for
potential symlinks by resolving both paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
Path
|
Path to check. |
required |
log_dir
|
Path
|
Reference log directory path. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if candidate is the log directory or an ancestor, False otherwise. |
Source code in pipeline/prepare_output.py
purge_output_directory
¶
Remove everything inside output_dir except the logs directory.
Module-internal helper for prepare_output_directory(). Recursively deletes all files and subdirectories except the log directory, which is preserved for audit trails.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Output directory to clean. |
required |
log_dir
|
Path
|
Log directory to preserve. |
required |
Source code in pipeline/prepare_output.py
default_prompt
¶
Prompt user for confirmation to delete output directory contents.
Module-internal helper for prepare_output_directory(). Interactive prompt to prevent accidental data loss when auto_remove is False.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Directory path being queried. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if user confirms (y/yes), False otherwise. |
Source code in pipeline/prepare_output.py
prepare_output_directory
¶
Prepare the output directory for a new pipeline run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root directory for pipeline outputs. |
required |
log_dir
|
Path
|
Directory where pipeline logs are stored. Typically a subdirectory of
|
required |
auto_remove
|
bool
|
When |
required |
prompt
|
Optional[Callable[[Path], bool]]
|
Optional callable used to prompt the user for confirmation. A return
value of |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in pipeline/prepare_output.py
Step 2 — Preprocessing¶
pipeline.preprocess
¶
Preprocessing pipeline for immunization-charts.
Normalizes and structures input data into a single JSON artifact for downstream pipeline steps. Handles data validation, client sorting, and vaccine processing. QR code generation is handled by a separate step after preprocessing.
Input Contract:
- Reads raw client data from CSV or Excel file (.xlsx, .xls, .csv)
- Validates file type and encoding (tries multiple encodings for CSV)
- Validates all required columns are present
Output Contract:
- Writes preprocessed artifact JSON to output/artifacts/preprocessed_clients_*.json
- Artifact contains all valid client records with normalized data types
- Artifact includes metadata (run_id, language, created_at, warnings)
- Downstream steps assume artifact is valid; preprocessing is the sole validation step
Error Handling:
- File I/O errors (missing file, unsupported format) raise immediately (infrastructure)
- Missing required columns raise immediately (data error in required step)
- Invalid data (missing DOB, unparseable date) logged as warnings; processing continues
- Fail-fast for structural issues; warn-and-continue for data quality issues
Validation Contract:
What this module validates:
- Input file exists and is readable
- Input file is supported format (.xlsx, .xls, .csv)
- File encoding (tries UTF-8, Latin-1, etc. for CSV)
- All required columns are present in input data
- Client data normalization (DOB parsing, vaccine processing)
- Language code is valid (from CLI argument)
What this module assumes (validated upstream):
- Language code from CLI is valid (validated by Language.from_string() at orchestrator)
- Disease and vaccine reference data are valid JSON (validated by config loading)
Note: This is the primary validation step. Downstream steps trust preprocessing output.
convert_date_string
¶
Convert a date to display format with locale-aware formatting.
Uses Babel for locale-aware date formatting. Generates format like "May 8, 2025" (en) or "8 mai 2025" (fr) depending on locale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_str
|
str | datetime | Timestamp
|
Date string in YYYY-MM-DD format or datetime-like object. |
required |
locale
|
str
|
Locale code for date formatting (default: "en"). Examples: "en" for English, "fr" for French. |
'en'
|
Returns:
| Type | Description |
|---|---|
str | None
|
Date in locale-specific format, or None if input is null. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If date_str is a string in unrecognized format. |
Source code in pipeline/preprocess.py
format_iso_date_for_language
¶
Format an ISO date string with locale-aware formatting for the given language.
Converts a date from ISO format (YYYY-MM-DD) to a long, locale-specific display format using Babel. This function handles language-specific date formatting for templates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iso_date
|
str
|
Date in ISO format (YYYY-MM-DD), e.g., "2025-08-31". |
required |
language
|
str
|
ISO 639-1 language code ("en", "fr", etc.). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Formatted date in the specified language, e.g., "August 31, 2025" (en) or "31 août 2025" (fr). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If iso_date is not in YYYY-MM-DD format. |
Source code in pipeline/preprocess.py
check_addresses_complete
¶
Check if address fields are complete in the DataFrame.
Adds a boolean 'address_complete' column based on presence of street address, city, province, and postal code.
Source code in pipeline/preprocess.py
convert_date_iso
¶
Convert a date from English display format to ISO format.
Reverses the formatting from convert_date_string(). Expects input in "Mon DD, YYYY" format (e.g., "May 8, 2025").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_str
|
str
|
Date in English display format (e.g., "May 8, 2025"). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Date in ISO format (YYYY-MM-DD). |
Source code in pipeline/preprocess.py
over_16_check
¶
Check if a client is over 16 years old on notice delivery date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_of_birth
|
str
|
Date of birth in YYYY-MM-DD format. |
required |
date_notice_delivery
|
str
|
Notice delivery date in YYYY-MM-DD format. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the client is over 16 years old on date_notice_delivery, False otherwise. |
Source code in pipeline/preprocess.py
configure_logging
¶
Configure file logging for the preprocessing step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory where logs subdirectory will be created. |
required |
run_id
|
str
|
Unique run identifier used in log filename. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Path to the created log file. |
Source code in pipeline/preprocess.py
detect_file_type
¶
Detect file type by extension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
Path
|
Path to the file to detect. |
required |
Returns:
| Type | Description |
|---|---|
str
|
File extension in lowercase (e.g., '.xlsx', '.csv'). |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file does not exist. |
Source code in pipeline/preprocess.py
read_input
¶
Read CSV or Excel input file into a pandas DataFrame.
Supports .xlsx, .xls, and .csv formats with robust encoding and delimiter detection. This is a critical preprocessing step that loads raw client data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
Path
|
Path to the input file (CSV, XLSX, or XLS). |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with raw client data loaded from the file. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If file type is unsupported or CSV cannot be decoded with common encodings. |
Exception
|
If file reading fails for any reason (logged to preprocessing logs). |
Source code in pipeline/preprocess.py
normalize
¶
Normalize formatting prior to matching.
Source code in pipeline/preprocess.py
split_vaccine_due_entry
¶
Separate a disease name from its optional dose field.
Source code in pipeline/preprocess.py
hide_vaccine_due_doses
¶
Remove supplied dose fields while preserving ordinary disease labels.
format_vaccine_due_list
¶
Format dose-bearing overdue entries for display.
Source code in pipeline/preprocess.py
map_columns
¶
Map dataframe columns to a set of required column names using fuzzy matching.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Input dataframe whose columns will be matched and optionally renamed. |
required |
required_columns
|
Sequence[str]
|
Sequence of expected/required column names to match against. Defaults to REQUIRED_COLUMNS. |
REQUIRED_COLUMNS
|
Returns:
| Type | Description |
|---|---|
tuple[DataFrame, dict]
|
A tuple (renamed_df, col_map) where |
Behavior
- Normalizes input column names and required column names using
normalize(...)before matching. - For each normalized input column, finds the best fuzzy match among normalized
required_columnsusingprocess.extractOne(..., scorer=fuzz.partial_ratio). - If the best match score is >= 80 (threshold in the implementation), the original input column name is mapped to the corresponding required column name; the mapping is recorded and the dataframe is renamed accordingly.
- A debug line is printed for each accepted match: "Matching '
' to ' ' with score ". - Columns with a best match score < 80 are ignored (not included in
col_map); matches with score 0 are effectively dropped. - The code resolves the original column name by locating the first column whose normalized form equals the normalized input. If multiple original columns normalize to the same value, the first encountered is used.
Notes
- The function depends on external helpers:
normalize,process.extractOne, andfuzz.partial_ratio. - The match threshold (80) is adjustable; lowering it makes matching more permissive, raising it makes it stricter.
- A
StopIterationmay occur if a normalized input column cannot be resolved back to an original column name. required_columnsshould be an iterable of strings;df.columnsare expected to be convertible to strings.
Examples:
Example usage (illustrative only):¶
renamed_df, mapping = map_columns(df, required_columns=['state', 'date', 'count'])¶
Source code in pipeline/preprocess.py
filter_columns
¶
Filter dataframe to only include required columns.
Source code in pipeline/preprocess.py
normalize_dataframe
¶
Validate, rename, and normalize the input DataFrame.
Combines column validation with type normalization. Standardizes column names to uppercase with underscores, validates all required columns are present, then normalizes data types and fills missing values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Input DataFrame with raw client data (column names may have mixed case/spacing). |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
Copy of DataFrame with validated, renamed, and normalized columns. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any required columns are missing from the DataFrame. |
Source code in pipeline/preprocess.py
synthesize_identifier
¶
Generate a deterministic identifier if one is not provided.
Source code in pipeline/preprocess.py
process_vaccines_due
¶
Map overdue diseases to canonical disease names.
Normalizes raw input disease strings to canonical disease names using config/disease_normalization.json. Returns a comma-separated string of canonical disease names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vaccines_due
|
Any
|
Raw string of comma-separated disease names from input. |
required |
language
|
str
|
Language code (e.g., "en", "fr"). Used for logging. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Comma-separated string of canonical disease names (English). Empty string if input is empty or invalid. |
Source code in pipeline/preprocess.py
normalize_validity_status
¶
Normalize a raw validity token to one of three canonical statuses.
Only the exact casings "valid"/"Valid" and "invalid"/"Invalid" are accepted as known statuses; everything else — typos, alternate casings, empty strings, None, NaN — maps to "unknown". This strict gate prevents ambiguous data from silently influencing validity markers on notices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_status
|
Any
|
Raw value extracted from an IMMS_GIVEN segment, or any value that needs to be coerced to a canonical status. Typically a str, but accepts Any so callers need not guard against None or NaN. |
required |
Returns:
| Type | Description |
|---|---|
str
|
One of |
Examples:
>>> normalize_validity_status("Valid")
'valid'
>>> normalize_validity_status("")
'unknown'
>>> normalize_validity_status(None)
'unknown'
Source code in pipeline/preprocess.py
collapse_validity_statuses
¶
Collapse multiple validity statuses using strict precedence.
Precedence:
- mixed (if both valid and invalid are present and no unknown)
- valid (if at least one valid is present and no unknown)
- invalid (if invalid is present and no unknown)
- unknown (otherwise)
Source code in pipeline/preprocess.py
classify_dataset_validity
¶
Scan all IMMS_GIVEN values and classify dataset-level validity coverage.
Performs a pre-pass over the full dataset before the per-client loop so
that a single, accurate dataset-level decision can be made about whether
to show warnings, raise errors, or proceed normally. This avoids the
unreliable alternative of accumulating per-record "unknown" counts,
which can mask a structurally inconsistent dataset.
Called once by build_preprocess_result immediately before the client
loop. Its return value determines which branch of the warning/error logic
fires; see the behaviour table in the module docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
imms_given_series
|
Series
|
The |
required |
Returns:
| Type | Description |
|---|---|
Literal['all_present', 'all_absent', 'mixed']
|
|
Notes
- Pure scan — no side effects, no logging.
- O(n × d) where n is the number of rows and d is the average number
of dose segments per row; short-circuits as soon as
"mixed"is confirmed.
Source code in pipeline/preprocess.py
parse_dose_segments
¶
Parse an IMMS_GIVEN string into a flat sorted list of individual dose entries.
Extracts individual dose entries from a semicolon-delimited string,
normalizes dates to ISO format, normalizes validity to one of
"valid" / "invalid" / "unknown", and filters unwanted
vaccine names. Unlike the former process_received_agents, this
function does not group by date — grouping and disease-expansion are
handled by build_received_rows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
received_agents
|
Any
|
Raw IMMS_GIVEN cell value. Must be a non-empty |
required |
replace_unspecified
|
List[str]
|
Vaccine names to silently drop (e.g. |
required |
Returns:
| Type | Description |
|---|---|
List[Dict[str, str]]
|
Flat list of |
Source code in pipeline/preprocess.py
compute_column_statuses
¶
Compute per-column validity status for a set of vaccine entries.
For each named disease in the header, collects the validity of all
vaccines that contribute to that disease and collapses using
unknown > mixed > valid > invalid precedence. The "Other"
column captures any vaccine that contributes at least one disease
not found in the named-disease set.
"mixed" is produced when both "valid" and "invalid"
contribute to a column with no "unknown" — meaning different
vaccines have conflicting validity for that column on this date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vaccines
|
List[Dict[str, Any]]
|
Vaccine entries from |
required |
chart_diseases_header
|
List[str]
|
Ordered disease column headers. |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, str]
|
Column name → one of |
Source code in pipeline/preprocess.py
build_received_rows
¶
Parse IMMS_GIVEN into display rows with pre-computed per-column validity.
Orchestrates parse_dose_segments → _deduplicate_vaccines_for_date
→ _split_into_rows for each administration date. Dates whose
vaccines would produce a "mixed" column status are split into
separate rows: valid vaccines on the first row, others on subsequent
rows. The date_rowspan field carries the row-merge count so that
Typst can render a single merged date cell spanning all rows of a date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
received_agents
|
Any
|
Raw IMMS_GIVEN cell value. |
required |
replace_unspecified
|
List[str]
|
Vaccine names to suppress. |
required |
vaccine_reference
|
Dict[str, Any]
|
Vaccine-to-disease mapping. |
required |
chart_diseases_header
|
List[str]
|
Ordered disease column headers (used for column assignment and split ordering). |
required |
Returns:
| Type | Description |
|---|---|
List[Dict[str, Any]]
|
Flat list of display rows, each with:: |
Source code in pipeline/preprocess.py
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | |
build_preprocess_result
¶
Normalize client data and produce the structured preprocessing artifact.
Orchestrates all per-dataset and per-client normalization: column
mapping, sorting, sequence assignment, dataset-level validity
classification, age calculation, vaccine history parsing, and disease
enrichment. The resulting PreprocessResult is the sole artifact
consumed by all downstream pipeline steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Raw input DataFrame, typically loaded from an Excel or CSV file.
Must contain all columns listed in |
required |
language
|
str
|
Language code for this batch ( |
required |
vaccine_reference
|
Dict[str, Any]
|
Maps vaccine codes to disease names. Passed through to
|
required |
replace_unspecified
|
List[str]
|
Vaccine names to suppress from immunization history. Passed
through to |
required |
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
PreprocessResult
|
Contains a list of |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ValueError
|
If any required columns are missing from |
Notes
- Reads
config_pathon every call to obtaindate_notice_delivery,chart_diseases_header,preprocess.include_dose, andpreprocess.show_validity_markers. If no path is provided,PARAMETERS_PATH(config/parameters.yaml) is used. A missing file is treated as empty config (all defaults apply). - Warns (does not raise) for: missing board name, missing date of
birth, duplicate client IDs,
all_absentvalidity whenshow_validity_markersisTrue,mixedvalidity whenshow_validity_markersisFalse.
Source code in pipeline/preprocess.py
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 | |
run_phix_validation
¶
Validate school names against the PHIX mapping file.
Reads phix_validation config from parameters.yaml. Returns the
DataFrame unchanged (with no warnings) when validation is disabled or
mapping_file is not set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Normalized DataFrame (output of |
required |
output_dir
|
Path
|
Directory where result CSVs ( |
required |
Returns:
| Type | Description |
|---|---|
tuple[DataFrame, list[str]]
|
Enriched DataFrame and a (possibly empty) list of warning strings. |
Source code in pipeline/preprocess.py
write_artifact
¶
Write preprocessed result to JSON artifact file.
Source code in pipeline/preprocess.py
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 | |
Step 3 — QR Code Generation¶
pipeline.generate_qr_codes
¶
Generate QR code PNG files from preprocessed client artifact.
This module creates QR code images for each client in the preprocessed artifact. QR payloads are generated from template strings defined in parameters.yaml and rendered as PNG files in the output artifacts directory.
The QR code generation step is optional and can be skipped via the qr.enabled configuration setting.
Input Contract:
- Reads preprocessed artifact JSON (created by preprocess step)
- Assumes artifact contains valid client records with required fields
- Assumes qr.enabled=true and qr.payload_template defined in config (if QR generation requested)
Output Contract:
- Writes QR code PNG files to output/artifacts/qr_codes/
- Returns list of successfully generated QR file paths
- Per-client errors are logged and skipped (optional feature; doesn't halt pipeline)
Error Handling:
- Configuration errors (missing template) raise immediately (infrastructure error)
- Per-client failures (invalid data) log warning and continue (data error in optional feature)
- This strategy allows partial success; some clients may not have QR codes
Validation Contract:
What this module validates:
- Artifact file exists and is valid JSON (validation in read_preprocessed_artifact())
- QR code generation is enabled in config (qr.enabled=true)
- Payload template is defined if QR generation is enabled
- Payload template format is valid (has valid placeholders)
- QR code can be rendered as PNG (infrastructure check)
What this module assumes (validated upstream):
- Artifact JSON structure is valid (validated by preprocessing step)
- Client records have all required fields (validated by preprocessing step)
- Output directory can be created (general I/O)
Per-client failures (invalid client data, template rendering errors) are logged and skipped (intentional for optional feature). Some clients may lack QR codes.
encode_qr_payload_url
¶
URL-encode parameter values in a QR payload URL.
This function preserves the URL structure (scheme, domain, path, parameter delimiters) while properly encoding parameter values to handle special characters like spaces, accents, and special symbols.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload_url
|
str
|
A URL string like "https://example.com/surveys/?s=ABC&qrfn=First Name&qrln=Last Name" |
required |
Returns:
| Type | Description |
|---|---|
str
|
The same URL with parameter values properly percent-encoded (e.g., spaces → %20) |
Source code in pipeline/generate_qr_codes.py
generate_qr_code
¶
Generate a monochrome QR code PNG and return the saved path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
The string payload to encode inside the QR code. |
required |
output_dir
|
Path
|
Directory where the QR image should be saved. The directory is created if it does not already exist. |
required |
filename
|
Optional[str]
|
Optional file name (including extension) for the resulting PNG. When omitted a deterministic name derived from the payload hash is used. |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
Absolute path to the generated PNG file. |
Source code in pipeline/generate_qr_codes.py
read_preprocessed_artifact
¶
Read preprocessed client artifact from JSON.
Input Contract: Assumes artifact was created by preprocessing step and exists on disk. Does not validate artifact schema; assumes preprocessing has already validated client data structure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the preprocessed JSON artifact file. |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Parsed artifact dict with clients and metadata. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If artifact file does not exist. |
JSONDecodeError
|
If artifact is not valid JSON. |
Source code in pipeline/generate_qr_codes.py
load_qr_settings
¶
Load QR payload template from parameters.yaml file.
Raises ValueError if qr.payload_template is not specified in the configuration.
Returns: QR payload template string
Source code in pipeline/generate_qr_codes.py
generate_qr_codes
¶
Generate QR code PNG files from preprocessed artifact.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_path
|
Path
|
Path to the preprocessed JSON artifact. |
required |
output_dir
|
Path
|
Directory to write QR code PNG files. |
required |
config_path
|
Path
|
Path to parameters.yaml. If not provided, uses default location. |
None
|
Returns:
| Type | Description |
|---|---|
List[Path]
|
List of generated QR code PNG file paths. |
Source code in pipeline/generate_qr_codes.py
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | |
main
¶
Main entry point for QR code generation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_path
|
Path
|
Path to the preprocessed JSON artifact. |
required |
output_dir
|
Path
|
Directory to write QR code PNG files. |
required |
config_path
|
Path
|
Path to parameters.yaml configuration file. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of QR codes generated. |
Source code in pipeline/generate_qr_codes.py
Step 4 — Notice Generation¶
pipeline.generate_notices
¶
Generate per-client Typst notices from the normalized preprocessing artifact.
This module consumes the JSON artifact emitted by preprocess.py and generates
per-client Typst templates for notice rendering.
Input Contract:
- Reads preprocessed artifact JSON (created by preprocess step)
- Assumes artifact contains valid client records with all required fields
- Assumes language validation already occurred at CLI entry point
Output Contract:
- Writes per-client Typst template files to output/artifacts/typst/
- Returns list of successfully generated .typ file paths
- All clients must succeed; fails immediately on first error (critical feature)
Error Handling:
- Client data errors raise immediately (cannot produce incomplete output)
- Infrastructure errors (missing paths) raise immediately
- Invalid language enum raises immediately (should never occur if upstream validates)
- No per-client recovery; fail-fast approach ensures deterministic output
Validation Contract:
What this module validates:
- Artifact language matches all client languages (fail-fast if mismatch)
What this module assumes (validated upstream):
- Artifact file exists and is valid JSON (validated by read_artifact())
- Language code is valid (validated at CLI by argparse choices)
- Client records have all required fields (validated by preprocessing step)
- File paths exist (output_dir, logo_path, signature_path)
Functions with special validation notes:
- render_notice(): Calls Language.from_string() on client.language to convert string to enum; this adds a second validation layer (redundant but safe)
- get_language_renderer(): Assumes language enum is valid; no defensive check (language validated upstream via CLI choices + Language.from_string())
load_template_module
¶
Dynamically load a template module from specified directory.
Loads a language-specific template module at runtime from a custom directory. This enables PHU-specific template customization without code changes.
Validation Contract:
- Template file must exist at {template_dir}/{language_code}_template.py
- Module must define render_notice() function
- Raises immediately if file missing or render_notice() not found
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template_dir
|
Path
|
Directory containing template modules (e.g., templates/ or phu_templates/my_phu/) |
required |
language_code
|
str
|
Two-character ISO language code (e.g., "en", "fr") |
required |
Returns:
| Type | Description |
|---|---|
module
|
Loaded Python module with render_notice() function |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If template file doesn't exist at expected path |
ImportError
|
If module cannot be loaded |
AttributeError
|
If module doesn't define render_notice() function |
Examples:
>>> module = load_template_module(Path("templates"), "en")
>>> module.render_notice(context, logo_path="/logo.png", signature_path="/sig.png")
Source code in pipeline/generate_notices.py
build_language_renderers
¶
Build renderer dictionary from templates in specified directory.
Discovers and loads all available language template modules from the given directory, building a mapping of language codes to their render_notice functions.
Validation Contract:
- Only languages with corresponding template files are included
- Each available template must have valid render_notice() function
- Raises immediately if any template file exists but is invalid
- Does NOT require all Language enum values to be present
- Later validation ensures requested language is available when needed
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template_dir
|
Path
|
Directory containing language template modules |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Mapping of language codes (str) to render_notice functions (callable)
Format: {"en": |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If a template file exists but doesn't define render_notice() |
Examples:
>>> renderers = build_language_renderers(Path("templates"))
>>> renderers["en"](context, logo_path="/logo.png", signature_path="/sig.png")
>>> # PHU providing only English
>>> renderers = build_language_renderers(Path("phu_templates/my_phu"))
>>> renderers # May only contain {"en": <function>}
Source code in pipeline/generate_notices.py
get_language_renderer
¶
Get template renderer for given language from provided renderer dict.
Maps Language enum values to their corresponding template rendering functions from a dynamically-built renderer dictionary. This provides a single dispatch point for template selection with runtime-configurable template sources.
Validation Contract: Assumes language is a valid Language enum (validated upstream at CLI entry point via argparse choices, and again by Language.from_string() before calling this function). Checks that language is available in renderers dict; raises with helpful error if template for requested language is not available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
language
|
Language
|
Language enum value (guaranteed to be valid from Language enum). |
required |
renderers
|
dict
|
Mapping of language codes to render_notice functions, built by build_language_renderers(). May only contain subset of all languages. |
required |
Returns:
| Type | Description |
|---|---|
callable
|
Template rendering function for the language. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If requested language template is not available in renderers dict. Provides helpful message listing available languages. |
Examples:
>>> renderers = build_language_renderers(Path("templates"))
>>> renderer = get_language_renderer(Language.ENGLISH, renderers)
>>> # renderer is now the render_notice function from en_template
Source code in pipeline/generate_notices.py
read_artifact
¶
Read and deserialize the preprocessed artifact JSON.
Input Contract: Assumes artifact was created by preprocessing step and contains valid client records. Does not validate client schema; relies on preprocessing to have ensured data quality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the preprocessed artifact JSON file. |
required |
Returns:
| Type | Description |
|---|---|
ArtifactPayload
|
Parsed artifact with clients and metadata. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If artifact file does not exist. |
JSONDecodeError
|
If artifact is not valid JSON. |
KeyError
|
If artifact is missing required fields. |
Source code in pipeline/generate_notices.py
escape_string
¶
Escape special characters in a string for Typst template output.
Module-internal helper for to_typ_value(). Escapes backslashes, quotes, and newlines to ensure the string can be safely embedded in a Typst template.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
String to escape. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Escaped string safe for Typst embedding. |
Source code in pipeline/generate_notices.py
to_typ_value
¶
Convert a Python value to its Typst template representation.
Module-internal helper for building template contexts. Handles strings (with escaping), booleans, None, numbers, sequences (tuples), and mappings (dicts) by converting them to Typst syntax.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
Python value to convert. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Typst-compatible representation of the value. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If value type is not supported. |
Examples:
>>> to_typ_value("hello")
'"hello"'
>>> to_typ_value(True)
'true'
>>> to_typ_value([1, 2, 3])
'(1, 2, 3)'
Source code in pipeline/generate_notices.py
load_and_translate_chart_diseases
¶
Load and translate the chart disease list from configuration.
Loads chart_diseases_header from config/parameters.yaml and translates each disease name to the target language using the diseases_chart translation domain. This ensures chart column headers match the configured set of diseases and are properly localized.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
language
|
str
|
Language code (e.g., "en", "fr"). |
required |
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
List[str]
|
List of translated disease names in order. |
Source code in pipeline/generate_notices.py
build_template_context
¶
Build template context from client data.
Translates disease names in vaccines_due_list and received records to localized display strings using the configured translation files. Also loads and translates the chart disease header list from configuration. Formats the notice date_data_cutoff with locale-aware formatting using Babel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
ClientRecord
|
Client record with all required fields. |
required |
qr_output_dir
|
Path
|
Directory containing QR code PNG files. |
None
|
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, str]
|
Template context with translated disease names and formatted date. |
Source code in pipeline/generate_notices.py
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | |
to_root_relative
¶
Convert absolute path to project-root-relative Typst path reference.
Module-internal helper for template rendering. Converts absolute file paths to paths relative to the project root, formatted for Typst's import resolution. If path is outside project root (e.g., custom assets), returns absolute path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Absolute path to convert. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Path string like "/artifacts/qr_codes/code.png" (relative to project root) or absolute path if outside project root. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If path cannot be resolved (defensive guard, should not occur in practice). |
Source code in pipeline/generate_notices.py
render_notice
¶
render_notice(client, *, output_dir, logo, signature, renderers, qr_output_dir=None, config_path=None)
Render a Typst notice for a single client using provided renderers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
ClientRecord
|
Client record with all required fields |
required |
output_dir
|
Path
|
Output directory (used for path resolution) |
required |
logo
|
Path
|
Path to logo image file |
required |
signature
|
Path
|
Path to signature image file |
required |
renderers
|
dict
|
Language code to render_notice function mapping from build_language_renderers() |
required |
qr_output_dir
|
Path
|
Directory containing QR code PNG files |
None
|
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
str
|
Rendered Typst template content |
Source code in pipeline/generate_notices.py
generate_typst_files
¶
generate_typst_files(payload, output_dir, logo_path, signature_path, template_dir, config_path=None)
Generate Typst template files for all clients in payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
ArtifactPayload
|
Preprocessed client data with metadata |
required |
output_dir
|
Path
|
Directory to write Typst files |
required |
logo_path
|
Path
|
Path to logo image |
required |
signature_path
|
Path
|
Path to signature image |
required |
template_dir
|
Path
|
Directory containing language template modules |
required |
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
List[Path]
|
List of generated .typ file paths |
Source code in pipeline/generate_notices.py
main
¶
Main entry point for Typst notice generation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_path
|
Path
|
Path to the preprocessed JSON artifact. |
required |
output_dir
|
Path
|
Directory to write Typst files. |
required |
logo_path
|
Path
|
Path to the logo image. |
required |
signature_path
|
Path
|
Path to the signature image. |
required |
template_dir
|
Path
|
Directory containing language template modules. |
required |
config_path
|
Path
|
Path to |
None
|
Returns:
| Type | Description |
|---|---|
List[Path]
|
List of generated Typst file paths. |
Source code in pipeline/generate_notices.py
Step 5 — PDF Compilation¶
pipeline.compile_notices
¶
Compile per-client Typst notices into PDFs sequentially.
This lightweight helper keeps the compilation step in Python so future enhancements (parallel workers, structured logging) can be layered on in a follow-up. For now it mirrors the behaviour of the original shell script.
Input Contract:
- Reads Typst template files from output/artifacts/typst/
- Assumes .typ files are valid Typst templates (generated by generate_notices step)
- Assumes typst compiler binary is available (configured in parameters.yaml)
Output Contract:
- Writes compiled PDF files to output/pdf_individual/
- All .typ files must compile successfully (critical step; fail-fast)
- Filenames match input .typ files with .pdf extension
Error Handling:
- Typst compilation errors raise immediately (subprocess check=True)
- Missing .typ files raise immediately (fail-fast)
- No per-file recovery; all-or-nothing output (critical feature)
Validation Contract:
What this module validates:
- All .typ files in artifact/typst/ can be discovered
- Typst compiler exists at configured path (or default 'typst')
- Typst compiler exits with success (exit code 0)
- Font paths are accessible (if configured)
What this module assumes (validated upstream):
- .typ files are valid Typst templates (validated by generate_notices step)
- Output directory can be created (general I/O)
- typst.bin and typst.font_path config keys are valid (from load_config)
Note: This is a critical step. Compilation failure halts pipeline (fail-fast).
discover_typst_files
¶
Discover all Typst template files in the artifact directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_dir
|
Path
|
Directory containing pipeline artifacts (should have a 'typst' subdirectory). |
required |
Returns:
| Type | Description |
|---|---|
list[Path]
|
Sorted list of Typst (.typ) file paths, or empty list if directory doesn't exist. |
Source code in pipeline/compile_notices.py
compile_file
¶
Compile a single Typst template file to PDF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
typ_path
|
Path
|
Path to the .typ Typst template file to compile. |
required |
pdf_dir
|
Path
|
Directory where the compiled PDF should be written. |
required |
typst_bin
|
str
|
Path or name of the typst binary to use for compilation. |
required |
font_path
|
Path | None
|
Optional path to directory containing custom fonts. |
required |
root_dir
|
Path
|
Root directory for relative path resolution in Typst compilation. This should be the template directory containing conf.typ and assets/. |
required |
verbose
|
bool
|
If True, print compilation status message. |
required |
Source code in pipeline/compile_notices.py
compile_typst_files
¶
Compile all discovered Typst template files sequentially to PDFs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_dir
|
Path
|
Directory containing Typst artifacts. |
required |
pdf_dir
|
Path
|
Output directory for compiled PDFs. |
required |
typst_bin
|
str
|
Path or name of the typst binary. |
required |
font_path
|
Path | None
|
Optional custom fonts directory. |
required |
root_dir
|
Path
|
Root directory for relative path resolution. Should be the template directory containing conf.typ and assets/. |
required |
verbose
|
bool
|
If True, print per-file compilation status. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of files successfully compiled. |
Source code in pipeline/compile_notices.py
compile_with_config
¶
Compile Typst files using configuration from parameters.yaml.
Reads typst configuration (binary path, font path) from parameters.yaml and compiles all Typst files in the artifact directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_dir
|
Path
|
Directory containing Typst template files |
required |
output_dir
|
Path
|
Directory where compiled PDFs will be written |
required |
config_path
|
Path
|
Path to parameters.yaml. If not provided, uses default location. |
None
|
template_dir
|
Path
|
Template directory for dynamic template loading. Typst compilation always uses PROJECT_ROOT as --root to find both templates and output artifacts. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of files compiled. |
Source code in pipeline/compile_notices.py
main
¶
Main entry point for Typst compilation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact_dir
|
Path
|
Directory containing Typst artifacts. |
required |
output_dir
|
Path
|
Directory for output PDFs. |
required |
config_path
|
Path
|
Path to parameters.yaml configuration file. |
None
|
template_dir
|
Path
|
Template directory containing conf.typ and assets/. Used as Typst --root. If not provided, defaults to project root. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of files compiled. |
Source code in pipeline/compile_notices.py
Step 6 — PDF Validation¶
pipeline.validate_pdfs
¶
Validate compiled PDFs for layout, structure, and quality issues.
Performs comprehensive validation of compiled PDF files including page counts, layout checks (signature placement), and structural integrity. Outputs validation results to JSON metadata for downstream processing and optional console warnings.
Input Contract:
- Reads PDF files from output/pdf_individual/ directory
- Assumes PDFs are valid (created by compilation step)
- Assumes each PDF corresponds to one client notice
Output Contract:
- Writes validation results to JSON: output/metadata/{language}validation.json
- Records per-PDF validations: page counts, layout warnings, structural issues
- Aggregate statistics: total PDFs, warnings by type, pass/fail counts
- Optional console output (controlled by config: pdf_validation.print_warnings)
Error Handling:
- Invalid/corrupt PDFs raise immediately (fail-fast; quality validation step)
- Missing PDF files raise immediately (infrastructure error)
- Layout warnings are non-fatal (logged but don't halt pipeline)
- All PDFs must be readable; validation results may contain warnings (quality step)
Validation Contract:
What this module validates:
- PDF files are readable and structurally valid (uses PdfReader)
- Page count statistics and distribution
- Layout markers (signature block placement using MARK_END_SIGNATURE_BLOCK)
- Expected vs actual page counts (configurable tolerance)
What this module assumes (validated upstream):
- PDF files exist and are complete (created by compile step)
- PDF filenames match expected pattern (from notice generation)
- Output metadata directory can be created (general I/O)
Note: This is a validation/QA step. Structural PDF errors halt pipeline (fail-fast), but layout warnings are non-fatal and logged for review.
ValidationResult
dataclass
¶
Result of validating a single PDF file.
Attributes:
| Name | Type | Description |
|---|---|---|
filename |
str
|
Name of the PDF file |
warnings |
List[str]
|
List of validation warnings (layout issues, unexpected page counts, etc.) |
passed |
bool
|
True if no warnings, False otherwise |
measurements |
dict[str, int | float | str]
|
Actual measurements extracted from PDF with proper types:
|
Source code in pipeline/validate_pdfs.py
RuleResult
dataclass
¶
Result of a single validation rule across all PDFs.
Attributes:
| Name | Type | Description |
|---|---|---|
rule_name |
str
|
Name of the validation rule |
severity |
str
|
Rule severity: "disabled", "warn", or "error" |
passed_count |
int
|
Number of PDFs that passed this rule |
failed_count |
int
|
Number of PDFs that failed this rule |
Source code in pipeline/validate_pdfs.py
ValidationSummary
dataclass
¶
Aggregate validation results for all PDFs.
Attributes:
| Name | Type | Description |
|---|---|---|
language |
str | None
|
Language code if filtered (e.g., 'en' or 'fr') |
total_pdfs |
int
|
Total number of PDFs validated |
passed_count |
int
|
Number of PDFs with no warnings |
warning_count |
int
|
Number of PDFs with warnings |
page_count_distribution |
dict[int, int]
|
Distribution of page counts (pages -> count) |
warning_types |
dict[str, int]
|
Count of warnings by type/category |
rule_results |
List[RuleResult]
|
Per-rule validation statistics |
results |
List[ValidationResult]
|
Per-file validation results |
Source code in pipeline/validate_pdfs.py
discover_pdfs
¶
Discover all PDF files at the given target path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Path
|
Either a directory containing PDFs or a single PDF file. |
required |
Returns:
| Type | Description |
|---|---|
List[Path]
|
Sorted list of PDF file paths. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If target is neither a PDF file nor a directory containing PDFs. |
Source code in pipeline/validate_pdfs.py
filter_by_language
¶
Filter PDF files by language prefix in filename.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
files
|
List[Path]
|
PDF file paths to filter. |
required |
language
|
str | None
|
Language code to filter by (e.g., 'en' or 'fr'). If None, returns all files. |
required |
Returns:
| Type | Description |
|---|---|
List[Path]
|
Filtered list of PDF paths, or all files if language is None. |
Source code in pipeline/validate_pdfs.py
find_client_id_in_text
¶
Find a 10-digit client ID in extracted PDF page text.
Searches for any 10-digit number; assumes the first match is the client ID. May be preceded by "Client ID: " or "Identifiant du client: " (optional).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
page_text
|
str
|
Extracted text from a PDF page. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
10-digit client ID if found, None otherwise. |
Source code in pipeline/validate_pdfs.py
extract_measurements_from_markers
¶
Extract dimension measurements from invisible text markers.
Typst templates embed invisible markers with measurements like: MEASURE_CONTACT_HEIGHT:123.45
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
page_text
|
str
|
Extracted text from a PDF page. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary mapping dimension names to values in points. Example: {"measure_contact_height": 123.45} |
Source code in pipeline/validate_pdfs.py
validate_pdf_layout
¶
Check PDF for layout issues using invisible markers and metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pdf_path
|
Path
|
Path to the PDF file being validated. |
required |
reader
|
PdfReader
|
Opened PDF reader instance. |
required |
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). |
required |
client_id_map
|
dict[str, str]
|
Mapping of PDF filename (without path) to expected client ID. If provided, client_id_presence validation uses this as source of truth. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[List[str], dict[str, float]]
|
Tuple of (warning messages, actual measurements). Measurements include signature_page, contact_height_inches, etc. |
Source code in pipeline/validate_pdfs.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |
validate_pdf_structure
¶
Validate a single PDF file for structure and layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pdf_path
|
Path
|
Path to the PDF file to validate. |
required |
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). |
None
|
client_id_map
|
dict[str, str]
|
Mapping of PDF filename to expected client ID (from preprocessed_clients.json). |
None
|
Returns:
| Type | Description |
|---|---|
ValidationResult
|
Validation result with measurements, warnings, and pass/fail status. |
Raises:
| Type | Description |
|---|---|
Exception
|
If PDF cannot be read (structural corruption). |
Source code in pipeline/validate_pdfs.py
compute_rule_results
¶
Compute per-rule pass/fail statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
results
|
List[ValidationResult]
|
Validation results for all PDFs. |
required |
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). |
required |
Returns:
| Type | Description |
|---|---|
List[RuleResult]
|
Per-rule statistics with pass/fail counts. |
Source code in pipeline/validate_pdfs.py
validate_pdfs
¶
Validate all PDF files and generate summary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
files
|
List[Path]
|
PDF file paths to validate. |
required |
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). |
None
|
client_id_map
|
dict[str, str]
|
Mapping of PDF filename to expected client ID (from preprocessed_clients.json). |
None
|
Returns:
| Type | Description |
|---|---|
ValidationSummary
|
Aggregate validation results with statistics and per-file details. |
Source code in pipeline/validate_pdfs.py
print_validation_summary
¶
Print human-readable validation summary to console.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
summary
|
ValidationSummary
|
Validation summary to print. |
required |
validation_json_path
|
Path
|
Path to validation JSON for reference in output. |
None
|
Source code in pipeline/validate_pdfs.py
write_validation_json
¶
Write validation summary to JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
summary
|
ValidationSummary
|
Validation summary to serialize. |
required |
output_path
|
Path
|
Path to output JSON file. |
required |
Source code in pipeline/validate_pdfs.py
check_for_errors
¶
Check if any validation rules are set to 'error' and have failures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
summary
|
ValidationSummary
|
Validation summary with warning counts by type. |
required |
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). |
required |
Returns:
| Type | Description |
|---|---|
List[str]
|
List of error messages for rules that failed with severity 'error'. |
Source code in pipeline/validate_pdfs.py
main
¶
main(target, language=None, enabled_rules=None, json_output=None, client_id_map=None, config_dir=None)
Main entry point for PDF validation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Path
|
PDF file or directory containing PDFs. |
required |
language
|
str
|
Optional language prefix to filter PDF filenames (e.g., 'en'). |
None
|
enabled_rules
|
dict[str, str]
|
Validation rules configuration (rule_name -> "disabled"/"warn"/"error"). If not provided and config_dir is given, loads from config_dir/parameters.yaml. |
None
|
json_output
|
Path
|
Optional path to write validation summary as JSON. |
None
|
client_id_map
|
dict[str, str]
|
Mapping of PDF filename to expected client ID (from preprocessed_clients.json). |
None
|
config_dir
|
Path
|
Path to config directory containing parameters.yaml. Used to load enabled_rules if not explicitly provided. If not provided, uses default location (config/parameters.yaml in project root). |
None
|
Returns:
| Type | Description |
|---|---|
ValidationSummary
|
Validation summary with all results and statistics. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If any validation rule with severity 'error' fails. |
Source code in pipeline/validate_pdfs.py
Step 7 — PDF Encryption¶
pipeline.encrypt_notice
¶
Encryption module for immunization PDF notices.
This module provides functions to encrypt PDF notices using client metadata. It's designed to be integrated into the pipeline as an optional step.
Passwords are generated per-client per-PDF using templates defined in config/parameters.yaml under encryption.password.template. Templates support placeholders like {client_id}, {date_of_birth_iso}, {date_of_birth_iso_compact}, {first_name}, {last_name}, {school}, {postal_code}, etc.
Input Contract:
- Reads PDF files from disk and client metadata from JSON
- Assumes PDF and JSON files exist before encryption
- Assumes JSON contains valid client metadata with required fields for password template
Output Contract:
- Writes encrypted PDFs to disk with "_encrypted" suffix
- Unencrypted originals are preserved (deleted during cleanup step if configured)
- Per-PDF failures are logged and skipped (optional feature; some PDFs may not be encrypted)
- Pipeline completes even if some PDFs fail to encrypt
Error Handling:
- Infrastructure errors (missing PDF/JSON files) raise immediately (fail-fast)
- Configuration errors (invalid password template) raise immediately (fail-fast)
- Per-PDF failures (encryption error, invalid template data) are logged and skipped
- This strategy allows partial success; users are notified with summary of results
- Per-PDF recovery is intentional for optional step; allows users to still get output
load_encryption_config
¶
Load and cache encryption configuration from parameters.yaml.
Module-internal helper. Configuration is loaded once and cached globally for subsequent function calls. This avoids repeated file I/O when generating passwords for multiple PDFs.
Returns:
| Type | Description |
|---|---|
dict
|
Encryption configuration dict (typically contains 'password' key with 'template' sub-key), or empty dict if config file not found. |
Source code in pipeline/encrypt_notice.py
get_encryption_config
¶
Get the encryption configuration from parameters.yaml.
Returns:
| Type | Description |
|---|---|
dict
|
Cached encryption configuration. |
encrypt_pdf
¶
Encrypt a PDF with a password derived from client context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
Path to the PDF file to encrypt. |
required |
context
|
dict
|
Template context dict with client metadata (from build_client_context). Must contain fields referenced in the password template. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Path to the encrypted PDF file with _encrypted suffix. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If password template references missing fields or is invalid. |
Source code in pipeline/encrypt_notice.py
load_notice_metadata
¶
Load client data dict and context from JSON notice metadata.
Module-internal helper for encrypt_notice(). Loads the JSON, extracts the client data dict, builds the templating context, and returns both.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
json_path
|
Path
|
Path to JSON metadata file. |
required |
Returns:
| Type | Description |
|---|---|
tuple
|
(client_dict: dict, context: dict) for password generation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If JSON is invalid or has unexpected structure. |
Source code in pipeline/encrypt_notice.py
encrypt_notice
¶
Encrypt a PDF notice using client data from the JSON file.
Returns the path to the encrypted PDF with _encrypted suffix. If the encrypted version already exists and is newer than the source, returns the existing file without re-encrypting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
json_path
|
Path
|
Path to the JSON file containing client metadata |
required |
pdf_path
|
Path
|
Path to the PDF file to encrypt |
required |
language
|
str
|
ISO 639-1 language code ('en' for English, 'fr' for French) |
required |
Returns:
| Type | Description |
|---|---|
path
|
Path to the encrypted PDF file |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If JSON or PDF file not found |
ValueError
|
If JSON is invalid |
Source code in pipeline/encrypt_notice.py
encrypt_pdfs_in_directory
¶
Encrypt all PDF notices in a directory using a combined JSON metadata file.
The JSON file should contain a dict where keys are client identifiers and values contain client metadata with DOB information.
PDFs are encrypted in-place with the _encrypted suffix added to filename.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pdf_directory
|
str
|
Directory containing PDF files to encrypt |
required |
json_file
|
Path
|
Path to the combined JSON file with all client metadata |
required |
language
|
str
|
ISO 639-1 language code ('en' for English, 'fr' for French) |
required |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If PDF directory or JSON file don't exist |
Source code in pipeline/encrypt_notice.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
Step 8 — PDF Bundling¶
pipeline.bundle_pdfs
¶
Bundle per-client PDFs into combined files with manifests.
This module combines individual per-client PDFs into bundled files with accompanying manifest records. It can be invoked as a CLI tool or imported for unit testing. Bundling supports three modes:
- Size-based (default): bundle the clients into fixed-size groups, i.e., 100 per bundle.
- School-based: group the clients by school code then bundle the clients into fixed-sized groups
- Board-based: group the clients by board code then bundle the clients into fixed-sized groups
Each bundle produces a merged PDF inside output/pdf_combined and a manifest JSON
record inside output/metadata that captures critical metadata for audits.
Input Contract:
- Reads individual PDF files from output/pdf_individual/
- Reads client metadata from preprocessed artifact JSON
- Assumes bundle_size > 0 in config (bundling is optional; disabled when bundle_size=0)
Output Contract:
- Writes merged PDF files to output/pdf_combined/
- Writes bundle manifest JSON to output/metadata/
- Returns list of created bundle files
Error Handling:
- Configuration errors (invalid bundle_size, group_by) raise immediately (infrastructure)
- Per-bundle errors (PDF merge failure) log and continue (optional feature)
- Pipeline completes even if some bundles fail to create (optional step)
Validation Contract:
What this module validates:
- Bundle size is positive (bundle_size > 0)
- Group-by strategy is valid (size, school, board, or None)
- PDF files can be discovered and merged
- Manifest records have required metadata
What this module assumes (validated upstream):
- PDF files are valid and readable (validated by count_pdfs step)
- Client metadata in artifact is complete (validated by preprocessing step)
- Output directory can be created (general I/O)
Note: This is an optional step. Per-bundle errors are logged but don't halt pipeline.
BundleConfig
dataclass
¶
Configuration for PDF bundling operation.
Attributes:
| Name | Type | Description |
|---|---|---|
output_dir |
Path
|
Root output directory containing pipeline artifacts |
language |
str
|
Language code ('en' or 'fr') |
bundle_size |
int
|
Maximum number of clients per bundle (0 disables bundling) |
bundle_strategy |
BundleStrategy
|
Strategy for grouping PDFs into bundles |
run_id |
str
|
Pipeline run identifier |
Source code in pipeline/bundle_pdfs.py
BundlePlan
dataclass
¶
Plan for a single bundle of PDFs.
Attributes:
| Name | Type | Description |
|---|---|---|
bundle_type |
BundleType
|
Type/strategy used for this bundle |
bundle_identifier |
str | None
|
School or board code if bundle was grouped, None for size-based |
bundle_number |
int
|
Sequential bundle number |
total_bundles |
int
|
Total number of bundles in this operation |
clients |
List[PdfRecord]
|
List of PDFs and metadata in this bundle |
Source code in pipeline/bundle_pdfs.py
BundleResult
dataclass
¶
Result of a completed bundle operation.
Attributes:
| Name | Type | Description |
|---|---|---|
pdf_path |
Path
|
Path to the merged PDF file |
manifest_path |
Path
|
Path to the JSON manifest file |
bundle_plan |
BundlePlan
|
The plan used to create this bundle |
Source code in pipeline/bundle_pdfs.py
bundle_pdfs_with_config
¶
Bundle PDFs using configuration from parameters.yaml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory containing pipeline artifacts. |
required |
language
|
str
|
Language prefix to bundle ('en' or 'fr'). |
required |
run_id
|
str
|
Pipeline run identifier to locate preprocessing artifacts. |
required |
config_path
|
Path
|
Path to parameters.yaml. If not provided, uses default location. |
None
|
Returns:
| Type | Description |
|---|---|
List[BundleResult]
|
List of bundle results created. |
Source code in pipeline/bundle_pdfs.py
main
¶
Main entry point for PDF bundling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory containing pipeline artifacts. |
required |
language
|
str
|
Language prefix to bundle ('en' or 'fr'). |
required |
run_id
|
str
|
Pipeline run identifier. |
required |
config_path
|
Path
|
Path to parameters.yaml configuration file. |
None
|
Returns:
| Type | Description |
|---|---|
List[BundleResult]
|
List of bundles created. |
Source code in pipeline/bundle_pdfs.py
chunked
¶
Split an iterable into fixed-size chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iterable
|
Sequence[T]
|
Sequence to chunk. |
required |
size
|
int
|
Maximum number of items per chunk (must be positive). |
required |
Returns:
| Type | Description |
|---|---|
Iterator[List[T]]
|
Iterator yielding lists of up to |
Raises:
| Type | Description |
|---|---|
ValueError
|
If size is not positive. |
Examples:
Source code in pipeline/bundle_pdfs.py
slugify
¶
Convert a string to a URL-safe slug format.
Converts spaces and special characters to underscores, removes consecutive underscores, and lowercases the result. Used for generating bundle filenames from school/board names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
String to slugify (e.g., school or board name). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Slugified string, or 'unknown' if value is empty/whitespace. |
Examples:
>>> slugify("Lincoln High School")
'lincoln_high_school'
>>> slugify("Bd. Métropolitain")
'bd_m_tropolitain'
Source code in pipeline/bundle_pdfs.py
load_artifact
¶
Load the preprocessed artifact JSON from the output directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory containing artifacts. |
required |
run_id
|
str
|
Pipeline run identifier matching the artifact filename. |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, object]
|
Parsed preprocessed artifact with clients and metadata. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the preprocessed artifact file does not exist. |
Source code in pipeline/bundle_pdfs.py
build_client_lookup
¶
Build a lookup table from artifact clients dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact
|
Dict[str, object]
|
Preprocessed artifact dictionary |
required |
Returns:
| Type | Description |
|---|---|
Dict[tuple[str, str], dict]
|
Lookup table keyed by (sequence, client_id) |
Source code in pipeline/bundle_pdfs.py
discover_pdfs
¶
Discover all individual PDF files for a given language.
Discovers non-encrypted PDF files only. Encrypted PDFs (with _encrypted suffix) are excluded from bundling since bundling operates on the original unencrypted PDFs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory. |
required |
language
|
str
|
Language prefix to match (e.g., 'en' or 'fr'). |
required |
Returns:
| Type | Description |
|---|---|
List[Path]
|
Sorted list of non-encrypted PDF file paths matching the language, or empty list if pdf_individual directory doesn't exist. |
Source code in pipeline/bundle_pdfs.py
build_pdf_records
¶
Build a list of PdfRecord objects from discovered PDF files.
Discovers PDFs, extracts metadata from filenames, looks up client data, and constructs PdfRecord objects with page counts and client metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory. |
required |
language
|
str
|
Language prefix to filter PDFs. |
required |
clients
|
Dict[tuple[str, str], dict]
|
Lookup table of client data keyed by (sequence, client_id). |
required |
Returns:
| Type | Description |
|---|---|
List[PdfRecord]
|
Sorted list of PdfRecord objects by sequence. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If a PDF filename has no matching client in the lookup table. |
Source code in pipeline/bundle_pdfs.py
plan_bundles
¶
Plan how to group PDFs into bundles based on configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
BundleConfig
|
Bundling configuration including strategy and bundle size |
required |
records
|
List[PdfRecord]
|
List of PDF records to bundle |
required |
log_path
|
Path
|
Path to logging file |
required |
Returns:
| Type | Description |
|---|---|
List[BundlePlan]
|
List of bundle plans |
Source code in pipeline/bundle_pdfs.py
relative
¶
Convert path to string relative to root directory.
Module-internal helper for manifest generation. Creates relative path strings for storing in JSON manifests, making paths portable across different base directories.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Absolute path to convert. |
required |
root
|
Path
|
Root directory to compute relative path from. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Relative path as POSIX string. |
Source code in pipeline/bundle_pdfs.py
Step 9 — Cleanup¶
pipeline.cleanup
¶
Cleanup module for Step 9: removing intermediate pipeline artifacts.
This step removes intermediate files generated during the pipeline run to reduce storage footprint. Configuration is read from parameters.yaml under pipeline.after_run.
This is distinct from Step 1 (prepare_output), which uses pipeline.before_run.clear_output_directory to clean up old pipeline runs at startup while preserving logs.
Step 1 Configuration (pipeline.before_run in parameters.yaml):
- clear_output_directory: when true, removes all output except logs before starting a new run
Step 9 Configuration (pipeline.after_run in parameters.yaml):
- remove_artifacts: when true, removes output/artifacts directory
- remove_unencrypted_pdfs: when true and (encryption OR batching) is enabled, removes non-encrypted PDFs from pdf_individual/ after encryption completes. If both encryption and batching are disabled, individual non-encrypted PDFs are assumed to be final output and are preserved.
Input Contract:
- Reads configuration from parameters.yaml (pipeline.after_run section)
- Assumes output directory structure exists (may be partially populated)
- Assumes encryption.enabled and bundling.bundle_size from parameters.yaml
Output Contract:
- Removes specified directories from output_dir
- Removes unencrypted PDFs if conditions are met:
- remove_unencrypted_pdfs=true AND (encryption enabled OR batching enabled)
- Does not modify final PDF outputs (unless configured to do so)
- Does not halt pipeline if cleanup fails
Error Handling:
- File deletion errors are logged and continue (optional step)
- Missing directories/files don't cause errors (idempotent)
- Pipeline completes even if cleanup partially fails (utility step)
Validation Contract:
What this module validates:
- Output directory exists and is writable
- Directory/file paths can be safely deleted (exist check before delete)
- Configuration values are sensible boolean types and integers
What this module assumes (validated upstream):
- Configuration keys are valid and well-formed
- Output directory structure is correct (created by prior steps)
Note: This is a utility/cleanup step. Failures don't halt pipeline.
safe_delete
¶
Safely delete a file or directory if it exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
File or directory to delete. |
required |
cleanup_with_config
¶
Perform cleanup using configuration from parameters.yaml.
Reads Step 9 (after_run) cleanup configuration from parameters.yaml. This is separate from Step 1's before_run.clear_output_directory setting, which cleans old runs at pipeline start (preserving logs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory containing generated files. |
required |
config_path
|
Path
|
Path to parameters.yaml. If not provided, uses default location. |
None
|
Source code in pipeline/cleanup.py
main
¶
Main entry point for cleanup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
Path
|
Root output directory to clean. |
required |
config_path
|
Path
|
Path to parameters.yaml configuration file. |
None
|
Source code in pipeline/cleanup.py
Utilities¶
pipeline.utils
¶
Utility functions for immunization pipeline processing.
Provides template rendering utilities and context building functions shared across pipeline steps, particularly for QR code generation, PDF encryption, and template variable substitution. All functions handle string conversions and safe formatting of client data for use in downstream templates.
string_or_empty
¶
Safely convert value to string, returning empty string for None/NaN.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
Value to convert (may be None, empty string, or any type) |
required |
Returns:
| Type | Description |
|---|---|
str
|
Stringified value or empty string for None/NaN values |
Source code in pipeline/utils.py
extract_template_fields
¶
Extract placeholder names from a format string template.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
str
|
Format string like "https://example.com?id={client_id}&dob={date_of_birth_iso}" |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of placeholder names found in template |
Raises:
| Type | Description |
|---|---|
ValueError
|
If template contains invalid format string syntax |
Examples:
Source code in pipeline/utils.py
validate_and_format_template
¶
Format template and validate placeholders against allowed set.
Ensures that:
- All placeholders in template exist in context
- All placeholders are in the allowed_fields set (if provided)
- Template is successfully rendered
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
str
|
Format string template with placeholders |
required |
context
|
dict[str, str]
|
Context dict with placeholder values |
required |
allowed_fields
|
set[str] | None
|
Set of allowed placeholder names. If None, allows any placeholder that exists in context. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
Rendered template |
Raises:
| Type | Description |
|---|---|
KeyError
|
If template contains placeholders not in context |
ValueError
|
If template contains disallowed placeholders (when allowed_fields provided) |
Examples:
>>> ctx = {"client_id": "12345", "date_of_birth_iso": "2015-03-15"}
>>> validate_and_format_template(
... "{client_id}_{date_of_birth_iso}",
... ctx,
... allowed_fields={"client_id", "date_of_birth_iso"}
... )
'12345_2015-03-15'
Source code in pipeline/utils.py
build_client_context
¶
Build template context dict from client metadata for templating.
Extracts and formats all available client fields for use in templates, supporting both QR code payloads and PDF encryption passwords.
Accepts either a dict (from JSON) or a ClientRecord dataclass instance. Both provide the same fields; the function handles both transparently.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_data
|
dict or ClientRecord
|
Client data as either: - A dict (from preprocessed artifact JSON) with nested structure: { "client_id": "...", "person": {"first_name": "...", "last_name": "...", "date_of_birth_iso": "..."}, "school": {"name": "..."}, "board": {"name": "..."}, "contact": {"postal_code": "...", "city": "...", ...} } - A ClientRecord dataclass instance with same nested fields. |
required |
language
|
str
|
ISO 639-1 language code ('en' or 'fr'). When omitted, falls back to the client's own language field if present, otherwise an empty string. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Context dict with keys: - client_id - first_name, last_name, name - date_of_birth (display format) - date_of_birth_iso (YYYY-MM-DD) - date_of_birth_iso_compact (YYYYMMDD) - school, board - postal_code, city, province, street_address - language_code ('en' or 'fr') |
Examples:
>>> client_dict = {
... "client_id": "12345",
... "person": {"first_name": "John", "last_name": "Doe", "date_of_birth_iso": "2015-03-15"},
... "school": {"name": "Lincoln School"},
... "contact": {"postal_code": "M5V 3A8"}
... }
>>> ctx = build_client_context(client_dict)
>>> ctx["client_id"]
'12345'
>>> ctx["first_name"]
'John'
Source code in pipeline/utils.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | |
deserialize_client_record
¶
Deserialize a dict to a ClientRecord dataclass instance.
Constructs a ClientRecord from a dict (typically from JSON), handling all required and optional fields uniformly. This is the canonical deserialization utility shared across modules for type safety and reduced code duplication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_dict
|
dict
|
Client dict with structure: { "sequence": "...", "client_id": "...", "language": "...", "person": {...}, "school": {...}, "board": {...}, "contact": {...}, "vaccines_due": "...", "vaccines_due_list": [...], "received": [...], "metadata": {...}, "qr": {...} (optional) } |
required |
Returns:
| Type | Description |
|---|---|
ClientRecord
|
Constructed dataclass instance. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If dict cannot be converted (missing required fields or type mismatch). |
Source code in pipeline/utils.py
Translation Helpers¶
pipeline.translation_helpers
¶
Translation and normalization helpers for disease names.
Provides utilities to normalize input disease names to canonical English forms and translate canonical names to localized display strings for multiple domains (overdue list, immunization history chart).
Contracts:
- Canonical disease names are English strings from vaccine_reference.json (e.g., "Diphtheria", "Polio")
- Normalization maps raw input strings to canonical names using config/disease_normalization.json
- Translation maps canonical names to localized display strings using config/translations/*.json
- Missing translations fall back leniently (return canonical name + log warning) unless strict=True
- Missing normalization keys return the input unchanged; they may map via disease_map.json later
load_normalization
¶
Load disease normalization map from config.
Returns:
| Type | Description |
|---|---|
Dict[str, str]
|
Map from raw disease strings to canonical disease names. Returns empty dict if file does not exist. |
Source code in pipeline/translation_helpers.py
load_translations
¶
Load translation map for a domain and language from config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
domain
|
Literal['diseases_overdue', 'diseases_chart']
|
Display domain (overdue list or chart). |
required |
lang
|
str
|
Language code (e.g., "en", "fr"). |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, str]
|
Map from canonical disease names to localized display strings. Returns empty dict if file does not exist. |
Source code in pipeline/translation_helpers.py
normalize_disease
¶
Normalize a raw disease string to canonical form.
Applies the normalization map from config/disease_normalization.json. If the token is not in the normalization map, returns it unchanged (it may be normalized via disease_map.json later in preprocessing).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token
|
str
|
Raw disease string from input data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Canonical disease name or unchanged token if not found. |
Examples:
>>> normalize_disease("Poliomyelitis")
"Polio"
>>> normalize_disease("Unknown Disease")
"Unknown Disease"
Source code in pipeline/translation_helpers.py
display_label
¶
Translate a canonical disease name to a localized display label.
Loads translations from config/translations/{domain}.{lang}.json.
Falls back leniently to the canonical key if missing (unless strict=True),
and logs a single warning per unique missing key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
domain
|
Literal['diseases_overdue', 'diseases_chart']
|
Display domain (overdue list or chart). |
required |
key
|
str
|
Canonical disease name (English). |
required |
lang
|
str
|
Language code (e.g., "en", "fr"). |
required |
strict
|
bool
|
If True, raise KeyError on missing translation. If False (default), return the canonical key and log a warning. |
False
|
Returns:
| Type | Description |
|---|---|
str
|
Localized display label or canonical key (if not strict and missing). |
Raises:
| Type | Description |
|---|---|
KeyError
|
If strict=True and translation is missing. |
Examples:
>>> display_label("diseases_overdue", "Polio", "en")
"Polio"
>>> display_label("diseases_overdue", "Polio", "fr")
"Poliomyélite"
Source code in pipeline/translation_helpers.py
clear_caches
¶
Clear all translation and normalization caches.
Useful for testing or reloading configs during runtime.
Source code in pipeline/translation_helpers.py
PHIX School Validation¶
pipeline.validate_phix
¶
Validate school/daycare names in the input DataFrame against the PHIX mapping file.
The mapping file is produced by a separate script and contains a PHU-keyed dict of normalized school names → PHIX facility IDs.
Match categories
exact: normalized name found in the target PHU's mapping AND facility ID matches
inexact: name found but no ID provided for comparison (name_only), name found but provided ID differs from mapping (id_mismatch),
or ID found under a different name (id_only)
no_match: neither name nor ID found for the target PHU
Usage (called from preprocess.run_phix_validation)
df, warnings = validate_schools(
df=df,
mapping_path=Path("config/phix_mapping.json"),
target_phu="Wellington Dufferin Guelph Public Health",
output_dir=output_dir,
)
PHIXMatchResult
dataclass
¶
Outcome of matching one input school entry against the PHIX mapping.
Source code in pipeline/validate_phix.py
normalize_school_name
¶
Uppercase and collapse whitespace.
Must produce the same keys as build_phix_mapping.py so lookups match.
parse_input_entry
¶
Split a raw input cell into (school_name, facility_id).
Input data sometimes carries the facility ID appended as
"SCHOOL NAME - 019186". We split on the rightmost " - "
so names that themselves contain dashes are handled correctly.
Returns (entry, "") when no separator is found.
Source code in pipeline/validate_phix.py
load_mapping
¶
Load phix_mapping.json and return lookup dicts for target_phu.
The by_id reverse lookup is built here from the flat name→id mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping_path
|
Path
|
Path to the JSON file produced by |
required |
target_phu
|
str
|
Exact PHU key string as it appears in the JSON (e.g.
|
required |
Returns:
| Name | Type | Description |
|---|---|---|
name_to_id |
dict
|
|
id_to_name |
dict
|
|
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
When the mapping file does not exist. |
KeyError
|
When target_phu is not present in the mapping, with available PHUs listed in the message. |
Source code in pipeline/validate_phix.py
classify_match
¶
Classify one input entry against the PHU's school/ID mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_name
|
str
|
Raw school name from the input (before normalisation). |
required |
input_id
|
str
|
Facility ID extracted from the input cell, or |
required |
name_to_id
|
dict[str, str]
|
|
required |
id_to_name
|
dict[str, str]
|
|
required |
Source code in pipeline/validate_phix.py
validate_schools
¶
validate_schools(df, mapping_path, target_phu, output_dir, school_column='SCHOOL_NAME', unmatched_behavior='warn', column_prefix='PHIX_')
Validate school names in df against the PHIX mapping for target_phu.
Adds four columns to the DataFrame (with column_prefix):
{prefix}FACILITY_ID: Matched facility ID, or""{prefix}MATCH_TYPE:"exact"|"inexact"|"no_match"{prefix}MATCHED_NAME: Canonical name from mapping, or""{prefix}MATCHED_PHU: target_phu for matched rows,""otherwise
Writes three CSV files to output_dir:
phix_exact.csvphix_inexact.csvphix_no_match.csv
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Input DataFrame (not mutated; a copy is returned). |
required |
mapping_path
|
Path
|
Path to |
required |
target_phu
|
str
|
Exact PHU key in the mapping JSON. |
required |
output_dir
|
Path
|
Directory for CSV output files. |
required |
school_column
|
str
|
Column in df containing school/daycare names. |
'SCHOOL_NAME'
|
unmatched_behavior
|
str
|
|
'warn'
|
column_prefix
|
str
|
Prefix applied to all output column names. |
'PHIX_'
|
Returns:
| Type | Description |
|---|---|
tuple[DataFrame, list[str]]
|
Enriched DataFrame and a list of human-readable warning strings. |
Source code in pipeline/validate_phix.py
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | |