Skip to main content

EMS & clinical drug dosing calculator library with CLI

Project description

๐Ÿ’Š drugdose

EMS & Clinical Drug Dosing Calculator โ€” weight-based doses, IV drip rates, contraindication checking, and drug interaction screening, all in one Python library.

PyPI version Python License: MIT Tests


โš ๏ธ Medical Disclaimer drugdose is a clinical decision-support tool intended for use by licensed healthcare professionals. It does not replace professional clinical judgment, institutional protocols, or current drug references (e.g. Lexicomp, Micromedex). Always verify doses independently before administration. The authors assume no liability for patient outcomes.


Features

  • Weight-based dose calculation โ€” mg/kg, mcg/kg, flat doses, across all common administration routes
  • Pediatric dose caps โ€” separate adult and pediatric maximum single-dose limits
  • IV drip rate calculator โ€” any rate unit (mcg/kg/min, mg/hr, g/hr, etc.) โ†’ mL/hr pump rate and bag duration
  • Allergy checker โ€” direct, brand-name, cross-reactivity, and drug-class allergy matching
  • Contraindication flags โ€” conditions, age/weight restrictions, pregnancy categories D & X, renal/hepatic caution
  • Drugโ€“drug interaction screener โ€” 39 curated rules with severity (major/moderate/minor), clinical description, and management guidance
  • 49-drug bundled database โ€” EMS, cardiac, anesthesia, ICU, antibiotics, toxicology, obstetrics, and more
  • Rich CLI โ€” interactive terminal interface with colour-coded safety output
  • Pure Python, zero heavy dependencies โ€” only rich and click

Installation

pip install drugdose

Requires Python 3.10+.


Quick Start

Python API

from drugdose import Patient, calculate_dose, calculate_drip

# โ”€โ”€ Build a patient โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
patient = Patient(
    weight_kg=70,
    age_years=35,
    allergies=["codeine"],
    current_medications=["midazolam"],
    conditions=["hypertension"],
    renal_impairment=False,
)

# โ”€โ”€ Calculate a single dose โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
result = calculate_dose("fentanyl", patient, route="IV")

print(result.summary())
# โ†’ Fentanyl Citrate IV: 200.00 mcg โ†’ 4.00 mL

print(f"Dose:    {result.dose_display:.1f} mcg")
print(f"Volume:  {result.volume_ml:.2f} mL")
print(f"Freq:    {result.frequency}")

# Safety flags
if result.contraindications:
    for ci in result.contraindications:
        print(f"[{'ABSOLUTE' if ci.absolute else 'relative'}] {ci.detail}")

if result.interactions:
    for ix in result.interactions:
        print(f"[{ix.severity.upper()}] {ix.drug_a} โŸบ {ix.drug_b}: {ix.description}")

IV Drip Rate

from drugdose import Patient, calculate_drip, standard_mixture

patient = Patient(weight_kg=80)

# Calculate pump rate
drip = calculate_drip(
    "dopamine",
    patient,
    ordered_dose=5.0,
    dose_unit="mcg/kg/min",
    bag_volume_ml=250.0,
)

print(drip.summary())
# โ†’ Dopamine drip @ 5 mcg/kg/min: 15.00 mL/hr  (bag lasts 16.7 hr)

print(f"Rate:     {drip.rate_ml_per_hr:.2f} mL/hr")
print(f"Delivers: {drip.dose_mg_per_min * 60:.2f} mg/hr")
print(f"Duration: {drip.duration_hr:.1f} hr")

# Build a custom mixture concentration
conc = standard_mixture("norepinephrine", total_drug_mg=4.0, bag_volume_ml=250.0)
print(f"Bag conc: {conc:.4f} mg/mL")   # โ†’ 0.0160 mg/mL

Dose Range (min โ†’ max)

from drugdose import Patient, calculate_range

patient = Patient(weight_kg=25, age_years=7)
min_r, max_r = calculate_range("ketamine", patient, route="IV")

print(f"Min dose: {min_r.dose_display:.1f} mg  ({min_r.volume_ml:.2f} mL)")
print(f"Max dose: {max_r.dose_display:.1f} mg  ({max_r.volume_ml:.2f} mL)")

Safety Check Only

from drugdose import get_drug, Patient, full_safety_check

drug = get_drug("amiodarone")
patient = Patient(
    weight_kg=70,
    age_years=68,
    allergies=["iodine"],
    current_medications=["digoxin", "metoprolol"],
)

ci_flags, ix_flags = full_safety_check(drug, patient)

for ci in ci_flags:
    severity = "ABSOLUTE" if ci.absolute else "relative"
    print(f"[{severity}] [{ci.category}] {ci.detail}")

for ix in ix_flags:
    print(f"[{ix.severity.upper()}] {ix.drug_a} + {ix.drug_b}")
    print(f"  {ix.description}")
    print(f"  Management: {ix.management}")

Drug Search & Lookup

from drugdose import get_drug, search_drugs, get_all_drugs

# Lookup by name or brand name
drug = get_drug("Narcan")     # returns naloxone Drug object
drug = get_drug("epi")        # partial match โ†’ epinephrine

