Interpretation Algorithms¶
Interpretation algorithms extend rule evaluation with additional logic. They are configured per project in the metadata JSON at respro init time and stored in the project database.
Overview¶
ResPro evaluates resistance at multiple levels:
- Single rules — each row in the primary rules TSV is an atomic mutation-to-interpretation mapping.
- Combination rules — boolean formulas over atomic
member_idvalues from grouped rules. - Interpretation algorithms — project-level logic that aggregates matched rules into per-drug results.
Rule nomenclature basics¶
Rules are amino-acid-centric. A notation such as A123V means reference amino acid A at position 123 changes to V.
| Type | Example | Meaning |
|---|---|---|
| Substitution | A123V | Position 123 changed from A to V. |
| Anchored deletion | VG215V | The G after position 215 is deleted. |
| Anchored insertion | V215VG | Insertion of G after the V at position 215. |
| Frameshift | L201LfsX | Reading-frame shift after the L at position 201. |
| Phenotype | sensitive / resistant | Captures in-vitro susceptibility interpretation. |
| Clinical phenotype | sensitive / resistant | Captures treatment-oriented interpretation where available. |
See Rules TSV Format for the full mutation normalization reference.
Combination rules¶
Combination rules allow interpretation based on boolean logic across multiple mutation members. They are defined separately from single rules (in the --formula-rules TSV) and evaluated with operators AND, OR, NOT, and XOR.
Combination members are evaluated based on a fixed member allele-frequency threshold (AF > 0.75 by default).
AND
All specified mutations must be present.
A AND B
OR
At least one specified mutation must be present.
A OR B
NOT
The specified mutation must not be present.
A AND NOT B
XOR
Exactly one specified mutation must be present.
A XOR B
Single rules represent one mutation-to-interpretation mapping. Combination rules fire only when their formula conditions are satisfied. Parentheses are supported and should be used whenever precedence should be explicit.
Interpretation algorithms¶
effect_as_resistant¶
Defines report-only metadata interpretation for observed high-impact variant effects. This does not create curated database rule hits.
Configured high-impact variant effects (frameshift, stop_gained, stop_lost, start_lost, insertion, deletion) observed in a feature/reference pair are interpreted as phenotype='resistant' for the configured drug. This algorithm does not set clinical_phenotype.
Configuration keys:
rules— required non-empty list- each rule must include
feature,effect,reference, anddrugas case-sensitive exact non-empty strings effect— required non-empty list of strings; each must be one of:frameshift,stop_gained,stop_lost,start_lost,insertion,deletion- each (
feature,reference,drug) tuple must be unique across the list
This metadata output is only produced when the project database has at least one curated rule with a known phenotype or clinical phenotype.
Example:
{
"name": "effect_as_resistant",
"rules": [
{
"feature": "UL23",
"effect": ["frameshift", "stop_gained", "stop_lost"],
"reference": "NC_001806",
"drug": "Aciclovir"
}
]
}
drug_interpretation¶
Combines matched rules into one overall drug result. Depending on the database, this can be based on phenotype labels, scores, IC50 values, or fold-change cutoffs.
Supported methods:
by_phenotype— counts phenotype-labelled hits per drug and compares counts against thresholdsby_score— sums score values per drug and compares totals against thresholdsby_ic50— checks per-hit IC50 values per drug; if any value meets the resistant threshold the drug is resistant, otherwise if any value meets the intermediate threshold the drug is intermediate, otherwise sensitiveby_fold_ic50— same logic asby_ic50, but using fold-IC50 values
Configuration keys:
method— required; must be"by_phenotype","by_score","by_ic50", or"by_fold_ic50"thresholds— required object; must include"resistant";"intermediate"is optional- for
by_phenotypeandby_score, threshold values must be positive integers - for
by_ic50andby_fold_ic50, threshold values must be positive numbers; ifintermediateis set,resistantmust be strictly greater thanintermediate - each method may appear at most once; two entries with the same
methodare rejected drug_thresholds— optional list of per-drug overrides; see Per-drug / per-reference overrides below
When multiple methods are configured, the report shows a per-method assessment column (plain text) alongside the final Assessment column. The final assessment uses strongest-wins resolution: resistant > contradictory > intermediate > sensitive. The most resistant result across all methods is taken as the final call.
When drug_thresholds overrides are configured, each per-method assessment cell in the report shows an info icon on hover naming the resolved thresholds and their source (override (reference, drug), override (drug), or global default). The table layout, badge styling, and final Assessment column are unchanged; without overrides the report renders identically to the global-only case.
Example:
{
"name": "drug_interpretation",
"method": "by_phenotype",
"thresholds": {
"resistant": 1,
"intermediate": 1
}
}
ic50_thresholds¶
Defines per-drug IC50 or fold-IC50 breakpoints. With this, each rule that has an IC50 value associated will be classified for a phenotype during init.
use— required; must be"ic50"or"fold_ic50"thresholds— required non-empty object; each key is a drug name; each value must have"intermediate"and"resistant"keys with positive numbers;"resistant"must be strictly greater than"intermediate"drug_thresholds— optional list of per-drug overrides; see Per-drug / per-reference overrides below
Example:
{
"name": "ic50_thresholds",
"use": "fold_ic50",
"thresholds": {
"ACV": {"intermediate": 3.0, "resistant": 10.0},
"PCV": {"intermediate": 3.0, "resistant": 10.0}
}
}
Per-drug / per-reference overrides¶
Both drug_interpretation and ic50_thresholds accept an optional drug_thresholds list that overrides the global thresholds for specific drugs, optionally scoped to a single reference. This is useful when a drug needs finer breakpoints than the database-wide default, or when the same drug has different breakpoints across references (e.g. different viral species).
Each entry is an object with:
reference— optional non-empty string; when present, the override applies only to rules/drugs whose reference matches (accession-version tolerant, e.g.NC_001345.1matchesNC_001345)drug— required non-empty string; the drug name to overridethresholds— required object with the same shape and constraints as the parent algorithm'sthresholds:- for
drug_interpretation: must includeresistant;intermediateis optional; integer forby_phenotype/by_score, positive number forby_ic50/by_fold_ic50(withresistant>intermediatewhenintermediateis set) - for
ic50_thresholds: bothintermediateandresistantare required, andresistantmust be strictly greater thanintermediate
Resolution precedence (most specific wins):
- an override matching
(reference, drug) - an override matching
(drug)only (noreference) - the global
thresholds
Duplicate (reference, drug) or (drug)-only keys are rejected. Two overrides whose reference values differ only by accession version (e.g. NC_001345 and NC_001345.1) are treated as the same key and rejected as duplicates. Overrides with no matching drug or reference fall back to the next precedence level. The Database Dashboard condenses overrides for display: entries sharing the same reference (shown as (all) when absent) and the same threshold values collapse into one row with a sorted drug set, mirroring the effect_as_resistant condensing.
When a drug has hits under multiple references in a single report (e.g. a multi-species run), the reference used to resolve per-(reference, drug) overrides is selected deterministically as the alphabetically first reference name. This keeps the report output stable across process invocations (set iteration order is otherwise hash-seed dependent).
Example — drug_interpretation with a per-reference override:
{
"name": "drug_interpretation",
"method": "by_phenotype",
"thresholds": {"resistant": 1, "intermediate": 1},
"drug_thresholds": [
{"reference": "ref", "drug": "ACV", "thresholds": {"resistant": 1, "intermediate": 1}}
]
}
Example — ic50_thresholds with a per-reference override:
{
"name": "ic50_thresholds",
"use": "fold_ic50",
"thresholds": {"ACV": {"intermediate": 3.0, "resistant": 10.0}},
"drug_thresholds": [
{"reference": "ref", "drug": "ACV", "thresholds": {"intermediate": 1.0, "resistant": 2.0}}
]
}
drug_groups¶
Assigns drugs to named groups (e.g. drug classes). This is only if you wish to group drugs in the final report.
groups— required non-empty object; each key is a group name; each value is a non-empty list of drug name strings; a drug name may not appear in more than one group
Example:
{
"name": "drug_groups",
"groups": {
"Nucleoside Analogues": ["ACV", "PCV"],
"Pyrophosphate Analogues": ["FOS"]
}
}
drug_alias¶
Defines canonical drug-name to short-alias mappings for report rendering.
groups— required non-empty object; keys are canonical drug names; values are aliases- each key and value must be a non-empty string
- alias values must be unique across canonical drug names
When configured, these mappings are written to the drug.alias column during respro init and used for report drug labels, for example Aciclovir (ACV).
Example:
{
"name": "drug_alias",
"groups": {
"Aciclovir": "ACV",
"Penciclovir": "PCV"
}
}
Phenotype and clinical phenotype¶
Two independent phenotype fields are tracked per rule:
- Phenotype — captures in-vitro susceptibility interpretation (resistant, intermediate, sensitive, unknown).
- Clinical phenotype — captures treatment-oriented interpretation where available.
Both are normalized independently from flexible input values. See Rules TSV Format for the full normalization table.
Full configuration example¶
For a complete metadata JSON with all interpretation algorithms, see Database Preparation.