cardinal_pythonlib.psychiatry.drugs


Original code copyright (C) 2009-2022 Rudolf Cardinal (rudolf@pobox.com).

This file is part of cardinal_pythonlib.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.


Drug information, with an emphasis on psychotropic drugs, including translating specific to generic names.

Examples

Test within Python:

from cardinal_pythonlib.psychiatry.drugs import *

drug_name_to_generic("UNKNOWN")
drug_name_to_generic("UNKNOWN", unknown_to_default=True)
drug_names_to_generic([
    "citalopram", "Citalopram", "Cipramil", "Celexa",
    "olanzepine",  # typo
    "dextroamphetamine",
    "amitryptyline",
])

Antidepressants

As of 2018-07-01, this is a functional superset of the SLAM antidepressant-finding SQL (see dep_med_v1), though mainly a superset in non-antidepressant respects; the only antidepressants it adds are:

  • buproprion, maprotiline

The SLAM antidepressant finder finds:

  • tricyclic (category)

  • amitriptyline, clomipramine, dosulepin, doxepin, imipramine, lofepramine, nortriptyline, trimipramine

  • mianserin, trazodone, phenelzine, isocarboxazid, tranylcypromine, moclobemide

  • citalopram, escitalopram, fluoxetine, fluvoxamine, paroxetine, sertraline

  • mirtazapine, reboxetine, venlafaxine, agomelatine, duloxetine

  • flupentixol, tryptophan

Sorted, that is:

agomelatine
amitriptyline
citalopram
clomipramine
dosulepin
doxepin
duloxetine
escitalopram
fluoxetine
flupentixol
fluvoxamine
imipramine
isocarboxazid
lofepramine
mianserin
mirtazapine
moclobemide
nortriptyline
paroxetine
phenelzine
reboxetine
sertraline
tranylcypromine
trazodone
tricyclic
trimipramine
tryptophan
venlafaxine

Compare that against the output of:

[x.generic_name for x in all_drugs_where(slam_antidepressant_finder=True,
                                         include_categories=True)]

Using this code from R via reticulate

Test within R:

# -------------------------------------------------------------------------
# Load libraries
# -------------------------------------------------------------------------

RUN_ONCE_ONLY <- '
    library(devtools)
    devtools::install_github("rstudio/reticulate")  # get latest version
'

library(data.table)
library(reticulate)

# -------------------------------------------------------------------------
# Set up reticulate
# -------------------------------------------------------------------------

VENV <- "~/dev/venvs/cardinal_pythonlib"  # or your preferred virtualenv
PYTHON_EXECUTABLE <- ifelse(
    .Platform$OS.type == "windows",
    file.path(VENV, "Scripts", "python.exe"),  # Windows
    file.path(VENV, "bin", "python")  # Linux
)
reticulate::use_python(PYTHON_EXECUTABLE, required=TRUE)
# ... it is CRITICAL to use required=TRUE, or it might fail silently

# Unnecessary now reticulate::use_python() works:
#
# PYTHON_VERSION <- "python3.5"
# CARDINAL_PYTHONLIB_BASEDIR <- ifelse(
#     .Platform$OS.type == "windows",
#     file.path(VENV, "lib", "site-packages/cardinal_pythonlib"),
#     file.path(VENV, "lib", PYTHON_VERSION, "site-packages/cardinal_pythonlib")
# )
# reticulate::use_virtualenv(VENV, required=TRUE)
#
# cpl_fileops <- reticulate::import_from_path("fileops", CARDINAL_PYTHONLIB_BASEDIR)
# cpl_drugs <- reticulate::import_from_path("drugs", file.path(CARDINAL_PYTHONLIB_BASEDIR, "psychiatry"))
#
# ... this is NOT WORKING properly; dotted imports via reticulate::import() fail; also, imports from
# within the Python code fail even if you use reticulate::import_from_path(); this suggests the virtualenv is not set up
# properly; use reticulate::use_python() instead.

# -------------------------------------------------------------------------
# Import Python modules
# -------------------------------------------------------------------------

