Metadata-Version: 2.4
Name: PharmcatParser
Version: 0.1.0
Summary: Convert PharmCAT / pbStarPhase long-read PGx output into the Geneyx PGx JSON format.
Author: Bar Cohen
Author-email: Bar Cohen <bar@geneyx.com>
License: MIT License
        
        Copyright (c) 2026 Geneyx
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Project-URL: homepage, https://github.com/geneyx/PharmcatParser
Project-URL: repository, https://github.com/geneyx/PharmcatParser
Project-URL: documentation, https://geneyx.com/docs
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# PharmcatParser

Converts long-read pharmacogenomics output — PharmCAT, pbStarPhase, or a plain
Gene/Diplotype table — into the JSON format Geneyx Analysis consumes for PGx
reporting.

Install it next to your own PacBio or ONT pipeline, run it on the output, and
upload the result to Geneyx.

```bash
pip install PharmcatParser
pharmcat-parser HG002.pharmcat.report.json HG002.pbstarphase.json --output-json HG002.geneyx-pgx-results.json
```

## Output format

A JSON array, one entry per gene, with exactly four fields:

```json
[
  { "Id": "CYP2C19", "Name": "CYP2C19", "StarAllele": "*1/*1", "Activity": "Normal Metabolizer" }
]
```

- **`Id`** / **`Name`** — the gene symbol. Both are required; the Geneyx report
  keys its result set on `Id` and filters on `Name`.
- **`StarAllele`** — the **diplotype** (`*1/*2`).
- **`Activity`** — the **phenotype** / metaboliser status (`Normal Metabolizer`),
  or `null` when it is not known.

These names are matched case-sensitively on the Geneyx side. Do not rename them.

A second file, `<output>.provenance.json`, is written alongside the result. It
records the caller versions, the mapping-table versions used, per-gene warnings,
and any term that had no Geneyx mapping. It is not part of the upload contract —
it exists so a report can be traced back to what produced it.

## Supported inputs

| Input | Detected by | Provides |
|---|---|---|
| `*.pharmcat.report.json` | name or `pharmcatVersion` | diplotypes, phenotypes, tool + data versions |
| `*.pharmcat.phenotype.json` | name or `geneReports` | diplotypes, phenotypes |
| `*.pbstarphase.json` | name or `gene_details` | diplotypes only, for more genes than PharmCAT reports |
| `*.csv` / `*.json` table | fallback | Gene + Diplotype (+ optional Phenotype) |

The minimal table is the upload format: a header with **Gene** and **Diplotype**
is enough. Column names are matched loosely (`gene`, `geneSymbol`, `symbol`;
`diplotype`, `genotype`, `starAllele`).

## Why two files are better than one

PharmCAT only reports genes that have a CPIC or DPWG guideline. In a PacBio
HG002 run, pbStarPhase called 35 genes and PharmCAT reported 22. Four of the
dropped genes — **NAT2, CYP1A2, CYP2A13, CYP2C8** — are covered by the Geneyx
PGx report. Passing the pbStarPhase summary alongside the PharmCAT output
recovers them; they arrive with a diplotype and no phenotype.

Where both files describe the same gene, PharmCAT wins: it normalises
PharmVar sub-alleles (`*4.015`) to the core alleles (`*4`) that Geneyx uses.

## Merging rules

- **One entry per gene.** PharmCAT emits a gene report per phenotype source, so
  the same 22 genes appear under both CPIC and DPWG. One source is preferred
  and the other is consulted only as a fallback — see below.
- **Unmapped terms are dropped, not passed through.** A PharmCAT phenotype with
  no Geneyx equivalent yields `Activity: null` plus a warning in the provenance
  file, rather than an unrecognised term that looks valid to the report.
- **Genotype-guided genes** (IFNL3, VKORC1) take their `StarAllele` from the
  rewritten allele names rather than from the phenotype.
- **HLA** alleles are truncated to two fields (`*01:01:01:01` → `*01:01`).
- **Single-allele genes** (MT-RNR1) are not written as a diplotype.

## Choosing a phenotype source

PharmCAT phenotypes come from two guideline bodies, **CPIC** and **DPWG**, and
they do not always agree. Pick one:

```bash
pharmcat-parser HG002.pharmcat.report.json --phenotype-source DPWG
```

The default is **CPIC** (the first entry of `phenotype_source_preference` in
`gene_rules.json`). The choice only reorders the sources — it never narrows the
output. When the chosen source has no usable phenotype for a gene, the next
source in the default order is used instead, and the substitution is recorded:

```json
{ "Id": "CYP2B6", "phenotypeSource": "CPIC",
  "warnings": ["no usable phenotype from DPWG; taken from CPIC"] }
```

"No usable phenotype" covers three cases: the source reported none at all
(HG002 CPIC: CYP3A4, CYP4F2, VKORC1), it reported a no-call token such as
`n/a` (HG002 DPWG: CYP2B6), or its term has no Geneyx mapping yet (HG002 DPWG:
DPYD `2.0 (Normal Metabolizer)`).

The source selection affects `Activity` only — `StarAllele` is identical either
way, since both sources describe the same call. The preference actually used is
written to the provenance file as `phenotypeSourcePreference`.

## Mapping tables

The clinical vocabulary lives in `PharmcatParser/Mappings/` as versioned JSON:

| File | Contains |
|---|---|
| `gene_rules.json` | structural rules — source preference, HLA/sub-allele handling |
| `phenotype_terms.json` | PharmCAT phenotype term → Geneyx Activity term |
| `genotype_terms.json` | allele/diplotype rewrites for genotype-guided genes |

> **The term tables are incomplete.** Entries with a `null` target still need
> filling from the approved mapping sheet. Run the parser and read
> `unmappedTerms` in the provenance file to see exactly which terms are missing
> for your data.

## Development

```bash
pip install -e .
pytest PharmcatParser/Test/Test_PharmcatParser.py -v
```

Test fixtures are real PacBio output for **HG002**, a public GIAB reference
sample. No patient data belongs in this repository.
