Drug repurposing¶
drug_repurposing.py assembles the data sets a drug repurposing study in an ALS registry starts from: who is in the motor neuron disease cohort and when they entered it, which medicines each participant was exposed to and what the evidence is, and how long each participant was followed to a defined data cut-off. The exposure criteria adapt the methodology of Reimer et al., Lancet Digital Health, 2026, a study of drug repurposing candidates for ALS in US Veterans Health Administration records. The module produces descriptive figures for generating hypotheses; it does not estimate the effect of any medicine.
Open the demo report Demo summary (CSV) Module source (drug_repurposing.py)
Live demo · Cohort · Exposure · Follow-up · Summary · Panels · Medicine names · Outputs · Running it · Limits
Live demo¶
The demo report below comes from the invented ALS cohort that ships with Registry Forge, run with a data cut-off of 31 October 2026. No real person is in it, and its figures say nothing about any medicine.
Cohort¶
Every participant with a motor neuron disease code in the problem list is in the cohort. Cohort entry is the date of the earliest such code.
| Vocabulary | Codes |
|---|---|
| ICD-10-CM | G12.20 (motor neuron disease, unspecified), G12.21 (ALS), G12.22 (progressive bulbar palsy), G12.23 (primary lateral sclerosis), G12.29 (other motor neuron disease) |
| ICD-9-CM | 335.20 to 335.29 |
| SNOMED CT | 86044005 (ALS), 230258005 (motor neuron disease) |
| Mondo | MONDO:0004976 (ALS), MONDO:0019056 (motor neuron disease) |
The codes are in COHORT_CODES at the top of the module; replace them to study a different disease. Participants with no medication record stay in the cohort and count as unexposed for every medicine, and the log reports how many cohort participants had any medication record. Reimer and colleagues left out patients with no medication record after cohort entry, as a sign that their care was not recorded; if your protocol does the same, apply that rule to the cohort file before analysis.
Exposure¶
The default criterion, any, counts a medicine as an exposure when any record of it falls between 6 months before and 12 months after cohort entry. This suits participant-contributed records, where each medication row is an order, a list entry or a statement rather than a pharmacy fill.
The stricter Reimer criteria suit dispensing data with fill dates and days' supply:
| Criterion | Rule |
|---|---|
reimer-a |
A dispensing within 12 months after cohort entry, with the prescription lasting at least 6 months |
reimer-b |
At least 2 dispensings between 6 months before and 12 months after cohort entry |
reimer |
Either A or B |
Each exposure lists its evidence types: order (MedicationRequest), dispense, administration, reported_use (MedicationStatement) or document_list (a C-CDA medication list entry, which does not say whether the medicine was taken). An order is not evidence that a medicine was taken.
Follow-up¶
Follow-up runs from cohort entry to the data cut-off given with --cutoff:
| Situation | Follow-up ends | Counted as |
|---|---|---|
Death on or before the cut-off (from FHIR or vital_status.csv) |
at death | event |
| Confirmed alive on or after the cut-off | at the cut-off | censored |
| Last confirmed alive before the cut-off | at the last confirmed alive date | censored |
| No vital status | at the last dated record | censored |
Nobody is assumed to be alive at the cut-off, and follow-up never runs to the date the script runs, so the same data and cut-off always give the same figures. Deaths recorded outside the EHR, for example from National Death Index linkage, go into vital_status.csv.
Summary figures¶
For each medicine with at least --min-exposed exposed participants, the summary gives exposed and unexposed counts, deaths in each group, and Kaplan-Meier median survival in months measured from a landmark 12 months after cohort entry, among participants alive and under follow-up at the landmark. The landmark is there because exposure is assessed through month 12; measuring from entry would credit exposed participants with time they had to survive to be counted as exposed. "Not reached" means fewer than half of the group died during follow-up.
Suppression is applied to the whole row:
- If either group has fewer than k participants, every figure for that medicine is held back for cell size.
- Death counts and landmark counts are held back in pairs, because exposed plus unexposed always equals a cohort total.
- Landmark counts are held back when the number lost before the landmark is small.
The figures are unadjusted. Disease stage, site of onset, age, the reason a medicine was prescribed and many other factors differ between groups, so a difference between two medians says nothing about a medicine's effect.
Reimer and colleagues kept medicines with at least 30 exposed participants in a cohort of about 11,000. A registry of a few dozen to a few hundred participants needs a lower value; the default here is 5, and the value is never set below k. The log lists the medicines with the most exposed participants and marks which were kept.
Medicine panels¶
The report always shows a panel of ALS clinical-interest medicines, whether or not they meet the minimum count. When fewer than k participants have a record of one, its participant count, year range, record count and evidence types are all held back for cell size.
| Medicine | Brand names | ATC code | Status shown |
|---|---|---|---|
| Riluzole | Rilutek, Tiglutik, Exservan | N07XX02 | FDA-approved for ALS (1995) |
| Edaravone | Radicava, Radicava ORS | N07XX14 | FDA-approved for ALS (2017) |
| Tofersen | Qalsody | N07XX22 | FDA-approved for SOD1 ALS (2023, accelerated approval) |
| Dextromethorphan-quinidine | Nuedexta | N07XX59 | FDA-approved for pseudobulbar affect; of interest in ALS |
| Sodium phenylbutyrate-taurursodiol | Relyvrio, Albrioza | N07XX19 | FDA-approved for ALS in 2022; withdrawn in 2024 after the PHOENIX trial |
Medicines approved for ALS, and the withdrawn sodium phenylbutyrate-taurursodiol, are left out of the CURE ID review worksheet, because their use in ALS is not off-label. ATC codes were checked against the WHO ATC index in November 2026.
Medicine names and ATC classes¶
Medication names are lowercased, stripped of dose and form, and mapped from brand to generic through BRAND_TO_GENERIC before the Anatomical Therapeutic Chemical (ATC) class is looked up in ATC_SEED. Combination products are recognized through COMBINATION_RULES: Nuedexta, or dextromethorphan and quinidine together, become dextromethorphan-quinidine, and Relyvrio, Albrioza, or phenylbutyrate with taurursodiol become sodium phenylbutyrate-taurursodiol. Dextromethorphan alone (an antitussive, R05DA09) and quinidine alone (an antiarrhythmic, C01BA01) are kept as separate medicines, as Reimer and colleagues reported them separately.
ATC classes in ATC_SEED
| ATC class | Medicines |
|---|---|
| HMG-CoA reductase inhibitors (C10AA) | simvastatin, lovastatin, pravastatin, atorvastatin, rosuvastatin, pitavastatin, fluvastatin |
| PDE5 inhibitors (G04BE) | sildenafil, vardenafil, tadalafil, avanafil |
| Alpha-adrenoreceptor antagonists (G04CA, C02CA) | tamsulosin, terazosin, alfuzosin, silodosin, doxazosin |
| Centrally acting muscle relaxants (M03BX) | cyclobenzaprine, baclofen, tizanidine |
| Other nervous system drugs (N07XX) | riluzole, edaravone, tofersen, sodium phenylbutyrate-taurursodiol, dextromethorphan-quinidine |
| Opium alkaloid antitussive (R05DA09) | dextromethorphan |
| Class IA antiarrhythmic (C01BA01) | quinidine |
| Oxicam NSAID (M01AC06) | meloxicam |
| Vitamin D (A11CC05) | colecalciferol |
| Direct factor Xa inhibitor (B01AF01) | rivaroxaban |
| Thiazide diuretic (C03AA03) | hydrochlorothiazide |
| ACE inhibitor (C09AA03) | lisinopril |
| Anticholinergic for sialorrhea (A03AB02) | glycopyrrolate |
| 5HT3 antagonist (A04AA01) | ondansetron |
| Opioid analgesics (N02AB03, N02AA, N07BC02) | fentanyl, morphine, oxycodone, hydromorphone, methadone |
| Gabapentinoid (N02BF01) | gabapentin |
| Decongestant (R01BA02) | pseudoephedrine |
| Mucolytic (R05CA03) | guaifenesin |
| H1 antihistamine (R06AE07) | cetirizine |
| Short-acting beta agonist (R03AC02) | salbutamol (albuterol) |
| Leukotriene receptor antagonist (R03DC03) | montelukast |
Brand names in BRAND_TO_GENERIC
| Generic | Brand names |
|---|---|
| riluzole | Rilutek, Tiglutik, Exservan |
| edaravone | Radicava, Radicava ORS |
| tofersen | Qalsody |
| dextromethorphan-quinidine | Nuedexta |
| sodium phenylbutyrate-taurursodiol | Relyvrio, Albrioza |
| statins | Lipitor, Crestor, Zocor, Mevacor, Altoprev, Pravachol, Livalo, Zypitamag, Lescol |
| PDE5 inhibitors | Viagra, Revatio, Levitra, Staxyn, Cialis, Adcirca, Stendra |
| alpha blockers | Flomax, Hytrin, Uroxatral, Rapaflo, Cardura |
| muscle relaxants | Flexeril, Amrix, Fexmid, Zanaflex, Lioresal, Gablofen, Ozobax |
| glycopyrrolate | Robinul, Cuvposa, Glycate, Dartisla |
| ondansetron | Zofran, Zuplenz |
| fentanyl | Sublimaze, Duragesic, Actiq, Fentora, Abstral, Subsys, Lazanda |
| gabapentin | Neurontin, Gralise, Horizant |
| cough and cold | Sudafed (pseudoephedrine), Mucinex and Robitussin (guaifenesin) |
| cetirizine | Zyrtec, Reactine |
| bronchodilators | Ventolin, Proventil, ProAir, AccuNeb (salbutamol); Xopenex (levalbuterol) |
| montelukast | Singulair |
| lisinopril | Prinivil, Zestril, Qbrelis |
| rivaroxaban | Xarelto |
| colecalciferol | Vitamin D, Vitamin D3, D3, cholecalciferol |
Medicines not in ATC_SEED are kept under "Not in ATC seed mapping". The log lists the most frequent unmatched names, which is the list to work from when you extend the two dictionaries for your own data.
Outputs¶
| File | Holds | Where run_all.py puts it |
|---|---|---|
drug_repurposing_cohort.csv |
One row per participant and medicine: pseudonymous ID, cohort entry, age, sex, race, ethnicity, exposure, criterion met, evidence types, follow-up end and its basis, vital status at the cut-off. Calendar dates are kept | restricted/drug_repurposing/ |
drug_repurposing_summary.csv |
One row per medicine with ATC class, ALS status, counts and landmark medians, with suppression applied | restricted/drug_repurposing/ and reports/ |
drug_repurposing_report.html |
The report, counts only | restricted/drug_repurposing/ and reports/ |
cure_id_review_worksheet.csv |
One row per exposed participant and medicine, in the shape of a CURE ID case report, for clinical review. It is a local worksheet, not a CURE ID submission | restricted/drug_repurposing/ |
off_label_snippets.md |
Example source records for common ALS symptom medicines, with years only | restricted/drug_repurposing/ |
--also-write-identified adds a cohort file with registry participant IDs; treat it as protected health information (PHI).
The cohort file is the input to a prespecified analysis, for example a Cox model or propensity score matching with lifelines or statsmodels. Reimer and colleagues matched with a caliper of 0.2 standard deviations of the logit of the propensity score and up to three controls for each exposed participant.
Running it¶
run_all.py runs the module when --cutoff is given. To run it on its own:
python pipeline/drug_repurposing.py --bundle RUN/dashboard_data.json \
--out RUN/restricted/drug_repurposing --cutoff 2026-10-31 \
--vital-status RUN/vital_status.csv --min-exposed 5 --k 5
| Option | Default | Meaning |
|---|---|---|
--cutoff |
latest record date, with a warning | Data cut-off |
--vital-status |
none | Deaths and alive confirmations from outside the records |
--min-exposed |
5 | Fewest exposed participants for a medicine to be summarized (never below k) |
--k |
5 | Small-cell threshold |
--landmark-months |
12 | Landmark for the survival medians |
--criterion |
any |
any, reimer-a, reimer-b or reimer |
--cohort-name |
ALS registry cohort |
Name in the report header |
The exposure windows, the cohort codes, the ATC seed, the brand names and the CURE ID age bands and race options are plain Python dictionaries and constants near the top of the module.
Limits¶
- Confounding by indication. A participant prescribed a PDE5 inhibitor may be healthier than average, and one prescribed an opioid may have more advanced disease. Matching reduces this but does not remove it.
- Diagnosis accuracy. A coded motor neuron disease diagnosis has not been checked against clinical criteria. Reimer and colleagues ran a sensitivity analysis restricted to participants treated with riluzole, whose indication is specific to ALS; the same check suits a registry.
- Missing records. Participant-contributed records can miss medicines filled outside connected health systems and deaths not yet linked.
- No dose. Dose is not taken from the bundle, so dose-response analysis needs an extension of the medication parser.
- Many comparisons. Screening many medicines raises the chance of false signals; report how you correct for this.
The cohort file is the starting point for a prespecified analysis, which needs a protocol stating the comparison, time zero, eligibility, covariates and how missing records and outside care are handled. Findings from one registry generate hypotheses; randomized trials test them.
Reference¶
Reimer RJ, Soper B, Wilson JL, Goncalves AR, Cadena J, Suarez P, Gryshuk AL, Osborne TF, Grimes KV, Ray P. Identification of drug repurposing candidates for amyotrophic lateral sclerosis using electronic health records: a retrospective cohort study. Lancet Digital Health. 2026. doi:10.1016/j.landig.2025.100963