Skip to main content

Map GA4GH Phenopackets v2 to FHIR R4 Questionnaire / QuestionnaireResponse

Project description

phenopacket-fhir

PyPI version Python versions License: MIT Tests

pip install phenopacket-fhir

Maps GA4GH Phenopackets v2 documents to FHIR R4 Questionnaire / QuestionnaireResponse resources.

Covered Phenopacket elements: Subject, PhenotypicFeature (HPO), Disease (MONDO / OMIM / ICD). Zero runtime dependencies — stdlib only, Python ≥ 3.9.


Installation

pip install phenopacket-fhir

Or for development (includes pytest):

pip install "phenopacket-fhir[dev]"

Quick start

1. Generate the FHIR Questionnaire definition

The Questionnaire is a static template describing the form structure (questions, types, answer options). Generate it once and store or publish it.

import json
from phenopackets_fhir import build_questionnaire

questionnaire = build_questionnaire()
print(json.dumps(questionnaire, indent=2))
Output snippet
{
  "resourceType": "Questionnaire",
  "id": "phenopacket-v2",
  "url": "https://phenopackets.org/fhir/Questionnaire/phenopacket-v2",
  "version": "2.0",
  "title": "GA4GH Phenopacket v2 — Clinical Phenotyping Form",
  "status": "active",
  "item": [
    { "linkId": "phenopacket.id", "text": "Phenopacket identifier", "type": "string", "required": true },
    {
      "linkId": "subject",
      "text": "Subject (Individual)",
      "type": "group",
      "required": true,
      "item": [
        { "linkId": "subject.id",            "text": "Patient / subject identifier", "type": "string" },
        { "linkId": "subject.date_of_birth", "text": "Date of birth",               "type": "date"   },
        { "linkId": "subject.sex",           "text": "Biological sex",              "type": "choice" }
      ]
    },
    { "linkId": "phenotypic_features", "type": "group", "repeats": true, "item": [ ... ] },
    { "linkId": "diseases",            "type": "group", "repeats": true, "item": [ ... ] }
  ]
}

2. Map a Phenopacket to a QuestionnaireResponse

import json
from phenopackets_fhir import build_questionnaire, phenopacket_to_response

phenopacket = {
    "id": "my-phenopacket-01",
    "subject": { "id": "patient-42", "sex": "FEMALE", "dateOfBirth": "1990-03-15" },
    "phenotypicFeatures": [
        {
            "type": { "id": "HP:0001250", "label": "Seizure" },
            "onset": { "ontologyClass": { "id": "HP:0003593", "label": "Infantile onset" } },
            "severity": { "id": "HP:0012826", "label": "Moderate" }
        }
    ],
    "diseases": [
        { "term": { "id": "MONDO:0005027", "label": "Epilepsy" }, "excluded": False }
    ],
    "metaData": { "phenopacketSchemaVersion": "2.0", "createdBy": "dr.jones" }
}

questionnaire = build_questionnaire()
response      = phenopacket_to_response(phenopacket, questionnaire)

print(json.dumps(response, indent=2))
Output snippet
{
  "resourceType": "QuestionnaireResponse",
  "id": "my-phenopacket-01-response",
  "questionnaire": "https://phenopackets.org/fhir/Questionnaire/phenopacket-v2|2.0",
  "status": "completed",
  "subject": { "reference": "Patient/patient-42" },
  "item": [
    { "linkId": "phenopacket.id", "answer": [{ "valueString": "my-phenopacket-01" }] },
    {
      "linkId": "subject",
      "item": [
        { "linkId": "subject.id",            "answer": [{ "valueString": "patient-42" }] },
        { "linkId": "subject.date_of_birth", "answer": [{ "valueDate": "1990-03-15" }] },
        { "linkId": "subject.sex",           "answer": [{ "valueCoding": { "code": "FEMALE" } }] }
      ]
    },
    {
      "linkId": "phenotypic_features",
      "item": [
        { "linkId": "phenotypic_feature.type",           "answer": [{ "valueCoding": { "code": "HP:0001250", "display": "Seizure" } }] },
        { "linkId": "phenotypic_feature.onset_ontology", "answer": [{ "valueCoding": { "code": "HP:0003593", "display": "Infantile onset" } }] },
        { "linkId": "phenotypic_feature.severity",       "answer": [{ "valueCoding": { "code": "HP:0012826", "display": "Moderate" } }] }
      ]
    },
    {
      "linkId": "diseases",
      "item": [
        { "linkId": "disease.term",     "answer": [{ "valueCoding": { "code": "MONDO:0005027", "display": "Epilepsy" } }] },
        { "linkId": "disease.excluded", "answer": [{ "valueBoolean": false }] }
      ]
    }
  ]
}