# Search with query and/or tag
cardiac_drugs = search_drugs("", tag="cardiac")
opioid_results = search_drugs("opioid")

# Full database
all_drugs = get_all_drugs()   # dict[str, Drug]
print(f"{len(all_drugs)} drugs in database")

CLI Reference

Install via pip then run drugdose:

Usage: drugdose [OPTIONS] COMMAND [ARGS]...

  ๐Ÿ’Š drugdose โ€” Clinical Dosing

Commands:
  calculate   Calculate a weight-based drug dose
  check       Run a full safety check for a drug and patient
  drip        Calculate IV drip / infusion pump rate
  info        Show detailed information about a drug
  list        List all drugs in the database
  search      Search the drug database by name, indication, or tag
  version     Show version and library info

Every command accepts --help / -h for full option details.

Examples

# Interactive dose calculator (prompts for patient info)
drugdose calculate epinephrine --route IV --weight 70

# Specify everything inline
drugdose calculate fentanyl -r IM -w 25 --age 8 --allergies penicillin

# Show the full min-to-max dose range
drugdose calculate ketamine --range -w 70 --age 30

# IV drip rate
drugdose drip dopamine -w 70 -d 5 -u mcg/kg/min

# Calculate a custom mixture concentration
drugdose drip epinephrine --mix --total-mg 4 -b 250

# Full drug info panel
drugdose info ketamine
drugdose info "Narcan"

# Safety check with patient context
drugdose check amiodarone --meds "digoxin,metoprolol" --age 72 -w 80
drugdose check morphine --allergies codeine --conditions "respiratory depression"

# Search and list
drugdose search opioid
drugdose search --tag cardiac
drugdose list --tag emergency
drugdose list --class benzodiazepine

Drug Database

49 drugs bundled across clinical categories:

Category Drugs
Emergency / EMS Epinephrine, Adenosine, Atropine, Naloxone, Dextrose, Tranexamic Acid, Glucagon, Activated Charcoal
Cardiac Amiodarone, Lidocaine, Adenosine, Metoprolol, Diltiazem, Digoxin, Nitroglycerin, Magnesium Sulfate
Vasopressors / Inotropes Norepinephrine, Dopamine, Dobutamine, Vasopressin, Phenylephrine, Epinephrine (drip)
Anesthesia / Sedation Ketamine, Propofol, Etomidate, Midazolam, Lorazepam, Diazepam
Neuromuscular Blockers Succinylcholine, Rocuronium
Opioid Analgesics Morphine, Fentanyl
Non-Opioid Analgesics Ketorolac, Acetaminophen
Respiratory Albuterol, Ipratropium, Methylprednisolone, Dexamethasone
Antibiotics Vancomycin, Ceftriaxone, Piperacillin-Tazobactam
Anticoagulants / Thrombolytics Heparin, Alteplase (tPA)
Metabolic / Electrolytes Insulin Regular, Sodium Bicarbonate, Calcium Gluconate, Furosemide
Other Ondansetron, Diphenhydramine, Haloperidol, Labetalol

All drugs include: multiple routes, dose ranges (mg/kg or mcg/kg), standard concentrations, adult and pediatric dose caps, frequency, onset/duration, contraindications, cross-reactivity lists, and clinical notes.


Adding Custom Drugs

Extend the bundled database by editing src/drugdose/data/drugs.json, or load your own at runtime:

import json
from drugdose.models.drug import Drug
from drugdose import calculate_dose, Patient

# Load a custom drug dict
with open("my_formulary.json") as f:
    entries = json.load(f)

custom_drug = Drug.from_dict(entries[0])

# Pass it directly to the checker or calculator internals
from drugdose.calculator import calculate_dose as _calc
from drugdose.db import get_all_drugs

# Or monkey-patch the cache for the session:
db = get_all_drugs()
db["my_drug"] = custom_drug

A plugin/formulary override system is planned for v0.2.0.


API Reference

Patient(weight_kg, age_years, sex, allergies, current_medications, conditions, is_pregnant, renal_impairment, hepatic_impairment, height_cm)

Property Type Description
is_pediatric bool Age < 18 years
is_neonate bool Age < 28 days
is_infant bool Age 28 days โ€“ 1 year
ibw_kg float | None Ideal body weight (Devine formula)
bmi float | None Body mass index
age_months float | None Age expressed in months

calculate_dose(drug_name, patient, route, concentration_mg_ml, dose_fraction) โ†’ DoseResult

Parameter Default Description
drug_name required Generic name, brand name, or partial name
patient required Patient object
route "IV" Route string: IV, IM, IN, SQ, ETT, PR, SL, INH, IV_DRIP
concentration_mg_ml None Override stock concentration. Uses database default when None.
dose_fraction 1.0 0.0 = minimum dose, 1.0 = maximum dose

calculate_range(drug_name, patient, route, concentration_mg_ml) โ†’ (DoseResult, DoseResult)

Returns (min_result, max_result).

calculate_drip(drug_name, patient, ordered_dose, dose_unit, concentration_mg_ml, bag_volume_ml) โ†’ DripResult