cardinal_pythonlib <- reticulate::import("cardinal_pythonlib")
cpl_fileops <- reticulate::import("cardinal_pythonlib.fileops")
cpl_drugs <- reticulate::import("cardinal_pythonlib.psychiatry.drugs")

# -------------------------------------------------------------------------
# Do something useful
# -------------------------------------------------------------------------

testnames <- c("citalopram", "Cipramil", "Prozac", "fluoxetine")
# Works for simple variables:
cpl_drugs$drug_names_to_generic(testnames)

# Also works for data table replacements:
dt <- data.table(
    subject = c("Alice", "Bob", "Charles", "Dawn", "Egbert", "Flora"),
    drug = c("citalopram", "Cipramil", "Prozac", "fluoxetine", "Priadel", "Haldol")
)
dt[, drug_generic := cpl_drugs$drug_names_to_generic(drug)]
dt[, is_antidepressant := cpl_drugs$drug_names_match_criteria(
        drug_generic,
        names_are_generic=TRUE,
        antidepressant=TRUE)]
dt[, is_antidepressant_not_ssri := cpl_drugs$drug_names_match_criteria(
        drug_generic,
        names_are_generic=TRUE,
        antidepressant=TRUE,
        ssri=FALSE)]
dt[, is_conventional_antidepressant := cpl_drugs$drug_names_match_criteria(
        drug_generic,
        names_are_generic=TRUE,
        conventional_antidepressant=TRUE)]
dt[, slam_antidepressant_finder := cpl_drugs$drug_names_match_criteria(
        drug_generic,
        names_are_generic=TRUE,
        slam_antidepressant_finder=TRUE,
        include_categories=TRUE)]

Use for SQL finding

from typing import List
from cardinal_pythonlib.psychiatry.drugs import *

colname = "somecol"

antidepressants = all_drugs_where(conventional_antidepressant=True)  # type: List[Drug]
antidep_sql_parts = [drug.sql_column_like_drug(colname) for drug in antidepressants]
antidep_sql = " OR ".join(antidep_sql_parts)

antipsychotics = all_drugs_where(antipsychotic=True)  # type: List[Drug]
antipsy_sql_parts = [drug.sql_column_like_drug(colname) for drug in antipsychotics]
antipsy_sql = " OR ".join(antipsy_sql_parts)

alldrugs = all_drugs_where()
alldrug_sql_parts = [drug.sql_column_like_drug(colname) for drug in alldrugs]
alldrug_sql = " OR ".join(alldrug_sql_parts)

lithium = get_drug("lithium")
lithium_sql = lithium.sql_column_like_drug(colname)
# HOWEVER, NOTE THAT LITHIUM IS CURRENTLY OVER-INCLUSIVE and will include
# lithium chloride for LiDCO measurement.
class cardinal_pythonlib.psychiatry.drugs.Drug(generic: str | List[str], alternatives: List[str] | None = None, category_not_drug: bool = False, add_preceding_wildcards: bool = True, add_preceding_word_boundary: bool = True, add_following_wildcards: bool = True, psychotropic: bool | None = None, antidepressant: bool = False, conventional_antidepressant: bool = False, ssri: bool = False, snri: bool = False, nassa: bool = False, non_ssri_modern_antidepressant: bool = False, tricyclic_antidepressant: bool = False, tetracyclic_and_related_antidepressant: bool = False, monoamine_oxidase_inhibitor: bool = False, antipsychotic: bool = False, first_generation_antipsychotic: bool = False, second_generation_antipsychotic: bool = False, stimulant: bool = False, anticholinergic: bool = False, benzodiazepine: bool = False, z_drug: bool = False, non_benzodiazepine_anxiolytic: bool = False, gaba_a_functional_agonist: bool = False, gaba_b_functional_agonist: bool = False, mood_stabilizer: bool = False, antidiabetic: bool = False, sulfonylurea: bool = False, biguanide: bool = False, glifozin: bool = False, glp1_agonist: bool = False, dpp4_inhibitor: bool = False, meglitinide: bool = False, thiazolidinedione: bool = False, cardiovascular: bool = False, beta_blocker: bool = False, ace_inhibitor: bool = False, statin: bool = False, respiratory: bool = False, beta_agonist: bool = False, gastrointestinal: bool = False, proton_pump_inhibitor: bool = False, nonsteroidal_anti_inflammatory: bool = False, vitamin: bool = False, slam_antidepressant_finder: bool = False)[source]

