Skip to content

Commit 3b33f52

Browse files
committed
Add new methods:
* Add new methods :meth:`api.core.load_recommendation_table` and :meth:`api.core.get_recommendation`.
1 parent a489f45 commit 3b33f52

File tree

6 files changed

+883
-2
lines changed

6 files changed

+883
-2
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Changelog
77
* Add new method :meth:`api.core.has_sv`.
88
* Update :meth:`api.core.sort_alleles` method to handle ``'Indeterminate'`` haplotype call when ``by='name'``.
99
* Update :meth:`api.utils.estimate_phase_beagle` method to handle situations where there are overlapping samples between input VCF and reference panel -- i.e. users are no longer required to change sample names. Before this update, the Beagle program would throw an error if there were overlapping samples (e.g. 1KGP samples). From now on, offending samples will be temporarily renamed before statistical phasing.
10+
* Add new methods :meth:`api.core.load_recommendation_table` and :meth:`api.core.get_recommendation`.
1011

1112
0.18.0 (2022-08-12)
1213
-------------------

README.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ We can obtain allele function for the CYP2D6 gene:
854854
>>> pypgx.get_function('CYP2D6', '*140')
855855
'Unknown Function'
856856
857-
We can predict phenotype for the CYP2D6 gene based on two haplotype calls:
857+
We can predict phenotype for CYP2D6 based on two haplotype calls:
858858

859859
.. code:: python3
860860
@@ -867,3 +867,18 @@ We can predict phenotype for the CYP2D6 gene based on two haplotype calls:
867867
'Indeterminate'
868868
>>> pypgx.predict_phenotype('CYP2D6', '*1', '*1x2') # Gene duplication
869869
'Ultrarapid Metabolizer'
870+
871+
We can also obtain recommendation (e.g. CPIC) for certain drug-phenotype combination:
872+
873+
.. code:: python3
874+
875+
>>> import pypgx
876+
>>> # Codeine, an opiate and prodrug of morphine, is metabolized by CYP2D6
877+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Normal Metabolizer')
878+
'Use codeine label recommended age- or weight-specific dosing.'
879+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Ultrarapid Metabolizer')
880+
'Avoid codeine use because of potential for serious toxicity. If opioid use is warranted, consider a non-tramadol opioid.'
881+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Poor Metabolizer')
882+
'Avoid codeine use because of possibility of diminished analgesia. If opioid use is warranted, consider a non-tramadol opioid.'
883+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Indeterminate')
884+
'None'

