Map GA4GH Phenopackets v2 to FHIR R4 Questionnaire / QuestionnaireResponse
Project description
phenopackets_fhir
Maps GA4GH Phenopackets v2 documents to FHIR R4 Questionnaire / QuestionnaireResponse resources.
Covered Phenopacket elements: Subject, PhenotypicFeature (HPO), Disease (MONDO / OMIM / ICD).
Setup
No external dependencies — standard library only.
# Clone or copy the phenopackets_fhir/ folder next to your scripts, then:
cd /path/to/Phenopackets
python3 -c "from phenopackets_fhir import build_questionnaire; print('OK')"
Quick start
1. Generate the FHIR Questionnaire definition
The Questionnaire is a static template — it describes the form structure (questions, types, answer options). Generate it once and store / 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",
"text": "Phenotypic Features",
"type": "group",
"repeats": true,
"item": [ ... ]
},
{
"linkId": "diseases",
"text": "Diseases",
"type": "group",
"repeats": true,
"item": [ ... ]
}
]
}
2. Map a Phenopacket to a QuestionnaireResponse
import json
from phenopackets_fhir import build_questionnaire, phenopacket_to_response
# Load your phenopacket
with open("phenopackets_fhir/example_phenopacket.json") as f:
phenopacket = json.load(f)
# Build both resources
questionnaire = build_questionnaire()
response = phenopacket_to_response(phenopacket, questionnaire)
print(json.dumps(response, indent=2))
Output snippet (Marfan syndrome example)
{
"resourceType": "QuestionnaireResponse",
"id": "phenopacket-marfan-001-response",
"questionnaire": "https://phenopackets.org/fhir/Questionnaire/phenopacket-v2|2.0",
"status": "completed",
"subject": { "reference": "Patient/patient-001" },
"item": [
{ "linkId": "phenopacket.id", "answer": [{ "valueString": "phenopacket-marfan-001" }] },
{ "linkId": "phenopacket.meta_created_by", "answer": [{ "valueString": "dr.smith@clinic.org" }] },
{
"linkId": "subject",
"item": [
{ "linkId": "subject.id", "answer": [{ "valueString": "patient-001" }] },
{ "linkId": "subject.date_of_birth", "answer": [{ "valueDate": "1985-07-14" }] },
{ "linkId": "subject.sex", "answer": [{ "valueCoding": { "code": "MALE" } }] },
{ "linkId": "subject.taxonomy", "answer": [{ "valueCoding": { "code": "NCBITaxon:9606", "display": "Homo sapiens" } }] }
]
},
{
"linkId": "phenotypic_features",
"item": [
{ "linkId": "phenotypic_feature.type", "answer": [{ "valueCoding": { "code": "HP:0002751", "display": "Kyphoscoliosis" } }] },
{ "linkId": "phenotypic_feature.excluded", "answer": [{ "valueBoolean": false }] },
{ "linkId": "phenotypic_feature.onset_ontology", "answer": [{ "valueCoding": { "code": "HP:0011463", "display": "Childhood onset" } }] },
{ "linkId": "phenotypic_feature.severity", "answer": [{ "valueCoding": { "code": "HP:0012826", "display": "Moderate" } }] }
]
},
...
{
"linkId": "diseases",
"item": [
{ "linkId": "disease.term", "answer": [{ "valueCoding": { "code": "MONDO:0007947", "display": "Marfan syndrome" } }] },
{ "linkId": "disease.excluded","answer": [{ "valueBoolean": false }] },
{ "linkId": "disease.onset_ontology", "answer": [{ "valueCoding": { "code": "HP:0011463", "display": "Childhood onset" } }] }
]
}
]
}
Command-line interface
# Print the Questionnaire definition
python3 -m phenopackets_fhir.cli questionnaire
# Map a phenopacket file → QuestionnaireResponse
python3 -m phenopackets_fhir.cli map phenopackets_fhir/example_phenopacket.json
# Emit both Questionnaire + QuestionnaireResponse in one JSON object
python3 -m phenopackets_fhir.cli map phenopackets_fhir/example_phenopacket.json --with-questionnaire
# Save output to a file
python3 -m phenopackets_fhir.cli map phenopackets_fhir/example_phenopacket.json > response.json
Phenopacket input format
The mapper accepts protobuf-JSON (the standard 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" }
}
Onset variants
All four Phenopacket TimeElement forms are supported:
// Ontology class (HPO age of onset)
"onset": { "ontologyClass": { "id": "HP:0003577", "label": "Congenital onset" } }
// ISO 8601 age
"onset": { "age": { "iso8601duration": "P2Y6M" } }
// Calendar date
"onset": { "timestamp": "2010-03-15T00:00:00Z" }
// Age range (start is used)
"onset": { "ageRange": { "start": { "iso8601duration": "P5Y" }, "end": { "iso8601duration": "P10Y" } } }
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 |
File layout
Phenopackets/
├── phenopackets_fhir/
│ ├── __init__.py # Public API: build_questionnaire, phenopacket_to_response
│ ├── questionnaire.py # FHIR Questionnaire definition builder
│ ├── mapper.py # Phenopacket → QuestionnaireResponse mapper
│ ├── cli.py # Command-line interface
│ └── example_phenopacket.json # Marfan syndrome sample
├── questionnaire.json # Pre-built Questionnaire output
└── questionnaire_response.json # Pre-built response for the example
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phenopacket_fhir-0.1.0.tar.gz.
File metadata
- Download URL: phenopacket_fhir-0.1.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84a3249f1339deb1f0904649cf6ae9171be5c7d3716732112f60d90768fc9076
|
|
| MD5 |
9b24f07864c73d95892f8c2ed430a495
|
|
| BLAKE2b-256 |
a20f291a60be7cbd243ae2e6a5bc15c5b1c0d60b331cd2394dfd6ff015369454
|
File details
Details for the file phenopacket_fhir-0.1.0-py3-none-any.whl.
File metadata
- Download URL: phenopacket_fhir-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8df8e68f336bec314e058ae3838d37ee2d61e03dc8a16fe8c04de2f6626ac70
|
|
| MD5 |
0fedc371a6c6e0f6a104467df61a78e9
|
|
| BLAKE2b-256 |
d2408ccc2ba5a50b9cec400c571eef392eaabae5797a4d1d5376f952c6c33387
|