refs/refs/FhirToCdm/FhirToCdmMappings.cs
lines 468–468
625 lines · cs
2using org.ohdsi.cdm.framework.common.Lookups; 3using org.ohdsi.cdm.framework.common.Omop; 5using System.Collections.Generic; 7using omop = org.ohdsi.cdm.framework.common.Omop; 11 public class FhirToCdmMappings 13 private Vocabulary _vocabulary; 15 public FhirToCdmMappings(Vocabulary vocabulary) 17 _vocabulary = vocabulary; 20 public IEnumerable<Tuple<omop.Person, List<omop.Location>>> CreatePersonAndLocations(Bundle fhir) 22 //provider_id Patient.generalPractitioner Patient 23 //care_site_id BodySite.patient BodySite 24 //birth_datetime Patient.birthDate us-core - patient 25 //location_id Patient.address Patient 27 var locations = new HashSet<omop.Location>(); 28 //var pat = fhir.Entry.FirstOrDefault(e => e.Resource.TypeName == "Patient"); 29 foreach (var pat in fhir.Entry.Where(e => e.Resource.TypeName == "Patient")) 31 var patient = (Patient)pat.Resource; 32 var person = new omop.Person 34 GenderSourceValue = patient.Gender.ToString(), 35 PersonSourceValue = patient.Id, 36 YearOfBirth = DateTime.Parse(patient.BirthDate).Year, 37 MonthOfBirth = DateTime.Parse(patient.BirthDate).Month, 38 DayOfBirth = DateTime.Parse(patient.BirthDate).Day, 39 EthnicityConceptId = 0 42 foreach (var ex in patient.Extension) 44 if (ex.Url.ToLower().Contains("death")) 50 switch (person.GenderSourceValue) 53 person.GenderConceptId = 8507; 57 person.GenderConceptId = 8532; 61 person.GenderConceptId = 0; 65 if (patient.GeneralPractitioner.Count > 0) 70 foreach (var address in patient.Address) 72 var location = new omop.Location 75 State = address.State, 76 Zip = address.PostalCode, 77 Country = address.Country 80 //var line = address.Line.ToList(); 83 // location.Address1 = line[0]; 86 // location.Address2 = line[1]; 88 locations.Add(location); 91 foreach (var item in patient.Extension) 93 if (item.Url == "http://hl7.org/fhir/StructureDefinition/us-core-race") 95 if (item.Value != null) 97 person.RaceSourceValue = ((Hl7.Fhir.Model.Coding)item.Value).Display; 99 else if (item.Extension.Count > 0) 101 person.RaceSourceValue = ((Hl7.Fhir.Model.Coding)item.Extension[0].Value).Display; 105 else if (item.Url == "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity") 107 if (item.Value != null) 109 person.EthnicitySourceValue = ((Hl7.Fhir.Model.Coding)item.Value).Display; 111 else if (item.Extension.Count > 0) 113 person.RaceSourceValue = ((Hl7.Fhir.Model.Coding)item.Extension[0].Value).Display; 119 if (!string.IsNullOrEmpty(person.EthnicitySourceValue)) 121 switch (person.EthnicitySourceValue.ToUpper()) 123 case "CENTRAL_AMERICAN": 127 case "SOUTH_AMERICAN": 128 person.EthnicityConceptId = 38003563; 132 person.EthnicityConceptId = 0; 137 if (!string.IsNullOrEmpty(person.RaceSourceValue)) 139 switch (person.RaceSourceValue.ToUpper()) 142 person.RaceConceptId = 8515; 146 person.RaceConceptId = 8516; 150 person.RaceConceptId = 8522; 154 person.RaceConceptId = 8527; 158 person.RaceConceptId = 0; 159 person.EthnicityConceptId = 38003563; 163 person.RaceConceptId = 0; 168 yield return new Tuple<omop.Person, List<omop.Location>>(person, locations.ToList()); 173 public IEnumerable<Tuple<KeyValuePair<string, VisitOccurrence>, Provider>> CreateVisitOccurenceAndProvider(Bundle fhir, Dictionary<string, long> personIds) 175 //care_site_id Encounter.location.location.identifier us-core - encounter, us - core - location 176 //admitting_source_concept_id Encounter.hospitalization.admitSource or Encounter.hospitalization.origin(location).type us - core - encounter, us - core - location 177 //discharge_to_concept_id Encounter.location.location.type us-core - encounter,us - core - location 178 //preceding_visit_occurence Encounter.partOf us-core - encounter 179 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "Encounter")) 181 var encounter = (Encounter)item.Resource; 183 var conceptId = 9202; 185 if (encounter.Class.Code.ToUpper() == "IMP") 187 else if (encounter.Class.Code.ToUpper() == "EMER") 190 if (encounter.Diagnosis.Count > 0) 195 if (encounter.ReasonCode.Count > 0) 197 foreach (var reasonCode in encounter.ReasonCode) 199 foreach (var code in reasonCode.Coding) 201 if (code.Code == "308646001") 210 if (encounter.Extension.Count > 0) 215 Provider provider = null; 216 if (encounter.ServiceProvider != null) 218 provider = new Provider 220 Id = Entity.GetId(encounter.ServiceProvider.Display), 221 Name = encounter.ServiceProvider.Display, 222 SourceValue = encounter.ServiceProvider.Display 226 var personId = GetPersonId1(encounter.Subject, personIds); 228 VisitOccurrence vo = null; 229 if (personId.HasValue) 231 vo = new VisitOccurrence(new Entity()) 233 PersonId = personId.Value, 234 SourceValue = encounter.Class.Code, 235 StartDate = DateTime.Parse(encounter.Period.Start), 236 EndDate = DateTime.Parse(encounter.Period.End), 237 TypeConceptId = 32817, 238 ConceptId = conceptId 241 if (provider != null) 243 vo.ProviderId = provider.Id; 247 yield return new Tuple<KeyValuePair<string, VisitOccurrence>, Provider>( 248 new KeyValuePair<string, VisitOccurrence>(encounter.Id, vo), provider); 252 public IEnumerable<omop.ConditionOccurrence> CreateConditionOccurrence(Bundle fhir, Dictionary<string, long> personIds, Dictionary<string, VisitOccurrence> visits) 254 //provider_id Condition.asserter us-core - condition 255 //visit_occurrence_id Condition.encounter us-core - condition 256 //condition_status_concept_id Condition.clinicalStatus us-core - condition 257 //stop_reason Condition.Extension(Proposed Name: abatement - reason : CodeableConcept) us - core - condition 259 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "Condition")) 261 var condition = (Condition)item.Resource; 263 foreach (var code in condition.Code.Coding) 265 var date = DateTime.Parse(((Hl7.Fhir.Model.FhirDateTime)condition.Onset).Value); 267 var personId = GetPersonId1(condition.Subject, personIds); 268 if (!personId.HasValue) 271 var co = new ConditionOccurrence(new Entity()) 273 PersonId = personId.Value, 274 TypeConceptId = 32817, 276 SourceValue = code.Code 279 if (condition.Abatement != null) 281 co.EndDate = DateTime.Parse(((Hl7.Fhir.Model.FhirDateTime)condition.Abatement).Value); 284 var result = LookupCode(code); 286 SetConceptId(co, result[0]); 288 if (co.Domain == "Drug") 290 co.TypeConceptId = 32817; 292 else if (co.Domain == "Observation") 294 co.TypeConceptId = 32817; 297 var vo = GetVisitOccurrence(condition.Encounter, visits); 298 co.VisitOccurrenceId = vo.Id; 299 co.VisitDetailId = vo.Id; 301 if (!co.EndDate.HasValue) 302 co.EndDate = vo.EndDate; 310 public IEnumerable<DrugExposure> CreateDrugExposure(Bundle fhir, Dictionary<string, long> personIds, Dictionary<string, VisitOccurrence> visits) 312 //stop_reason MedicationStatement.statusReason us-core - medicationstatement 313 //refills MedicationStatement.basedOn(MedicationRequest).dispenseRequest.numberOfRepeatsAllowed us - core - medicationstatement, us - core - medicationrequest 314 //quantity MedicationStatement.basedOn(MedicationRequest).dispenseRequest.quantity us - core - medicationstatement, us - core - medicationrequest 315 //days_supply MedicationStatement.basedOn(MedicationRequest).dispenseRequest.expectedSupplyDuration us - core - medicationstatement, us - core - medicationrequest 316 //lot_number MedicationStatement.medication.batch.lotNumber us-core - medicationstatement, us - core - medication 317 //route_concept_id MedicationStatement.basedOn(MedicationRequest).dosageInstruction.route us - core - medicationstatement, us - core - medicationrequest 318 //provider_id MedicationStatement.basedOn(MedicationRequest).requester us - core - medicationstatement, us - core - medicationrequest 319 //verbatim_end_date MedicationStatement.basedOn(MedicationRequest).validityPeriod us - core - medicationstatement, us - core - medicationrequest 322 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "MedicationRequest")) 324 var medication = (MedicationRequest)item.Resource; 325 var cc = medication.Medication as Hl7.Fhir.Model.CodeableConcept; 329 foreach (var code in cc.Coding) 331 var personId = GetPersonId1(medication.Subject, personIds); 332 if (!personId.HasValue) 335 var de = new DrugExposure(new Entity()) 337 PersonId = personId.Value, 338 TypeConceptId = 32817 341 if (medication.BasedOn.Count > 0) 346 if (medication.StatusReason != null) 351 if (medication.DosageInstruction != null && medication.DosageInstruction.Count > 0) 353 de.Sig = medication.DosageInstruction[0].Text; 356 if (medication.DispenseRequest != null) 361 var result = LookupCode(code); 363 SetConceptId(de, result[0]); 365 var vo = GetVisitOccurrence(medication.Encounter, visits); 366 de.VisitOccurrenceId = vo.Id; 367 de.VisitDetailId = vo.Id; 368 de.StartDate = vo.StartDate; 369 de.EndDate = vo.EndDate; 376 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "Immunization")) 378 var immunization = (Immunization)item.Resource; 380 foreach (var code in ((Hl7.Fhir.Model.CodeableConcept)immunization.VaccineCode).Coding) 382 var personId = GetPersonId1(immunization.Patient, personIds); 383 if (!personId.HasValue) 386 var de = new omop.DrugExposure(new omop.Entity()) 388 PersonId = personId.Value, 389 TypeConceptId = 32817 392 var result = LookupCode(code); 394 SetConceptId(de, result[0]); 396 var vo = GetVisitOccurrence(immunization.Encounter, visits); 397 de.VisitOccurrenceId = vo.Id; 398 de.VisitDetailId = vo.Id; 399 de.StartDate = vo.StartDate; 400 de.EndDate = vo.EndDate; 407 public IEnumerable<ProcedureOccurrence> CreateProcedureOccurrence(Bundle fhir, Dictionary<string, long> personIds, Dictionary<string, VisitOccurrence> visits) 409 //quantity Procedure.Extension(Proposed Name: num - of - procedures : CodeableConcept) us - core - procedure 410 //provider_id Procedure.performer.actor 412 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "Procedure")) 414 var procedure = (Procedure)item.Resource; 416 foreach (var code in ((Hl7.Fhir.Model.CodeableConcept)procedure.Code).Coding) 418 var personId = GetPersonId1(procedure.Subject, personIds); 419 if (!personId.HasValue) 422 var po = new ProcedureOccurrence(new Entity()) 424 PersonId = personId.Value, 425 TypeConceptId = 32817 428 var result = LookupCode(code); 430 SetConceptId(po, result[0]); 432 if (procedure.Extension.Count > 0) 437 if (po.Domain == "Measurement") 439 po.TypeConceptId = 32817; 442 var vo = GetVisitOccurrence(procedure.Encounter, visits); 443 po.VisitOccurrenceId = vo.Id; 444 po.VisitDetailId = vo.Id; 445 po.StartDate = DateTime.Parse(((Hl7.Fhir.Model.Period)procedure.Performed).Start); 446 po.EndDate = DateTime.Parse(((Hl7.Fhir.Model.Period)procedure.Performed).End); 453 public IEnumerable<omop.Observation> CreateObservation(Bundle fhir, Dictionary<string, long> personIds, Dictionary<string, VisitOccurrence> visits) 455 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "AllergyIntolerance")) 457 var allergy = (AllergyIntolerance)item.Resource; 459 foreach (var code in ((Hl7.Fhir.Model.CodeableConcept)allergy.Code).Coding) 461 var personId = GetPersonId1(allergy.Patient, personIds); 462 if (!personId.HasValue) 465 var o = new omop.Observation(new Entity()) 467 PersonId = personId.Value, 468 TypeConceptId = 32817 471 var result = LookupCode(code); 473 SetConceptId(o, result[0]); 475 o.StartDate = DateTime.Parse(allergy.RecordedDate); 482 public IEnumerable<Measurement> CreateMeasurement(Bundle fhir, Dictionary<string, long> personIds, Dictionary<string, VisitOccurrence> visits) 484 //provider_id Observation.performer(Practitioner) us - core - observationresults 485 //value_as_concept_id Observation.valueCodeableConcept us-core - observationresults 487 foreach (var item in fhir.Entry.Where(e => e.Resource.TypeName == "Observation")) 489 var observation = (Hl7.Fhir.Model.Observation)item.Resource; 491 foreach (var code in ((CodeableConcept)observation.Code).Coding) 493 var personId = GetPersonId1(observation.Subject, personIds); 494 if (!personId.HasValue) 497 var m = new Measurement(new Entity()) 499 PersonId = personId.Value, 500 TypeConceptId = 32817 503 var result = LookupCode(code); 505 SetConceptId(m, result[0]); 507 if (observation.ReferenceRange != null && observation.ReferenceRange.Count > 0) 509 if (observation.ReferenceRange[0].Low != null) 510 m.RangeLow = observation.ReferenceRange[0].Low.Value; 512 if (observation.ReferenceRange[0].High != null) 513 m.RangeHigh = observation.ReferenceRange[0].High.Value; 516 var vo = GetVisitOccurrence(observation.Encounter, visits); 517 m.VisitOccurrenceId = vo.Id; 518 m.VisitDetailId = vo.Id; 519 m.StartDate = DateTime.Parse(((FhirDateTime)observation.Effective).Value); 521 if (observation.Value != null) 523 var quantity = observation.Value as Quantity; 524 if (quantity != null) 526 m.UnitSourceValue = quantity.Unit; 527 var unit = LookupCode(m.UnitSourceValue, "Unit"); 528 if (unit.Any() && unit[0].ConceptId.HasValue) 530 m.UnitConceptId = unit[0].ConceptId.Value; 533 m.ValueAsNumber = quantity.Value; 534 m.ValueSourceValue = m.ValueAsNumber.ToString(); 538 var cc = observation.Value as CodeableConcept; 540 if (cc != null && cc.Coding.Count > 0) 542 m.ValueSourceValue = cc.Coding[0].Display; 544 var conceptId = LookupCode(cc.Coding[0]); 545 if (conceptId.Any() && conceptId[0].ConceptId.HasValue) 546 m.ValueAsConceptId = conceptId[0].ConceptId.Value; 550 m.ValueSourceValue = observation.Value.ToString(); 560 private long? GetPersonId1(ResourceReference e, Dictionary<string, long> personIds) 562 var key = e.Reference.Replace("urn:uuid:", ""); 563 if (personIds.ContainsKey(key)) 564 return personIds[key]; 569 private VisitOccurrence GetVisitOccurrence(ResourceReference e, Dictionary<string, VisitOccurrence> visits) 571 return visits[e.Reference.Replace("urn:uuid:", "")]; 574 private void SetConceptId(IEntity e, LookupValue value) 576 if (value.ConceptId.HasValue) 578 e.ConceptId = value.ConceptId.Value; 579 e.Domain = value.Domain; 581 if (value.Ingredients != null) 583 e.Ingredients = new List<int>(value.Ingredients.Count); 584 e.Ingredients.AddRange(value.Ingredients); 588 e.SourceConceptId = value.SourceConceptId; 591 private List<LookupValue> LookupCode(string code, string vocabularyName) 593 return _vocabulary.Lookup(code, vocabularyName, DateTime.MinValue); 596 private List<LookupValue> LookupCode(Coding code) 598 var vocabularyName = ""; 601 case "http://snomed.info/sct": 602 vocabularyName = "Snomed"; 605 case "http://www.nlm.nih.gov/research/umls/rxnorm": 606 vocabularyName = "Rxnorm"; 609 case "http://hl7.org/fhir/sid/cvx": 610 vocabularyName = "Cvx"; 613 case "http://loinc.org": 614 vocabularyName = "Loinc"; 618 throw new Exception("unknown vocabulary " + code.System); 621 return LookupCode(code.Code, vocabularyName);