Class to describe a specific drug, or a drug category.

Also embodies knowledge about brand names and common misspellings.

See the DRUGS list for example of use.

Initialize and determine/store category knowledge.

alternatives can include regexes (as text).

We add front/back wildcards by default; this handles all situations like “depot X”, etc. We also add a preceding word boundary (after the wildcard); thus the usual transformation is XXX -> .*XXX.*.

Parameters:
  • generic – generic name, or list of names

  • alternatives – can include regexes (as text)

  • category_not_drug – is this a drug category, not a specific drug?

  • add_preceding_wildcards – when making a regex (etc.), add a wildcard to the start of all possibilities (generic + alternative names) that don’t already have one?

  • add_preceding_word_boundary – when making a regex (etc.), add word boundaries to the start of all possibilities (generic + alternative names) that don’t already have one?

  • add_following_wildcards – when making a regex (etc.), add a wildcard to the end of all possibilities (generic + alternative names) that don’t already have one?

  • psychotropic – a psychotropic drug?

  • antidepressant – an antidepressant?

  • conventional_antidepressant – a traditional antidepressant?

  • ssri – a selective serotonin reuptake inhibitor (SSRI)?

  • non_ssri_modern_antidepressant – a non-SSRI “modern” antidepressant?

  • tricyclic_antidepressant – a tricyclic?

  • tetracyclic_and_related_antidepressant – a tetracyclic or related?

  • monoamine_oxidase_inhibitor – a MAO-I?

  • antipsychotic – an antipsychotic?

  • first_generation_antipsychotic – an FGA?

  • second_generation_antipsychotic – an SGA?

  • stimulant – a psychostimulant?

  • anticholinergic – an anticholinergic?

  • benzodiazepine – a benzodiazepine?

  • z_drug – a “Z” drug (e.g. zopiclone, zolpidem, …)

  • non_benzodiazepine_anxiolytic – a non-BZ anxiolytic?

  • gaba_a_functional_agonist – a GABA-A functional agonist?

  • gaba_b_functional_agonist – a GABA-B functional agonist?

  • mood_stabilizer – a “mood stabilizer”?

  • antidiabetic – treats diabetes?

  • sulfonylurea – a sulfonylurea (sulphonylurea), for diabetes?

  • biguanide – a biguanide, for diabetes?

  • glifozin – a glifozin, for diabetes?

  • glp1_agonist – a GLP-1 agonist, for diabetes?

  • dpp4_inhibitor – a DPP4 inhibitor, for diabetes?

  • meglitinide – a meglitinide, for diabetes?

  • thiazolidinedione – a thiazolidinedione, for diabetes?

  • cardiovascular – a cardiovascular drug?

  • beta_blocker – a beta adrenoceptor antagonist?

  • ace_inhibitor – an ACE inhibitor?

  • statin – a statin?

  • respiratory – a respiratory drug?

  • beta_agonist – a beta adrenoceptor agonist?

  • gastrointestinal – a gastrointestinal drug?

  • proton_pump_inhibitor – a PPI?

  • nonsteroidal_anti_inflammatory – an NSAID?

  • vitamin – a vitamin?

  • slam_antidepressant_finder – a drug found by the SLAM antidepressant-finding code? (A bit specialized, this one!)

mixture

is this a mixture of more than one drug? Will be set if more than one generic name is given.

Type:

bool

all_generics

list of all generic names in lower case

Type:

List[str]

generic_name

generic name (or combination name like a_with_b for mixtures of a and b)

name_matches(name: str) bool[source]

Detects whether the name that’s passed matches our knowledge of any of things that this drug might be called: generic name, brand name(s), common misspellings.

The parameter should be pre-stripped of edge whitespace.

regex() Pattern[source]

Returns a compiled case-insensitive regular expression to match possible names for this drug.

regex_text() str[source]

Return regex text (yet to be compiled) for this drug.