3. Load from a JSON file

import json
from phenopackets_fhir import build_questionnaire, phenopacket_to_response

with open("my_phenopacket.json") as f:
    phenopacket = json.load(f)

response = phenopacket_to_response(phenopacket, build_questionnaire())

with open("response.json", "w") as f:
    json.dump(response, f, indent=2)

Command-line interface

After pip install phenopacket-fhir a phenopacket-fhir command is available:

# Print the Questionnaire definition
phenopacket-fhir questionnaire

# Map a phenopacket file → QuestionnaireResponse
phenopacket-fhir map my_phenopacket.json

# Emit both Questionnaire + QuestionnaireResponse together
phenopacket-fhir map my_phenopacket.json --with-questionnaire

# Save to a file
phenopacket-fhir map my_phenopacket.json > response.json

You can also invoke it as a module if you prefer:

python -m phenopackets_fhir.cli map my_phenopacket.json

Phenopacket input format

The mapper accepts protobuf-JSON (the standard Phenopacket wire format). Field names are camelCase as produced by MessageToJson() or any GA4GH Phenopacket SDK.

Minimal valid input

{
  "id": "my-phenopacket-01",
  "subject": { "id": "patient-42", "sex": "FEMALE" },
  "phenotypicFeatures": [
    { "type": { "id": "HP:0001250", "label": "Seizure" } }
  ],
  "diseases": [
    { "term": { "id": "MONDO:0005027", "label": "Epilepsy" } }
  ],
  "metaData": { "phenopacketSchemaVersion": "2.0" }
}

Supported onset variants

All five Phenopacket TimeElement forms are handled:

{ "onset": { "ontologyClass":  { "id": "HP:0003577", "label": "Congenital onset" } } }
{ "onset": { "age":            { "iso8601duration": "P2Y6M" } } }
{ "onset": { "ageRange":       { "start": { "iso8601duration": "P5Y" }, "end": { "iso8601duration": "P10Y" } } } }
{ "onset": { "timestamp":      "2010-03-15T00:00:00Z" } }
{ "onset": { "gestationalAge": { "weeks": 32, "days": 3 } } }

Questionnaire structure

linkId Type Repeats Notes
phenopacket.id string Required
phenopacket.meta_created_by string
phenopacket.meta_created dateTime
subject group Required
subject.id string
subject.date_of_birth date
subject.sex choice FEMALE / MALE / OTHER_SEX / UNKNOWN_SEX
subject.karyotypic_sex choice XX / XY / XO / XXY …
subject.taxonomy open-choice NCBITaxon answerOption
subject.vital_status choice ALIVE / DECEASED / UNKNOWN_STATUS
phenotypic_features group One group per feature
phenotypic_feature.type open-choice HPO value set
phenotypic_feature.excluded boolean Negated observation
phenotypic_feature.onset_ontology choice HPO onset terms
phenotypic_feature.onset_age string ISO 8601 duration
phenotypic_feature.onset_date date
phenotypic_feature.severity choice HPO severity terms
phenotypic_feature.modifiers open-choice HPO modifier terms
diseases group One group per disease
disease.term open-choice MONDO / OMIM / ICD
disease.excluded boolean Rule-out diagnosis
disease.onset_ontology choice HPO onset terms
disease.onset_age string ISO 8601 duration
disease.onset_date date
disease.disease_stage open-choice TNM / cancer staging
disease.primary_site open-choice Anatomical site
disease.laterality choice Right / Left / Unilateral / Bilateral

Contributing

git clone https://github.com/schmitzdonatien/phenopacket-fhir.git
cd phenopacket-fhir
pip install -e ".[dev]"
pytest

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

phenopacket_fhir-0.1.1.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

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

phenopacket_fhir-0.1.1-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file phenopacket_fhir-0.1.1.tar.gz.

File metadata

  • Download URL: phenopacket_fhir-0.1.1.tar.gz
  • Upload date:
  • Size: 13.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for phenopacket_fhir-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a618b16cc0136c10ba230b1d191776056b57e0b5fa9d42ec21324b518e1f1e4d
MD5 1aa6d53b7cf26b0b92399a88df7c29fd
BLAKE2b-256 0291119031c0cdac5027a00d1d37e459b8da5bebf054df18e2c298537bad153f

See more details on using hashes here.

File details

Details for the file phenopacket_fhir-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for phenopacket_fhir-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 05d48b0007a293b596a34f8bfc805bb8e98898f4ba6585e40cd7b9200e5466ec
MD5 4f3b296ffb0269c9ff1ce4ac0ac81ee0
BLAKE2b-256 1e4d264e32ecda229a9206c04e6625f373c1c7acc99dc8a75d192e13b5024cea

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