use of org.mitre.synthea.world.concepts.HealthRecord.Encounter in project synthea by synthetichealth.
the class FhirStu3 method encounterClaim.
/**
* Create an entry for the given Claim, associated to an Encounter.
*
* @param rand Source of randomness to use when generating ids etc
* @param personEntry Entry for the person
* @param bundle The Bundle to add to
* @param encounterEntry The current Encounter
* @param claim the Claim object
* @return the added Entry
*/
private static BundleEntryComponent encounterClaim(RandomNumberGenerator rand, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, Claim claim) {
org.hl7.fhir.dstu3.model.Claim claimResource = new org.hl7.fhir.dstu3.model.Claim();
org.hl7.fhir.dstu3.model.Encounter encounterResource = (org.hl7.fhir.dstu3.model.Encounter) encounterEntry.getResource();
claimResource.setStatus(ClaimStatus.ACTIVE);
claimResource.setUse(org.hl7.fhir.dstu3.model.Claim.Use.COMPLETE);
// duration of encounter
claimResource.setBillablePeriod(encounterResource.getPeriod());
claimResource.setPatient(new Reference(personEntry.getFullUrl()));
claimResource.setOrganization(encounterResource.getServiceProvider());
// add item for encounter
claimResource.addItem(new ItemComponent(new PositiveIntType(1)).addEncounter(new Reference(encounterEntry.getFullUrl())));
int itemSequence = 2;
int conditionSequence = 1;
int procedureSequence = 1;
int informationSequence = 1;
for (Claim.ClaimEntry claimEntry : claim.items) {
HealthRecord.Entry item = claimEntry.entry;
if (Costs.hasCost(item)) {
// update claimItems list
ItemComponent claimItem = new ItemComponent(new PositiveIntType(itemSequence));
Code primaryCode = item.codes.get(0);
String system = ExportHelper.getSystemURI(primaryCode.system);
CodeableConcept serviceProvided = new CodeableConcept().addCoding(new Coding().setCode(primaryCode.code).setVersion("v1").setSystem(system));
claimItem.setService(serviceProvided);
// calculate the cost of the procedure
Money moneyResource = new Money();
moneyResource.setCode("USD");
moneyResource.setSystem("urn:iso:std:iso:4217");
moneyResource.setValue(item.getCost());
claimItem.setNet(moneyResource);
if (item instanceof HealthRecord.Procedure) {
Type procedureReference = new Reference(item.fullUrl);
ProcedureComponent claimProcedure = new ProcedureComponent(new PositiveIntType(procedureSequence), procedureReference);
claimResource.addProcedure(claimProcedure);
claimItem.addProcedureLinkId(procedureSequence);
procedureSequence++;
} else {
Reference informationReference = new Reference(item.fullUrl);
SpecialConditionComponent informationComponent = new SpecialConditionComponent();
informationComponent.setSequence(informationSequence);
informationComponent.setValue(informationReference);
CodeableConcept category = new CodeableConcept();
category.getCodingFirstRep().setSystem("http://hl7.org/fhir/claiminformationcategory").setCode("info");
informationComponent.setCategory(category);
claimResource.addInformation(informationComponent);
claimItem.addInformationLinkId(informationSequence);
claimItem.setService(claimResource.getType());
informationSequence++;
}
claimResource.addItem(claimItem);
} else {
// assume it's a Condition, we don't have a Condition class specifically
// add diagnosisComponent to claim
Reference diagnosisReference = new Reference(item.fullUrl);
org.hl7.fhir.dstu3.model.Claim.DiagnosisComponent diagnosisComponent = new org.hl7.fhir.dstu3.model.Claim.DiagnosisComponent(new PositiveIntType(conditionSequence), diagnosisReference);
claimResource.addDiagnosis(diagnosisComponent);
// update claimItems with diagnosis
ItemComponent diagnosisItem = new ItemComponent(new PositiveIntType(itemSequence));
diagnosisItem.addDiagnosisLinkId(conditionSequence);
claimResource.addItem(diagnosisItem);
conditionSequence++;
}
itemSequence++;
}
Money moneyResource = new Money();
moneyResource.setCode("USD");
moneyResource.setSystem("urn:iso:std:iso:4217");
moneyResource.setValue(claim.getTotalClaimCost());
claimResource.setTotal(moneyResource);
return newEntry(rand, bundle, claimResource);
}
use of org.mitre.synthea.world.concepts.HealthRecord.Encounter in project synthea by synthetichealth.
the class CSVExporter method allergy.
/**
* Write a single Allergy to allergies.csv.
*
* @param personID ID of the person that has the allergy.
* @param encounterID ID of the encounter where the allergy was diagnosed
* @param allergy The allergy itself
* @throws IOException if any IO error occurs
*/
private void allergy(String personID, String encounterID, HealthRecord.Allergy allergy) throws IOException {
// START,STOP,PATIENT,ENCOUNTER,CODE,SYSTEM,DESCRIPTION,TYPE,CATEGORY
// REACTION1,DESCRIPTION1,SEVERITY1,
// REACTION2,DESCRIPTION2,SEVERITY2
StringBuilder s = new StringBuilder();
s.append(dateFromTimestamp(allergy.start)).append(',');
if (allergy.stop != 0L) {
s.append(dateFromTimestamp(allergy.stop));
}
s.append(',');
s.append(personID).append(',');
s.append(encounterID).append(',');
Code coding = allergy.codes.get(0);
s.append(coding.code).append(',');
s.append(getSystemFromURI(coding.system)).append(',');
s.append(clean(coding.display)).append(',');
if (allergy.allergyType != null) {
s.append(allergy.allergyType);
}
s.append(',');
if (allergy.category != null) {
s.append(allergy.category);
}
s.append(',');
int reactionsSize = 0;
if (allergy.reactions != null) {
reactionsSize = allergy.reactions.size();
}
Function<Map.Entry<HealthRecord.Code, HealthRecord.ReactionSeverity>, String> template = mapEntry -> {
StringBuilder reactionBuilder = new StringBuilder();
reactionBuilder.append(mapEntry.getKey().code).append(',');
reactionBuilder.append(clean(mapEntry.getKey().display)).append(',');
reactionBuilder.append(mapEntry.getValue());
return reactionBuilder.toString();
};
switch(reactionsSize) {
case 0:
s.append(",,,,,");
break;
case 1:
s.append(allergy.reactions.entrySet().stream().map(template).collect(Collectors.joining()));
s.append(",,,");
break;
default:
// case where there are more than two reactions so we need to support by severity
s.append(allergy.reactions.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).limit(2).map(template).collect(Collectors.joining(",")));
}
s.append(NEWLINE);
write(s.toString(), allergies);
}
use of org.mitre.synthea.world.concepts.HealthRecord.Encounter in project synthea by synthetichealth.
the class Exporter method filterForExport.
/**
* Filter the health record to only the last __ years
* but also include relevant history from before that. Exclude
* any history that occurs after the specified end_time -- typically
* this is the current time/System.currentTimeMillis().
*
* @param record The record to filter.
* @param yearsToKeep The last __ years to keep.
* @param endTime The time the history ends.
* @return Modified record with history expunged.
*/
private static HealthRecord filterForExport(HealthRecord record, int yearsToKeep, long endTime) {
long cutoffDate = endTime - Utilities.convertTime("years", yearsToKeep);
Predicate<HealthRecord.Entry> notFutureDated = e -> e.start <= endTime;
for (Encounter encounter : record.encounters) {
List<Claim.ClaimEntry> claimItems = encounter.claim.items;
// keep conditions if still active, regardless of start date
Predicate<HealthRecord.Entry> conditionActive = c -> record.conditionActive(c.type);
// or if the condition was active at any point since the cutoff date
Predicate<HealthRecord.Entry> activeWithinCutoff = c -> c.stop != 0L && c.stop > cutoffDate;
Predicate<HealthRecord.Entry> keepCondition = conditionActive.or(activeWithinCutoff);
filterEntries(encounter.conditions, claimItems, cutoffDate, endTime, keepCondition);
// allergies are essentially the same as conditions
// But we need to redefine all of the predicates, because we are talking about Allergies as
// opposed to Entries... You would think that it would work... but generics are hard
Predicate<HealthRecord.Allergy> allergyActive = c -> record.allergyActive(c.type);
// or if the condition was active at any point since the cutoff date
Predicate<HealthRecord.Allergy> allergyActiveWithinCutoff = c -> c.stop != 0L && c.stop > cutoffDate;
Predicate<HealthRecord.Allergy> keepAllergy = allergyActive.or(allergyActiveWithinCutoff);
filterEntries(encounter.allergies, claimItems, cutoffDate, endTime, keepAllergy);
// some of the "future death" logic could potentially add a future-dated death certificate
Predicate<Observation> isCauseOfDeath = o -> DeathModule.CAUSE_OF_DEATH_CODE.code.equals(o.type);
// keep cause of death unless it's future dated
Predicate<Observation> keepObservation = isCauseOfDeath.and(notFutureDated);
filterEntries(encounter.observations, claimItems, cutoffDate, endTime, keepObservation);
// keep all death certificates, unless they are future-dated
Predicate<Report> isDeathCertificate = r -> DeathModule.DEATH_CERTIFICATE.code.equals(r.type);
Predicate<Report> keepReport = isDeathCertificate.and(notFutureDated);
filterEntries(encounter.reports, claimItems, cutoffDate, endTime, keepReport);
filterEntries(encounter.procedures, claimItems, cutoffDate, endTime, null);
// keep medications if still active, regardless of start date
filterEntries(encounter.medications, claimItems, cutoffDate, endTime, med -> record.medicationActive(med.type));
filterEntries(encounter.immunizations, claimItems, cutoffDate, endTime, null);
// keep careplans if they are still active, regardless of start date
filterEntries(encounter.careplans, claimItems, cutoffDate, endTime, cp -> record.careplanActive(cp.type));
}
// if ANY of these are not empty, the encounter is not empty
Predicate<Encounter> encounterNotEmpty = e -> !e.conditions.isEmpty() || !e.allergies.isEmpty() || !e.observations.isEmpty() || !e.reports.isEmpty() || !e.procedures.isEmpty() || !e.medications.isEmpty() || !e.immunizations.isEmpty() || !e.careplans.isEmpty();
Predicate<Encounter> isDeathCertification = e -> !e.codes.isEmpty() && DeathModule.DEATH_CERTIFICATION.equals(e.codes.get(0));
Predicate<Encounter> keepEncounter = encounterNotEmpty.or(isDeathCertification.and(notFutureDated));
// finally filter out any empty encounters
filterEntries(record.encounters, Collections.emptyList(), cutoffDate, endTime, keepEncounter);
return record;
}
use of org.mitre.synthea.world.concepts.HealthRecord.Encounter in project synthea by synthetichealth.
the class FhirDstu2 method medicationClaim.
/**
* Create an entry for the given Claim, which references a Medication.
*
* @param rand
* Source of randomness to use when generating ids etc
* @param personEntry
* Entry for the person
* @param bundle
* The Bundle to add to
* @param encounterEntry
* The current Encounter
* @param claim
* the Claim object
* @param medicationEntry
* The Entry for the Medication object, previously created
* @return the added Entry
*/
private static Entry medicationClaim(RandomNumberGenerator rand, Entry personEntry, Bundle bundle, Entry encounterEntry, Claim claim, Entry medicationEntry) {
ca.uhn.fhir.model.dstu2.resource.Claim claimResource = new ca.uhn.fhir.model.dstu2.resource.Claim();
ca.uhn.fhir.model.dstu2.resource.Encounter encounterResource = (ca.uhn.fhir.model.dstu2.resource.Encounter) encounterEntry.getResource();
// assume institutional claim
// TODO review claim type
claimResource.setType(ClaimTypeEnum.INSTITUTIONAL);
claimResource.setUse(UseEnum.COMPLETE);
claimResource.setPatient(new ResourceReferenceDt(personEntry.getFullUrl()));
claimResource.setOrganization(encounterResource.getServiceProvider());
// add prescription.
claimResource.setPrescription(new ResourceReferenceDt(medicationEntry.getFullUrl()));
return newEntry(rand, bundle, claimResource);
}
use of org.mitre.synthea.world.concepts.HealthRecord.Encounter in project synthea by synthetichealth.
the class FhirDstu2 method convertToFHIR.
/**
* Convert the given Person into a FHIR Bundle with the Patient and the
* associated entries from their health record.
*
* @param person Person to generate the FHIR Bundle
* @param stopTime Time the simulation ended
* @return String containing a FHIR Bundle containing the Person's health record
*/
public static Bundle convertToFHIR(Person person, long stopTime) {
Bundle bundle = new Bundle();
if (TRANSACTION_BUNDLE) {
bundle.setType(BundleTypeEnum.TRANSACTION);
} else {
bundle.setType(BundleTypeEnum.COLLECTION);
}
Entry personEntry = basicInfo(person, bundle, stopTime);
for (Encounter encounter : person.record.encounters) {
Entry encounterEntry = encounter(person, personEntry, bundle, encounter);
for (HealthRecord.Entry condition : encounter.conditions) {
condition(person, personEntry, bundle, encounterEntry, condition);
}
for (HealthRecord.Entry allergy : encounter.allergies) {
allergy(person, personEntry, bundle, encounterEntry, allergy);
}
for (Observation observation : encounter.observations) {
// Observation resources in stu3 don't support Attachments
if (observation.value instanceof Attachment) {
media(person, personEntry, bundle, encounterEntry, observation);
} else {
observation(person, personEntry, bundle, encounterEntry, observation);
}
}
for (Procedure procedure : encounter.procedures) {
procedure(person, personEntry, bundle, encounterEntry, procedure);
}
for (Medication medication : encounter.medications) {
medication(person, personEntry, bundle, encounterEntry, medication);
}
for (HealthRecord.Entry immunization : encounter.immunizations) {
immunization(person, personEntry, bundle, encounterEntry, immunization);
}
for (Report report : encounter.reports) {
report(person, personEntry, bundle, encounterEntry, report);
}
for (CarePlan careplan : encounter.careplans) {
careplan(person, personEntry, bundle, encounterEntry, careplan);
}
for (ImagingStudy imagingStudy : encounter.imagingStudies) {
imagingStudy(person, personEntry, bundle, encounterEntry, imagingStudy);
}
for (HealthRecord.Device device : encounter.devices) {
device(person, personEntry, bundle, device);
}
for (HealthRecord.Supply supply : encounter.supplies) {
supplyDelivery(person, personEntry, bundle, supply, encounter);
}
// one claim per encounter
encounterClaim(person, personEntry, bundle, encounterEntry, encounter.claim);
}
return bundle;
}
Aggregations