docs/create.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@
822822
>>> pypgx.get_function('CYP2D6', '*140')
823823
'Unknown Function'
824824
825-
We can predict phenotype for the CYP2D6 gene based on two haplotype calls:
825+
We can predict phenotype for CYP2D6 based on two haplotype calls:
826826
827827
.. code:: python3
828828
@@ -835,6 +835,21 @@
835835
'Indeterminate'
836836
>>> pypgx.predict_phenotype('CYP2D6', '*1', '*1x2') # Gene duplication
837837
'Ultrarapid Metabolizer'
838+
839+
We can also obtain recommendation (e.g. CPIC) for certain drug-phenotype combination:
840+
841+
.. code:: python3
842+
843+
>>> import pypgx
844+
>>> # Codeine, an opiate and prodrug of morphine, is metabolized by CYP2D6
845+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Normal Metabolizer')
846+
'Use codeine label recommended age- or weight-specific dosing.'
847+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Ultrarapid Metabolizer')
848+
'Avoid codeine use because of potential for serious toxicity. If opioid use is warranted, consider a non-tramadol opioid.'
849+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Poor Metabolizer')
850+
'Avoid codeine use because of possibility of diminished analgesia. If opioid use is warranted, consider a non-tramadol opioid.'
851+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Indeterminate')
852+
'None'
838853
""".format(**d)
839854

840855
readme_file = f'{core.PROGRAM_PATH}/README.rst'

pypgx/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
get_function,
1313
get_paralog,
1414
get_priority,
15+
get_recommendation,
1516
get_ref_allele,
1617
get_region,
1718
get_score,
@@ -30,6 +31,7 @@
3031
load_equation_table,
3132
load_gene_table,
3233
load_phenotype_table,
34+
load_recommendation_table,
3335
load_variant_table,
3436
predict_phenotype,
3537
predict_score,

pypgx/api/core.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,104 @@ def get_priority(gene, phenotype):
554554

555555
return df[i].Priority.values[0]
556556

557+
def get_recommendation(drug, gene1, phenotype1, gene2=None, phenotype2=None):
558+
"""
559+
Get recommendation for specified drug-phenotype combination.
560+
561+
Parameters
562+
----------
563+
drug : str
564+
Drug name.
565+
gene1 : str
566+
Gene name.
567+
phenotype1 : str
568+
Phenotype name.
569+
gene2 : str, optional
570+
Second gene name.
571+
phenotype2 : str, optional
572+
Second phenotype name.
573+
574+
Returns
575+
-------
576+
str
577+
Drug recommendation.
578+
579+
Examples
580+
--------
581+
582+
>>> import pypgx
583+
>>> # Codeine, an opiate and prodrug of morphine, is metabolized by CYP2D6
584+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Normal Metabolizer')
585+
'Use codeine label recommended age- or weight-specific dosing.'
586+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Ultrarapid Metabolizer')
587+
'Avoid codeine use because of potential for serious toxicity. If opioid use is warranted, consider a non-tramadol opioid.'
588+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Poor Metabolizer')
589+
'Avoid codeine use because of possibility of diminished analgesia. If opioid use is warranted, consider a non-tramadol opioid.'
590+
>>> pypgx.get_recommendation('codeine', 'CYP2D6', 'Indeterminate')
591+
'None'
592+
>>> # It's possible to have an altered recommendation for Normal Metabolizer
593+
>>> pypgx.get_recommendation('tacrolimus', 'CYP3A5', 'Normal Metabolizer')
594+
'Increase starting dose 1.5 to 2 times recommended starting dose. Total starting dose should not exceed 0.3 mg/kg/day. Use therapeutic drug monitoring to guide dose adjustments.'
595+
>>> # Some recommendations are determined by multiple genes (the order doesn't matter)
596+
>>> pypgx.get_recommendation('fluvastatin', 'CYP2C9', 'Normal Metabolizer')
597+
/Users/sbslee/Desktop/pypgx/pypgx/api/core.py:633: UserWarning: Recommendations for fluvastatin are determined by multiple genes (CYP2C9, SLCO1B1); for best results, specify phenotype for each gene
598+
warnings.warn(message)
599+
'Prescribe desired starting dose and adjust doses of fluvastatin based on disease-specific guidelines.'
600+
>>> pypgx.get_recommendation('fluvastatin', 'SLCO1B1', 'Normal Function')
601+
/Users/sbslee/Desktop/pypgx/pypgx/api/core.py:633: UserWarning: Recommendations for fluvastatin are determined by multiple genes (CYP2C9, SLCO1B1); for best results, specify phenotype for each gene
602+
warnings.warn(message)
603+
'Prescribe desired starting dose and adjust doses of fluvastatin based on disease-specific guidelines.'
604+
>>> pypgx.get_recommendation('fluvastatin', 'CYP2C9', 'Normal Metabolizer', 'SLCO1B1', 'Normal Function')
605+
'Prescribe desired starting dose and adjust doses of fluvastatin based on disease-specific guidelines.'
606+
>>> pypgx.get_recommendation('fluvastatin', 'SLCO1B1', 'Normal Function', 'CYP2C9', 'Normal Metabolizer')
607+
'Prescribe desired starting dose and adjust doses of fluvastatin based on disease-specific guidelines.'
608+
"""
609+
if gene1 not in list_genes(mode='all'):
610+
raise sdk.utils.GeneNotFoundError(gene1)
611+
612+
if gene2 is not None and gene2 not in list_genes(mode='all'):
613+
raise sdk.utils.GeneNotFoundError(gene2)
614+
615+
if phenotype1 not in list_phenotypes(gene1):
616+
l = ', '.join([f"'{x}'" for x in list_phenotypes(gene1)])
617+
raise sdk.utils.PhenotypeNotFoundError(f"{phenotype1} in {gene1} (choices: {l})")
618+
619+
if phenotype2 is not None and phenotype2 not in list_phenotypes(gene2):
620+
l = ', '.join([f"'{x}'" for x in list_phenotypes(gene2)])
621+
raise sdk.utils.PhenotypeNotFoundError(f"{phenotype2} in {gene2} (choices: {l})")
622+
623+
df = load_recommendation_table()
624+
625+
if drug not in df.Drug.unique():
626+
raise ValueError(f"Drug not found: {drug}")
627+
628+
df = df[df.Drug == drug]
629+
630+
target_genes = set(df.Gene1.to_list() + df.Gene2.to_list())
631+
632+
if gene1 not in target_genes:
633+
raise ValueError(f"{gene1} does not have any recommendations for {drug}")
634+
635+
if gene2 is not None and gene2 not in target_genes:
636+
raise ValueError(f"{gene2} does not have any recommendations for {drug}")
637+
638+
if df.Gene2.unique() == ['None']:
639+
return df[(df.Gene1 == gene1) & (df.Phenotype1 == phenotype1)].Recommendation.values[0]
640+
641+
if gene2 is None:
642+
message = (f"Recommendations for {drug} are determined by multiple genes "
643+
f"({', '.join(target_genes)}); for best results, specify phenotype for each gene")
644+
warnings.warn(message)
645+
if gene1 in df.Gene1.unique():
646+
return df[(df.Gene1 == gene1) & (df.Phenotype1 == phenotype1)].Recommendation.values[0]
647+
else:
648+
return df[(df.Gene2 == gene1) & (df.Phenotype2 == phenotype1)].Recommendation.values[0]
649+
650+
if gene1 in df.Gene1.unique():
651+
return df[(df.Gene1 == gene1) & (df.Phenotype1 == phenotype1) & (df.Gene2 == gene2) & (df.Phenotype2 == phenotype2)].Recommendation.values[0]
652+
else:
653+
return df[(df.Gene2 == gene1) & (df.Phenotype2 == phenotype1) & (df.Gene1 == gene2) & (df.Phenotype1 == phenotype2)].Recommendation.values[0]
654+
557655
def get_ref_allele(gene):
558656
"""
559657
Get the reference allele for target gene.
@@ -1161,6 +1259,31 @@ def load_phenotype_table():
11611259
b = BytesIO(pkgutil.get_data(__name__, 'data/phenotype-table.csv'))
11621260
return pd.read_csv(b)
11631261

