def individual_to_fhir(obj): """Converts Individual to FHIR Patient. :param obj: Individual json :return: FHIR Patient json """ # first validate if phenopackets object is well-formed schema_path = os.path.join(SCHEMA_PATH, 'individual_schema.json') try: validate_schema(schema_path, obj) except jsonschema.exceptions.ValidationError: raise Exception("The individual object is not valid.") patient = p.Patient() patient.id = obj['id'] patient.birthDate = fhirdate.FHIRDate(obj.get('dateOfBirth', None)) patient.gender = obj.get('sex', None) patient.active = obj.get('active', None) patient.deceasedBoolean = obj.get('deceased', None) patient.extension = list() # age if 'age' in obj: age_extension = age_to_fhir( obj, PHENOPACKETS_ON_FHIR_MAPPING['individual']['age'], 'age') patient.extension.append(age_extension) # karyotypic_sex if 'karyotypicSex' in obj: karyotypic_sex_extension = extension.Extension() karyotypic_sex_extension.url = PHENOPACKETS_ON_FHIR_MAPPING[ 'individual']['karyotypicSex']['url'] karyotypic_sex_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) karyotypic_sex_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('karyotypicSex', None) coding.code = obj.get('karyotypicSex', None) coding.system = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypicSex']['system'] karyotypic_sex_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(karyotypic_sex_extension) # taxonomy if 'taxonomy' in obj: taxonomy_extension = extension.Extension() taxonomy_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'taxonomy'] taxonomy_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) taxonomy_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('taxonomy', None).get('label', None) coding.code = obj.get('taxonomy', None).get('id', None) taxonomy_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(taxonomy_extension) return patient.as_json()
def add_phased_relationship_obv(self): patient_reference = reference.FHIRReference( {"reference": "Patient/" + self.patientID}) self.sequence_rels \ = get_sequence_relation(self.phased_rec_map) for index in self.sequence_rels.index: siduid = "sid-" + uuid4().hex[:13] self.result_ids.append(siduid) observation_sid = observation.Observation() observation_sid.resource_type = "Observation" observation_sid.id = siduid observation_sid.meta = meta.Meta({ "profile": [("http://hl7.org/fhir/uv/" + "genomics-reporting/" + "StructureDefinition/" + "sequence-phase-relationship")] }) observation_sid.status = "final" observation_sid.category = [ concept.CodeableConcept({ "coding": [{ "system": ("http://terminology.hl7.org/" + "CodeSystem/observation-category"), "code": "laboratory" }] }) ] observation_sid.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "82120-7", "display": "Allelic phase" }] }) observation_sid.subject = patient_reference observation_sid.valueCodeableConcept = concept.CodeableConcept({ "coding": [{ "system": ("http://hl7.org/fhir/uv/" + "genomics-reporting/" + "CodeSystem/seq-phase-relationship"), "code": self.sequence_rels.at[index, 'Relation'], "display": self.sequence_rels.at[index, 'Relation'] }] }) self.report.contained.append(observation_sid)
def get_codeable_concept(system, code, display=None): codeable_concept = {"coding": [{}]} codeable_concept['coding'][0]['system'] = system codeable_concept['coding'][0]['code'] = code if display is not None: codeable_concept['coding'][0]['display'] = display return concept.CodeableConcept(codeable_concept)
def to_fhir(self): route_code = codeableconcept.CodeableConcept() route_code.coding = [ route_coding.to_fhir() for route_coding in self.coding ] return route_code
def _get_section_object(nested_obj, title): """Internal function to convert phenopacket m2m objects to Composition section. :param nested_obj: m2m relationship object :param title: field name that holds m2m relationship :return: section content object """ section_content = comp.CompositionSection() section_values = PHENOPACKETS_ON_FHIR_MAPPING['phenopacket'][title] section_content.title = section_values['title'] section_content.code = codeableconcept.CodeableConcept() section_content.code.coding = [] coding = c.Coding() coding.system = section_values['code']['system'] coding.version = section_values['code']['version'] coding.code = section_values['code']['code'] coding.display = section_values['code']['display'] section_content.code.coding.append(coding) section_content.entry = [] for item in nested_obj: entry = fhirreference.FHIRReference() if item.get('id'): entry.reference = str(item['id']) elif item.get('uri'): entry.reference = item['uri'] else: # generate uuid when no 'id' or 'uri' present entry.reference = str(uuid.uuid1()) section_content.entry.append(entry) return section_content
def __init__(self, Organization=None): """ Uses fhirclient.models to create and post practitoner resource. Currently, using class variables. :param smart: fhirclient.client.FHIRClient object. :returns: practitioner id created by server """ if Organization is None: self.Organization = generateorganization.GenerateOrganization( ).Organization else: self.Organization = Organization Practitioner = pr.Practitioner() PractitionerQualification = pr.PractitionerQualification() CodeableConcept = cc.CodeableConcept() Coding = c.Coding() Coding.code = random.choice(['MD', 'DO']) Coding.system = 'https://www.hl7.org/fhir/v2/0360/2.7/index.html' CodeableConcept.coding = [Coding] PractitionerQualification.code = CodeableConcept Practitioner.qualification = [PractitionerQualification] name = hn.HumanName() self.family, self.given, Practitioner.gender = self._generate_person() name.family = [self.family] name.given = [self.given] Practitioner.name = name self._validate(Practitioner) self.response = self.post_resource(Practitioner) Practitioner.id = self._extract_id() self.Practitioner = Practitioner print(self)
def annotate(self, obsid): obs = o.Observation() obs.uuid = uuid.uuid4().urn observation = o.Observation.read(obsid, self.smart.server) obs.specimen = observation.specimen obs.related = observation.related obs.basedOn = observation.basedOn obs.code = observation.code obs.component = observation.component obs.method = observation.method seq_id = observation.related[0].target.reference.split("/")[1] seq = s.Sequence.read(seq_id, self.smart.server) obseverved_seq = seq.observedSeq annotation = self.gfeapi.annotate_get(obseverved_seq, imgthla_version="3.31.0") gfe = annotation.gfe bodysite3 = cc.CodeableConcept() bodySiteCoding3 = mkCoding(system='http://act.b12x.org', code='261063000', version="0.0.5") bodysite3.coding = [bodySiteCoding3] bodysite3.text = gfe obs.valueCodeableConcept = bodysite3 obs.status = 'final' obs.subject = observation.subject return obs
def category(self): return [cc.CodeableConcept({ "coding": [{ "system": "http://hl7.org/fhir/observation-category", "code": "vital-signs", "display": "Vital Signs" }] })]
def fhir_specimen(obj): """ Converts biosample to FHIR Specimen. """ specimen = s.Specimen() specimen.identifier = [] # id identifier = fhir_indentifier.Identifier() identifier.value = obj['id'] specimen.identifier.append(identifier) # individual - subject property in FHIR is mandatory for a specimen specimen.subject = fhirreference.FHIRReference() specimen.subject.reference = obj.get('individual', 'unknown') # sampled_tissue specimen.type = codeableconcept.CodeableConcept() specimen.type.coding = [] coding = c.Coding() coding.code = obj['sampled_tissue']['id'] coding.display = obj['sampled_tissue']['label'] specimen.type.coding.append(coding) # description if 'description' in obj.keys(): specimen.note = [] annotation = a.Annotation() annotation.text = obj.get('description', None) specimen.note.append(annotation) # procedure specimen.collection = s.SpecimenCollection() specimen.collection.method = fhir_codeable_concept( obj['procedure']['code']) if 'body_site' in obj['procedure'].keys(): specimen.collection.bodySite = fhir_codeable_concept( obj['procedure']['body_site']) # Note on taxonomy from phenopackets specs: # Individuals already contain a taxonomy attribute so this attribute is not needed. # extensions specimen.extension = [] # individual_age_at_collection if 'individual_age_at_collection' in obj.keys(): ind_age_at_collection_extension = fhir_age( obj, PHENOPACKETS_ON_FHIR_MAPPING['biosample'] ['individual_age_at_collection'], 'individual_age_at_collection') specimen.extension.append(ind_age_at_collection_extension) concept_extensions = codeable_concepts_fields([ 'histological_diagnosis', 'tumor_progression', 'tumor_grade', 'diagnostic_markers' ], 'biosample', obj) for concept in concept_extensions: specimen.extension.append(concept) if 'is_control_sample' in obj.keys(): control_extension = extension.Extension() control_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['biosample'][ 'is_control_sample'] control_extension.valueBoolean = obj['is_control_sample'] specimen.extension.append(control_extension) # TODO 2m extensions - references return specimen.as_json()
def category(self): return cc.CodeableConcept({ "coding": [{ "system": "http://hl7.org/fhir/observation-category", "code": "activity", "display": "Activity" }], "text": "Activity" })
def code(self): return cc.CodeableConcept({ "coding": [{ "system": "https://r.details.loinc.org/LOINC", "code": "67775-7", "display": "Level of responsiveness" }], "text": "Level of responsiveness" })
def fhir_patient(obj): """ Converts Individual to FHIR Patient. """ patient = p.Patient() patient.id = obj['id'] patient.birthDate = fhirdate.FHIRDate(obj.get('date_of_birth', None)) patient.gender = obj.get('sex', None) patient.active = obj.get('active', None) patient.deceasedBoolean = obj.get('deceased', None) patient.extension = list() # age if 'age' in obj.keys(): age_extension = fhir_age( obj, PHENOPACKETS_ON_FHIR_MAPPING['individual']['age'], 'age') patient.extension.append(age_extension) # karyotypic_sex karyotypic_sex_extension = extension.Extension() karyotypic_sex_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypic_sex']['url'] karyotypic_sex_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) karyotypic_sex_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('karyotypic_sex', None) coding.code = obj.get('karyotypic_sex', None) coding.system = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypic_sex']['system'] karyotypic_sex_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(karyotypic_sex_extension) # taxonomy if 'taxonomy' in obj.keys(): taxonomy_extension = extension.Extension() taxonomy_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'taxonomy'] taxonomy_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) taxonomy_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('taxonomy', None).get('label', None) coding.code = obj.get('taxonomy', None).get('id', None) taxonomy_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(taxonomy_extension) return patient.as_json()
def interpretation(self): return cc.CodeableConcept({ "coding": [ { "system": "http://hl7.org/fhir/v2/0078", "code": "H", "display": "High" } ] })
def interpretation(self): return cc.CodeableConcept({ "coding": [ { "system": "http://hl7.org/fhir/v2/0078", "code": "N", "display": "Normal" } ], "text": "Normal (applies to non-numeric results)" })
def _get_region_studied_component(self, reportable_query_regions, nocall_regions): observation_rs_components = [] for _, row in reportable_query_regions.df.iterrows(): obv_comp = observation.ObservationComponent() obv_comp.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "51959-5", "display": "Ranges-examined component" }] }) obv_comp.valueRange = valRange.Range({ "low": { "value": np.float(row['Start']) + 1 }, "high": { "value": np.float(row['End']) + 1 } }) observation_rs_components.append(obv_comp) for _, row in nocall_regions.df.iterrows(): obv_comp = observation.ObservationComponent() obv_comp.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "TBD-UncallableRegions", "display": "Uncallable region" }] }) obv_comp.valueRange = valRange.Range({ "low": { "value": np.float(row['Start']) + 1 }, "high": { "value": np.float(row['End']) + 1 } }) observation_rs_components.append(obv_comp) return observation_rs_components
def category(self): return [ cc.CodeableConcept({ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs", "display": "Vital Signs" }], "text": "Vital Signs" }) ]
def fhir_codeable_concept(obj): """ Generic function to convert object to FHIR CodeableConcept. """ codeable_concept = codeableconcept.CodeableConcept() codeable_concept.coding = [] if isinstance(obj, list): for item in obj: coding = fhir_coding_util(item) codeable_concept.coding.append(coding) else: coding = fhir_coding_util(obj) codeable_concept.coding.append(coding) return codeable_concept
def _create_FHIRCodeableConcept(self, code, system=None, display=None): """ Creates and returns a FHIRCodeableConcept object. References self._create_FHIRCoding() :param self: :param code: code from standard System :param system: coding System :param display: how the resource should be displayed :returns: CodeableConcept FHIR object """ CodeableConcept = cc.CodeableConcept() Coding = self._create_FHIRCoding(code, system, display) CodeableConcept.coding = [Coding] return CodeableConcept
def map_cc(concept): # create CodeableConcept based on slot data cc = CC.CodeableConcept() cc.coding = [] cc.text = concept.text try: cc_coding = Coding.Coding() for translation in concept.coding: cc_coding.code = translation.code cc_coding.display = translation.display cc_coding.system = translation.system cc.coding.append(cc_coding) except TypeError: # coding missing pass return (cc)
def mksequence(): """ make a Sequence resource using the data model """ import fhirclient.models.sequence as s sequence = s.Sequence({ # 'id': 'seq-1', 'coordinateSystem': 0 }) # adding uuid attribute to the sequence object # for later use in building bundles and referencing # resources with fullUrl sequence.uuid = uuid.uuid4().urn import fhirclient.models.coding as c coding = c.Coding() coding.system = 'http://www.ebi.ac.uk/ipd/imgt/hla/' coding.version = '3.23' coding.display = 'HLA-A*01:01:01:01' coding.code = 'HLA00001' import fhirclient.models.codeableconcept as cc codecon = cc.CodeableConcept() codecon.coding = [coding] codecon.text = 'HLA-A*01:01:01:01' refseq = s.SequenceReferenceSeq() refseq.referenceSeqId = codecon refseq.windowStart = 503 refseq.windowEnd = 773 sequence.type = 'dna' sequence.referenceSeq = refseq sequence.observedSeq = ( 'GCTCCCACTCCATGAGGTATTTCTTCACATCCGTGTCCCGGCCCGGCCGCGGGGAGCCCC' 'GCTTCATCGCCGTGGGCTACGTGGACGACACGCAGTTCGTGCGGTTCGACAGCGACGCCG' 'CGAGCCAGAAGATGGAGCCGCGGGCGCCGTGGATAGAGCAGGAGGGGCCGGAGTATTGGG' 'ACCAGGAGACACGGAATATGAAGGCCCACTCACAGACTGACCGAGCGAACCTGGGGACCC' 'TGCGCGGCTACTACAACCAGAGCGAGGACG') import fhirclient.models.narrative as n narrative = n.Narrative() narrative.div = ('<div xmlns="http://www.w3.org/1999/xhtml">' '<pre>HLA-A*01:01:01:01, exon 3</pre>' '</div>') narrative.status = 'generated' sequence.text = narrative return sequence
def _add_codeable_value(self, Observation, measurement): """ Adds a codeableconcept value object to Observation. :param Observation: fhirclient.models.observation.Observation object :param measurement: measurement dictionary :returns: Observation FHIR object """ CodeableConcept = cc.CodeableConcept() Coding = c.Coding() Coding.system = 'http://loinc.org' Coding.code = self.observation_dict[measurement]['value_loinc'] Coding.display = self.observation_dict[measurement]['value_display'] CodeableConcept.coding = [Coding] Observation.valueCodeableConcept = CodeableConcept return Observation
def build_keyword(study_keywords): """ Build the keywords up :param keywords: :return: """ keywords = [] for term in study_keywords: cc = codeableconcept.CodeableConcept() cc.text = term cc.coding = [ coding.Coding( dict(code=quote(term), system="https://example.org", display=term)) ] keywords.append(cc) return keywords
def initalize_report(self): patient_reference = reference.FHIRReference( {"reference": "Patient/" + self.patientID}) self.report.id = "dr-" + uuid4().hex[:13] self.report.meta = meta.Meta({ "profile": [("http://hl7.org/fhir/uv/genomics-reporting" + "/StructureDefinition/genomics-report")] }) self.report.status = "final" self.report.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "81247-9", "display": "Master HL7 genetic variant reporting panel" }] }) self.report.subject = patient_reference self.report.issued = date.FHIRDate(get_fhir_date()) self.report.contained = []
def build_focus(mesh_terms): """ Build the ResearchStudy.focus :param conditions: :param interventions: :return: """ # assuming mesh term here focus = [] for study_term_type, terms in mesh_terms.items(): print("{}: {}".format(study_term_type, terms)) for term in terms: cc = codeableconcept.CodeableConcept() cc.text = term cc.coding = [ coding.Coding( dict(code=term, system="https://mesh.org", display="")) ] focus.append(cc) return focus
def write(server_url, system, code, patient, value): observation = o.Observation() observation.status = "final" observation.subject = fr.FHIRReference() observation.subject.reference = ("Patient/%s" % patient) observation.code = cc.CodeableConcept() tmp = c.Coding() tmp.system = system tmp.code = code observation.code.coding = [tmp] observation.valueString = str(value) observation.effectiveDateTime = fd.FHIRDate("2017-11-28T00:00:00+00:00") #write json obj json_obj = observation.as_json() json_obj["resourceType"] = "Observation" print(json.dumps(json_obj)) requests.post(server_url + "Observation", json=json_obj)
def addObservationToServer(self, patient_id, value_code, value_unit, value_quantity, coding_code, coding_display, coding_system, timestamp): observation = o.Observation() # Create Value Quantity quantity = q.Quantity() quantity.code = value_code quantity.unit = value_unit quantity.value = value_quantity observation.valueQuantity = quantity # Create Coding code = cc.CodeableConcept() coding_item = c.Coding() coding_item.code = coding_code coding_item.display = coding_display coding_item.system = coding_system coding_list = [coding_item] code.coding = coding_list observation.code = code # Create Subject reference = r.FHIRReference() reference.reference = self.getPatientById(patient_id).relativePath() observation.subject = reference # Create Status observation.status = 'final' # Create Issued/EffectiveDateTime observation.effectiveDateTime = d.FHIRDate(timestamp) # Write the observation result_json = observation.create(self.smart.server) observation.id = self.getCreatedId(result_json) return observation.id
def _get_section_object(nested_obj, title): """ Internal function to convert phenopacket m2m objects to Composition section. """ section_content = comp.CompositionSection() section_values = PHENOPACKETS_ON_FHIR_MAPPING['phenopacket'][title] section_content.title = section_values['title'] section_content.code = codeableconcept.CodeableConcept() section_content.code.coding = [] coding = c.Coding() coding.system = section_values['code']['system'] coding.version = section_values['code']['version'] coding.code = section_values['code']['code'] coding.display = section_values['code']['display'] section_content.code.coding.append(coding) section_content.entry = [] for item in nested_obj: entry = fhirreference.FHIRReference() if item.get('id'): entry.reference = str(item['id']) else: entry.reference = item['uri'] section_content.entry.append(entry) return section_content
def writeMedProfile(meds_medication, meds_frequencyPerYear, meds_fractionOfSubjects, meds_correlatedLabsCoefficients, meds_correlatedMedsCoefficients, meds_correlatedProceduresCoefficients, meds_correlatedDiagnosisCoefficients, meds_correlatedPhenotypesCoefficients, cohort='All', sex='All', race='All', age_low='All', age_high=None, topN=10, correlationCutoff=0.3): """Write out Medication Clinical Profile to JSON File and save locally Keywords: Structures from output of calculateAnyProfile(profileType='medications') cohort -- short name for cohort, special characters besides hyphens are prohibited (default 'All') sex -- specification of whether this is a 'All', 'Male', or 'Female' sex profile (default 'All') race -- specification of whether this is 'All', 'White or Caucasian', 'Black or African American', 'Other' race profile (default 'All') age_low -- low age range for this profile (default 'All') age_high -- high age range for this profile (default None) topN -- integer representing the maximum number of correlations to report in the profile, ranked descending (default 10) correlationCutoff -- minimum correlation coefficient value to report for whole profile (default 0.3) """ import os import sys import sqlalchemy import urllib.parse import pandas as pd import numpy as np import getpass from dataclasses import dataclass from SciServer import Authentication from fhirclient.models import clinicalprofile, fhirreference, identifier, codeableconcept, fhirdate, quantity from datetime import datetime import json from fhir_loader import fhir_loader import pymssql # Initialize profile clinicalProfile = clinicalprofile.ClinicalProfile() if sex == 'M': sex = 'Male' elif sex == 'F': sex = 'Female' # Header info if (age_low != 'All'): clinicalProfile.id = ('jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) clinicalProfile.identifier = [ identifier.Identifier({ 'value': ('jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) }) ] clinicalProfile.cohort = fhirreference.FHIRReference({ 'reference': ('Group/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) }) else: clinicalProfile.id = 'jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( age_low) clinicalProfile.identifier = [ identifier.Identifier({ 'value': 'jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(age_low) }) ] clinicalProfile.cohort = fhirreference.FHIRReference({ 'reference': ('Group/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(age_low)) }) clinicalProfile.status = 'draft' clinicalProfile.population = fhirreference.FHIRReference( {'reference': 'Group/jh-medications-' + cohort}) clinicalProfile.date = fhirdate.FHIRDate( str(datetime.now()).replace(' ', 'T')) clinicalProfile.reporter = fhirreference.FHIRReference({ 'reference': 'Organization/JHM', 'type': 'Organization', 'display': 'Johns Hopkins School of Medicine' }) meds = list() meds_medication = [x for x in meds_medication if str(x) != 'nan'] for thisMed in meds_medication: thisCPMed = clinicalprofile.ClinicalProfileMedication() try: thisCPMed.medicationCodeableConcept = codeableconcept.CodeableConcept( dict(coding=[ dict(system='http://www.nlm.nih.gov/research/umls/rxnorm/', code=str(thisMed)) ])) # meds_dosageInfo # thisCPMed.dose = quantity.Quantity(dict(unit=str(meds_dosageInfo.loc[thisMed]))) thisCPMed.frequencyPerYear = round( float(meds_frequencyPerYear.loc[thisMed].mean()), 3) thisCPMed.fractionOfSubjects = round( float(meds_fractionOfSubjects.loc[thisMed].mean()), 3) try: topNcorrs = (pd.DataFrame( meds_correlatedLabsCoefficients.loc[thisMed].groupby([ 'LAB_LOINC' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherLab = [(dict( coding=[dict(system='http://loinc.org', code=code)]))] entries.append(dict(labcode=otherLab, coefficient=corr)) if not entries: print('No correlated Labs for Med ', thisMed) else: thisCPMed.correlatedLabs = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedLabs(dict(topn=topN, entry=entries)) except: print('No correlated Labs for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedDiagnosisCoefficients.loc[thisMed].groupby([ 'DX' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherDX = (dict(coding=[ dict(system='http://www.icd10data.com/', code=code) ])) entries.append(dict(code=otherDX, coefficient=corr)) if not entries: print('No correlated Diagnoses for Med ', thisMed) else: thisCPMed.correlatedDiagnoses = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedDiagnoses( dict(topn=topN, entry=entries)) except: print('No correlated DX for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedProceduresCoefficients.loc[thisMed].groupby( ['RAW_PX' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherProc = [(dict(coding=[ dict(system= 'http://www.ama-assn.org/practice-management/cpt', code=code) ]))] entries.append(dict(code=otherProc, coefficient=corr)) if not entries: print('No correlated Procedures for Med ', thisMed) else: thisCPMed.correlatedProcedures = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedProcedures( dict(topn=topN, entry=entries)) except: print('No correlated Procedures for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedMedsCoefficients.loc[thisMed].groupby([ 'JH_INGREDIENT_RXNORM_CODE' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherMed = [ dict(medicationCodeableConcept=dict(coding=[ dict( system= 'http://www.nlm.nih.gov/research/umls/rxnorm/', code=code) ])) ] entries.append(dict(meds=otherMed, coefficient=corr)) if not entries: print('No correlated Meds for Med ', thisMed) else: thisCPMed.correlatedMedications = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedMedications( dict(topn=topN, entry=entries)) except: print('No correlated Meds for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedPhenotypesCoefficients.loc[thisMed].groupby( ['HPO' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherHPO = (dict(coding=[ dict(system='http://hpo.jax.org/app/', code=code) ])) entries.append(dict(code=otherHPO, coefficient=corr)) if not entries: print('No correlated Phenotypes for Med ', thisMed) else: thisCPMed.correlatedPhenotypes = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedPhenotypes( dict(topn=topN, entry=entries)) except: print('No correlated Phenotypes for Med ', thisMed) meds.append(thisCPMed) except Exception as e: print(e) print('This med did not work ', thisMed) clinicalProfile.medication = meds if age_high != None: filename = cohort + '_resources/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( int(age_low)) + '-' + str(int(age_high)) + '.json' else: filename = cohort + '_resources/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( age_low) + '.json' with open(filename, 'w') as outfile: json.dump(clinicalProfile.as_json(), outfile, indent=4) del (clinicalProfile) return print('Write to ' + filename + ' successful')
def writeLabProfile(labs_counts, labs_frequencyPerYear, labs_fractionOfSubjects,labs_units, labs_names, labs_stats, labs_aboveBelowNorm, labs_correlatedLabsCoefficients, labs_abscorrelation, labs_correlatedMedsCoefficients, labs_correlatedProceduresCoefficients, labs_correlatedDiagnosisCoefficients, labs_correlatedPhenotypesCoefficients, cohort='All', sex='All', race='All', age_low='All', age_high=None, topN=10, correlationCutoff=0.3): """Write out Lab Clinical Profile to JSON File and save locally Keywords: Structures from output of calculateAnyProfile(profileType='labs') cohort -- short name for cohort, special characters besides hyphens are prohibited (default 'All') sex -- specification of whether this is a 'All', 'Male', or 'Female' sex profile (default 'All') race -- specification of whether this is 'All', 'White or Caucasian', 'Black or African American', 'Other' race profile (default 'All') age_low -- low age range for this profile (default 'All') age_high -- high age range for this profile (default None) topN -- integer representing the maximum number of correlations to report in the profile, ranked descending (default 10) correlationCutoff -- minimum correlation coefficient value to report for whole profile (default 0.3) """ import os import sys import sqlalchemy import urllib.parse import pandas as pd import numpy as np import getpass from dataclasses import dataclass from SciServer import Authentication from datetime import datetime import json from fhir_loader import fhir_loader from fhirclient.models import clinicalprofile, fhirreference, identifier, codeableconcept, fhirdate, quantity import pymssql # Initialize profile clinicalProfile = clinicalprofile.ClinicalProfile() clinicalProfile.resourceType = 'ClinicalProfile' if sex == 'M': sex = 'Male' elif sex =='F': sex = 'Female' # Header info if (age_low != 'All'): clinicalProfile.id = 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low))+'-'+str(int(age_high)) clinicalProfile.identifier = [identifier.Identifier({'value': 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+ str(int(age_low))+'-'+str(int(age_high))})] clinicalProfile.cohort = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low)) +'-'+str(int(age_high))}) else: clinicalProfile.id = 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low) clinicalProfile.identifier = [identifier.Identifier({'value': 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)})] clinicalProfile.cohort = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)}) clinicalProfile.status = 'draft' clinicalProfile.population = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort}) clinicalProfile.date = fhirdate.FHIRDate(str(datetime.now()).replace(' ', 'T')) clinicalProfile.reporter = fhirreference.FHIRReference({'reference': 'Organization/JHM', 'type': 'Organization', 'display': 'Johns Hopkins School of Medicine'}) ## LABS labs = list() corrmat = (pd.DataFrame(labs_correlatedLabsCoefficients).unstack(level=[0,1]).corr(min_periods=50) .droplevel(level=0).droplevel(level=0,axis=1)) lab_names = pd.DataFrame({'lab_name':labs_names}).reset_index() lab_counts = pd.DataFrame({'lab_counts':labs_counts}).reset_index().rename({'index':'LAB_LOINC'},axis=1) lab_info = lab_names.merge(lab_counts, how='inner', on='LAB_LOINC').set_index('LAB_LOINC') for thisLab in lab_info.index: # Check if STDEV is NaN and skip that lab if so if np.isnan(float(labs_stats.loc[thisLab]['std'].median())): continue # Build the profile thisCPLab = clinicalprofile.ClinicalProfileLab() # try: thisCPLab.code = [codeableconcept.CodeableConcept(dict(coding=[dict(system='http://loinc.org', code=thisLab)], text=lab_info.loc[thisLab]['lab_name'][0]))] thisCPLab.count = int(lab_info.loc[thisLab]['lab_counts']) thisCPLab.frequencyPerYear = round(float(labs_frequencyPerYear.loc[thisLab].mean()),3) thisCPLab.fractionOfSubjects = round(float(labs_fractionOfSubjects.loc[thisLab].mean()),3) thisCPLab.scalarDistribution = clinicalprofile.ClinicalProfileLabScalarDistribution() thisCPLab.scalarDistribution.units = quantity.Quantity(dict(unit=str(labs_units.loc[thisLab][0]))) thisCPLab.scalarDistribution.min = round(float(labs_stats.loc[thisLab]['min'].min()),3) thisCPLab.scalarDistribution.max = round(float(labs_stats.loc[thisLab]['max'].max()),3) thisCPLab.scalarDistribution.mean = round(float(labs_stats.loc[thisLab]['mean'].mean()),3) thisCPLab.scalarDistribution.median = round(float(labs_stats.loc[thisLab]['median'].median()),3) thisCPLab.scalarDistribution.stdDev = round(float(labs_stats.loc[thisLab]['std'].median()),3) deciles = list() for dec in labs_stats.columns[5:]: deciles.append(clinicalprofile.ClinicalProfileLabScalarDistributionDecile( dict(nth=int(dec), value=round(labs_stats.loc[thisLab][dec].mean(),3)))) thisCPLab.scalarDistribution.decile = deciles thisCPLab.scalarDistribution.fractionAboveNormal = round(float(labs_aboveBelowNorm.loc[thisLab].aboveNorm.mean()),3) thisCPLab.scalarDistribution.fractionBelowNormal = round(float(labs_aboveBelowNorm.loc[thisLab].belowNorm.mean()),3) try: yearly_vals = dict() for year in corrmat.loc[thisLab].index: crosstab = corrmat.loc[(thisLab, year)] yearly_vals[year] = (crosstab[crosstab.index.get_level_values(level=1).astype('float') == year] .droplevel(level=1)) topNcorrs = pd.DataFrame(yearly_vals).apply(np.mean, axis=1).drop(thisLab).nlargest(topN).round(3) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherLoinc = [(dict(coding=[dict(system='http://loinc.org', code=code)], text=str(lab_info.loc[code]['lab_name'][0])))] entries.append(dict(labcode=otherLoinc, coefficient=corr)) if not entries: print('No correlated Labs for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedLabs = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedLabs( dict(topn=topN, entry=entries)) except: print('No correlated Labs for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedMedsCoefficients.loc[thisLab].groupby(['JH_INGREDIENT_RXNORM_CODE']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherRX = [dict(medicationCodeableConcept=dict(coding= [dict(system='http://www.nlm.nih.gov/research/umls/rxnorm/', code=code)]))] entries.append(dict(meds=otherRX, coefficient=corr)) if not entries: print('No correlated Meds for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedMedications = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedMedications( dict(topn=topN, entry=entries)) except: print('No correlated Meds for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedDiagnosisCoefficients.loc[thisLab].groupby(['DX']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherDX = (dict(coding=[dict(system='http://www.icd10data.com/', code=code)])) entries.append(dict(code=otherDX, coefficient=corr)) if not entries: print('No correlated Diagnoses for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedDiagnoses = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedDiagnoses( dict(topn=topN, entry=entries)) except: print('No correlated Diagnoses for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedProceduresCoefficients.loc[thisLab].groupby(['RAW_PX']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherProc = [(dict(coding=[dict(system='http://www.ama-assn.org/practice-management/cpt', code=code)]))] entries.append(dict(code=otherProc, coefficient=corr)) if not entries: print('No correlated Procedures for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedProcedures = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedProcedures( dict(topn=topN, entry=entries)) except: print('No correlated Procedures for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedPhenotypesCoefficients.loc[thisLab].groupby(['HPO']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherHPO = (dict(coding=[dict(system='http://hpo.jax.org/app/', code=code)])) entries.append(dict(code=otherHPO, coefficient=corr)) if not entries: print('No correlated Phenotypes for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedPhenotypes = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedPhenotypes( dict(topn=topN, entry=entries)) except: print('No correlated Phenotypes for Lab ', thisLab) labs.append(thisCPLab) # except: # print('This lab did not work ', thisLab) clinicalProfile.lab = labs if age_high != None: filename = cohort+'_resources/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low))+'-'+str(int(age_high))+'.json' else: filename = cohort+'_resources/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)+'.json' with open(filename, 'w') as outfile: json.dump(clinicalProfile.as_json(), outfile, indent=4) del(clinicalProfile) return print('Write to '+ filename + ' successful')
def add_regionstudied_obv(self, ref_seq, reportable_query_regions, nocall_regions): if reportable_query_regions.empty and nocall_regions.empty: return patient_reference = reference.FHIRReference( {"reference": "Patient/" + self.patientID}) contained_uid = "rs-" + uuid4().hex[:13] self.result_ids.append(contained_uid) # Region Studied Obeservation observation_rs = observation.Observation() contained_rs = observation_rs contained_rs.id = contained_uid observation_rs.resource_type = "Observation" contained_rs.meta = meta.Meta({ "profile": [("http://hl7.org/fhir/uv/" + "genomics-reporting/" + "StructureDefinition/region-studied")] }) observation_rs.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "53041-0", "display": "DNA region of interest panel" }] }) observation_rs.status = "final" observation_rs.category = [ concept.CodeableConcept({ "coding": [{ "system": ("http://terminology.hl7.org/" + "CodeSystem/observation-category"), "code": "laboratory" }] }) ] observation_rs.subject = patient_reference observation_rs_component2 = observation.ObservationComponent() observation_rs_component2.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "92822-6", "display": "Genomic coord system" }] }) observation_rs_component2\ .valueCodeableConcept = concept.CodeableConcept( { "coding": [ { "system": "http://loinc.org", "code": "LA30102-0", "display": "1-based character counting" } ] } ) observation_rs_component3 = observation.ObservationComponent() observation_rs_component3.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "48013-7", "display": "Genomic reference sequence ID" }] }) observation_rs_component3\ .valueCodeableConcept = concept.CodeableConcept( { "coding": [ { "system": "http://www.ncbi.nlm.nih.gov/nuccore", "code": ref_seq } ] } ) observation_rs_components = self._get_region_studied_component( reportable_query_regions, nocall_regions) observation_rs.component = [ observation_rs_component2, observation_rs_component3 ] + observation_rs_components # Observation structure : described-variants self.report.contained.append(contained_rs)