static regex_to_sql_like(regex_text: str, single_wildcard: str = '_', zero_or_more_wildcard: str = '%') List[str][source]

Converts regular expression text to a reasonably close fragment for the SQL LIKE operator.

NOT PERFECT, but works for current built-in regular expressions.

Parameters:
  • regex_text – regular expression text to work with

  • single_wildcard – SQL single wildcard, typically an underscore

  • zero_or_more_wildcard – SQL “zero/one/many” wildcard, probably

  • symbol (always _sphinx_paramlinks_cardinal_pythonlib.psychiatry.drugs.Drug.regex_to_sql_like.a percent) –

Returns:

string for an SQL string literal

Raises:
  • ValueError

  • properly

sql_column_like_drug(column_name: str) str[source]

Returns SQL like

(column_name LIKE '%drugname1%' OR
 column_name LIKE '%drugname2%')

for the drug names that this Drug object knows about.

Parameters:

column_name – column name, pre-escaped if necessary

Returns:

SQL fragment as above

sql_like_fragments() List[str][source]

Returns all the string literals to which a database column should be compared using the SQL LIKE operator, to match this drug.

This isn’t as accurate as the regex, but LIKE can do less.

LIKE uses the wildcards ? and %.

cardinal_pythonlib.psychiatry.drugs.all_drugs_where(sort=True, include_categories: bool = False, **criteria: bool) List[Drug][source]

Find all drugs matching the specified criteria (see drug_matches_criteria()). If include_categories is true, then drug categories (like “tricyclics”) are included as well as individual drugs.

Pass keyword arguments such as

from cardinal_pythonlib.psychiatry.drugs import *
non_ssri_antidep = all_drugs_where(antidepressant=True, ssri=False)
print([d.generic_name for d in non_ssri_antidep])
conventional_antidep = all_drugs_where(conventional_antidepressant=True)
print([d.generic_name for d in conventional_antidep])
cardinal_pythonlib.psychiatry.drugs.drug_matches_criteria(drug: Drug, **criteria: bool) bool[source]

Determines whether a drug, passed as an instance of Drug, matches the specified criteria.

Parameters:
  • drug – a Drug instance

  • criterianame=value pairs to match against the attributes of the Drug class. For example, you can include keyword arguments like antidepressant=True.

cardinal_pythonlib.psychiatry.drugs.drug_name_matches_criteria(drug_name: str, name_is_generic: bool = False, include_categories: bool = False, **criteria: bool) bool[source]

Establish whether a single drug, passed by name, matches the specified criteria. See drug_matches_criteria().

cardinal_pythonlib.psychiatry.drugs.drug_name_to_generic(drug_name: str, unknown_to_default: bool = False, default: str | None = None, include_categories: bool = False) str[source]

Converts a drug name to the name of its generic equivalent.

cardinal_pythonlib.psychiatry.drugs.drug_names_match_criteria(drug_names: List[str], names_are_generic: bool = False, include_categories: bool = False, **criteria: bool) List[bool][source]

Establish whether multiple drugs, passed as a list of drug names, each matches the specified criteria. See drug_matches_criteria().

cardinal_pythonlib.psychiatry.drugs.drug_names_to_generic(drugs: List[str], unknown_to_default: bool = False, default: str | None = None, include_categories: bool = False) List[str][source]

Converts a list of drug names to their generic equivalents.

The arguments are as for drug_name_to_generic() but this function handles a list of drug names rather than a single one.

Note in passing the following conversion of blank-type representations from R via reticulate, when using e.g. the default parameter and storing results in a data.table() character column:

------------------------------  ----------------
To Python                       Back from Python
------------------------------  ----------------
[not passed, so Python None]    "NULL"
NULL                            "NULL"
NA_character_                   "NA"
NA                              TRUE (logical)
------------------------------  ----------------
cardinal_pythonlib.psychiatry.drugs.get_drug(drug_name: str, name_is_generic: bool = False, include_categories: bool = False) Drug | None[source]

Converts a drug name to a Drug class.

If you already have the generic name, you can get the Drug more efficiently by setting name_is_generic=True.

Set include_categories=True to include drug categories (such as tricyclics) as well as individual drugs.