1262+
def load_recommendation_table():
1263+
"""
1264+
Load the recommendation table.
1265+
1266+
Returns
1267+
-------
1268+
pandas.DataFrame
1269+
Requested table.
1270+
1271+
Examples
1272+
--------
1273+
1274+
>>> import pypgx
1275+
>>> df = pypgx.load_recommendation_table()
1276+
>>> df.head()
1277+
Drug Gene1 Phenotype1 Gene2 Phenotype2 Recommendation
1278+
0 tacrolimus CYP3A5 Normal Metabolizer None None Increase starting dose 1.5 to 2 times recommen...
1279+
1 tacrolimus CYP3A5 Intermediate Metabolizer None None Increase starting dose 1.5 to 2 times recommen...
1280+
2 tacrolimus CYP3A5 Possible Intermediate Metabolizer None None None
1281+
3 tacrolimus CYP3A5 Poor Metabolizer None None Initiate therapy with standard recommended dos...
1282+
4 tacrolimus CYP3A5 Indeterminate None None None
1283+
"""
1284+
b = BytesIO(pkgutil.get_data(__name__, 'data/recommendation-table.csv'))
1285+
return pd.read_csv(b)
1286+
11641287
def load_variant_table():
11651288
"""
11661289
Load the variant table.

0 commit comments

Comments
 (0)