Supported dose_unit values: mcg/kg/min, mcg/kg/hr, mg/kg/min, mg/kg/hr, mcg/min, mcg/hr, mg/min, mg/hr, g/hr, units/min, units/hr.

standard_mixture(drug_name, total_drug_mg, bag_volume_ml) โ†’ float

Returns concentration in mg/mL.

full_safety_check(drug, patient, route) โ†’ (list[ContraindicationFlag], list[InteractionFlag])

search_drugs(query, tag) โ†’ list[Drug]

get_drug(name) โ†’ Drug | None

Matches by generic name, display name, brand names, and partial substring.


Exceptions

Exception Raised when
DrugNotFoundError Drug name not in database
InvalidRouteError Route not available for the drug
InvalidPatientError Weight/age outside physiologic range
ContraindicatedError Absolute contraindication triggered (if you raise it yourself)
WeightError Weight is zero or negative
ConcentrationError No concentration provided and none in database

All inherit from DrugDoseError.


Development

# Clone and install in editable mode
git clone https://github.com/londonchowdhury/drugdose.git
cd drugdose
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run tests with coverage
pytest tests/ --cov=drugdose --cov-report=term-missing

Project Structure

drugdose/
โ”œโ”€โ”€ pyproject.toml              # Package config & dependencies
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ CHANGELOG.md
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ drugdose/
โ”‚       โ”œโ”€โ”€ __init__.py         # Public API re-exports
โ”‚       โ”œโ”€โ”€ calculator.py       # calculate_dose(), calculate_range()
โ”‚       โ”œโ”€โ”€ drip.py             # calculate_drip(), standard_mixture()
โ”‚       โ”œโ”€โ”€ checker.py          # Contraindication & interaction engine
โ”‚       โ”œโ”€โ”€ db.py               # Drug database loader & search
โ”‚       โ”œโ”€โ”€ exceptions.py       # Custom exception hierarchy
โ”‚       โ”œโ”€โ”€ cli.py              # Rich + Click CLI
โ”‚       โ”œโ”€โ”€ models/
โ”‚       โ”‚   โ”œโ”€โ”€ drug.py         # Drug, RouteConfig dataclasses
โ”‚       โ”‚   โ”œโ”€โ”€ patient.py      # Patient dataclass
โ”‚       โ”‚   โ””โ”€โ”€ result.py       # DoseResult, DripResult, flags
โ”‚       โ””โ”€โ”€ data/
โ”‚           โ”œโ”€โ”€ drugs.json      # 49-drug database
โ”‚           โ””โ”€โ”€ interactions.json  # 39 interaction rules
โ””โ”€โ”€ tests/
    โ””โ”€โ”€ test_calculator.py      # 24 unit tests

Publishing to PyPI

pip install build twine
python -m build
twine check dist/*
twine upload dist/*

Roadmap

  • Renal dose-adjustment engine (Cockcroft-Gault, CKD-EPI)
  • ACLS/PALS automated protocol sequences
  • Broselow tape weight-estimation by age/length
  • Pharmacokinetic simulation (Cp vs. time)
  • PDF/JSON export for dose calculations
  • REST API via drugdose serve
  • Plugin / custom formulary system
  • Expanded database: oncology, psychiatry, neonatal specific
  • Web UI

Contributing

Contributions are welcome โ€” especially:

  • New drugs or routes โ€” open a PR editing drugs.json
  • Interaction rules โ€” open a PR editing interactions.json
  • Bug reports โ€” open an issue with patient parameters and expected vs. actual output
  • Protocol corrections โ€” cite your source (AHA guidelines, package insert, etc.)

Please include a citation for any dose ranges added or modified.


License

MIT ยฉ 2026 London Chowdhury. See LICENSE for full text.


Acknowledgements

Dose ranges sourced from and cross-referenced against:

  • American Heart Association (AHA) ACLS/PALS Guidelines 2020
  • Pediatric Advanced Life Support (PALS) Provider Manual
  • Micromedex / Lexicomp drug references
  • Surviving Sepsis Campaign Guidelines 2021
  • Individual FDA-approved package inserts

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drugdose-0.1.0.tar.gz (53.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drugdose-0.1.0-py3-none-any.whl (50.2 kB view details)

Uploaded Python 3

File details

Details for the file drugdose-0.1.0.tar.gz.

File metadata

  • Download URL: drugdose-0.1.0.tar.gz
  • Upload date:
  • Size: 53.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for drugdose-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dd8737e1a9b46a4f2174889f13004f97c736d23f643b2f587e195fb9a35bc12b
MD5 59d844ac7ba0fd6c53453516d1aaf77d
BLAKE2b-256 313ceda691660d29b92c319c3828b6cc46d9e08c1fdf1f41788106015c9b9993

See more details on using hashes here.

File details

Details for the file drugdose-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: drugdose-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 50.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for drugdose-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a13793aea5d806f9fe3a4f3e884cb341ab207b8ac51ca22d53308ee0d0e11060
MD5 26296e2c90a566c153253d689747b0f5
BLAKE2b-256 ff215b5df3468031fbd7773bcfc6d6e16bf00101a88102913924493a77629606

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page