Skip to content

Commit

Permalink
review improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dehall committed Apr 12, 2024
1 parent f59d3f8 commit d0e4371
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 46 deletions.
14 changes: 10 additions & 4 deletions src/main/java/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public static void main(String[] args) throws Exception {
} else if (currArg.equalsIgnoreCase("-p")) {
String value = argsQ.poll();
options.population = Integer.parseInt(value);
Config.set("generate.default_population", value);
} else if (currArg.equalsIgnoreCase("-o")) {
String value = argsQ.poll();
options.overflow = Boolean.parseBoolean(value);
Expand Down Expand Up @@ -132,10 +133,7 @@ public static void main(String[] args) throws Exception {
String value = argsQ.poll();
File configFile = new File(value);
Config.load(configFile);
// Any options that are automatically set by reading the configuration
// file during options initialization need to be reset here.
options.population = Config.getAsInteger("generate.default_population", 1);
options.threadPoolSize = Config.getAsInteger("generate.thread_pool_size", -1);
resetOptionsFromConfig(options);
} else if (currArg.equalsIgnoreCase("-d")) {
String value = argsQ.poll();
File localModuleDir = new File(value);
Expand Down Expand Up @@ -252,6 +250,7 @@ public static void main(String[] args) throws Exception {
}

Config.set(configSetting, value);
resetOptionsFromConfig(options);
} else if (options.state == null) {
options.state = currArg;
} else {
Expand All @@ -271,6 +270,13 @@ public static void main(String[] args) throws Exception {
generator.run();
}
}

private static void resetOptionsFromConfig(Generator.GeneratorOptions options) {
// Any options that are automatically set by reading the configuration
// file during options initialization need to be reset here.
options.population = Config.getAsInteger("generate.default_population", 1);
options.threadPoolSize = Config.getAsInteger("generate.thread_pool_size", -1);
}

private static boolean validateConfig(Generator.GeneratorOptions options,
boolean overrideFutureDateError) {
Expand Down
17 changes: 9 additions & 8 deletions src/main/java/org/mitre/synthea/export/flexporter/Actions.java
Original file line number Diff line number Diff line change
Expand Up @@ -649,13 +649,9 @@ private static void dateFilter(Bundle bundle, String minDateStr, String maxDateS
* Cascade (current), Delete reference field but leave object, Do nothing
*
* @param bundle FHIR Bundle to filter
* @param list List of resource types to delete, other types not listed will be kept
* @param list List of resource types or FHIRPath to delete, other types not listed will be kept
*/
public static void deleteResources(Bundle bundle, List<String> list) {
// TODO: make this FHIRPath instead of just straight resource types

Set<String> resourceTypesToDelete = new HashSet<>(list);

Set<String> deletedResourceIDs = new HashSet<>();

Iterator<BundleEntryComponent> itr = bundle.getEntry().iterator();
Expand All @@ -665,10 +661,15 @@ public static void deleteResources(Bundle bundle, List<String> list) {

Resource resource = entry.getResource();
String resourceType = resource.getResourceType().toString();
if (resourceTypesToDelete.contains(resourceType)) {
deletedResourceIDs.add(resource.getId());
itr.remove();

for (String applicability : list) {
if (applicability.equals(resourceType) || FhirPathUtils.appliesToResource(resource, applicability)) {
deletedResourceIDs.add(resource.getId());
itr.remove();
break;
}
}

}

if (!deletedResourceIDs.isEmpty()) {
Expand Down
140 changes: 134 additions & 6 deletions src/main/java/org/mitre/synthea/modules/OphthalmicNoteModule.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.mitre.synthea.modules;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.mitre.synthea.engine.Module;
import org.mitre.synthea.export.ExportHelper;
import org.mitre.synthea.world.agents.Person;
import org.mitre.synthea.world.concepts.HealthRecord.Encounter;
import org.mitre.synthea.world.concepts.HealthRecord.Observation;
import org.mitre.synthea.world.concepts.HealthRecord.Procedure;

public class OphthalmicNoteModule extends Module {

Expand Down Expand Up @@ -48,6 +51,8 @@ public boolean process(Person person, long time) {
} else {
encounterNote.append("Followup exam with ")
.append(person.attributes.get(Person.NAME))
.append(' ')
.append(ExportHelper.dateFromTimestamp(time))
.append('\n');

firstObservedDrStage = (Integer) person.attributes.get("first_observed_dr_stage");
Expand All @@ -56,34 +61,157 @@ public boolean process(Person person, long time) {
HashMap<Integer,Long> drStageFirstObservedDate = (HashMap<Integer,Long>) person.attributes.get("dr_stage_to_first_observed_date");
if (drStageFirstObservedDate == null) {
drStageFirstObservedDate = new HashMap<>();
person.attributes.put("dr_stage_to_first_observed_date", drStageFirstObservedDate);
}

boolean stable = true;
if (!drStageFirstObservedDate.containsKey(drStage)) {
drStageFirstObservedDate.put(drStage, currEncounter.start);
stable = false;
}

if (drStage == 0) {
encounterNote.append("No current signs of diabetic retinopathy, both eyes\n");
} else if (firstObservedDrStage > 0) {
encounterNote.append(STAGES[firstObservedDrStage]).append(" OU\n");
} else {
boolean first = true;
for (int i = 1 ; i <= 4 ; i++) {
Long observed = drStageFirstObservedDate.get(i);
if (observed != null) {
if (first) {
encounterNote.append(STAGES[i]).append(" OU ").append(ExportHelper.dateFromTimestamp(observed)).append('\n');
first = false;
} else {
encounterNote.append("Progressed to " + STAGES[i] + " " + ExportHelper.dateFromTimestamp(observed)).append('\n');
}
}
}
}

Procedure panRetinalLaser = (Procedure) person.attributes.get("panretinal_laser");
List<Procedure> gridLaserHistory = (List<Procedure>)person.attributes.get("grid_laser_history");
if (gridLaserHistory == null) {
gridLaserHistory = new ArrayList<>();
person.attributes.put("grid_laser_history", gridLaserHistory);
}

if (panRetinalLaser != null || !gridLaserHistory.isEmpty()) {
encounterNote.append("Procedure History:\n");
if (panRetinalLaser != null) {
encounterNote.append("Panretinal laser ").append(ExportHelper.dateFromTimestamp(panRetinalLaser.start)).append('\n');
} else {
encounterNote.append("Grid laser");
for (Procedure g : gridLaserHistory) {
encounterNote.append(", ").append(ExportHelper.dateFromTimestamp(g.start));
}
encounterNote.append('\n');
}
}

double va = (double) person.attributes.get("visual_acuity_logmar");
// logmar to 20/x = 20*10^(logmar)
long denom = Math.round(20 * Math.pow(10, va));
encounterNote.append("Visual Acuity: 20/").append(denom).append(" OD, 20/").append(denom).append(" OS\n");

int iop = (int) person.attributes.get("intraocular_pressure");
encounterNote.append("Intraocular Pressure (IOP): ").append(iop).append(" mmHg OD, ").append(iop).append(" mmHg OS\n");

// an example from chatGPT
encounterNote.append("Pupils: Equal, round, reactive to light and accommodation\n");
encounterNote.append("Extraocular Movements: Full and smooth\n");
encounterNote.append("Confrontation Visual Fields: Full to finger count OU\n");
encounterNote.append("Anterior Segment: Normal lids, lashes, and conjunctiva OU. Cornea clear OU. Anterior chamber deep and quiet OU. Iris normal architecture OU. Lens clear OU.\n");
encounterNote.append("Dilated Fundus Examination:\n");
encounterNote.append("Optic Disc: Pink, well-defined margins, cup-to-disc ratio 0.3 OU\n");

boolean edema = (boolean) person.attributes.getOrDefault("macular_edema", false);

if (edema) {
// TODO encounterNote.append("Macula: Flat, no edema or exudates OU\n");
} else {
encounterNote.append("Macula: Flat, no edema or exudates OU\n");
}

if (drStage > firstObservedDrStage) {
// encounterNote.append("Progressed to " )
encounterNote.append("Vessels: Attenuated arterioles with some copper wiring changes OU. No neovascularization noted.\n");
encounterNote.append("Periphery: No tears, holes, or detachments OU");

Procedure firstAntiVEGF = (Procedure)person.attributes.get("first_anti_vegf");

for (Procedure p : currEncounter.procedures) {
switch (p.type) {
// primary code

// visual acuity
case "16830007":
break;

// IOP
case "252832004":
break;

// Slit-lamp biomicroscopy
case "55468007":
break;

// Gonioscopy
case "389153003":
break;

// Fundoscopy
case "314971001":
break;

// Examination of the peripheral retina and vitreous
case "722161008":
break;

// OCT
case "700070005":
break;

// Panretinal laser
case "413180006":
person.attributes.put("panretinal_laser", p);
break;

// Grid laser
case "397539000":
gridLaserHistory.add(p);
break;

// Anti VEGF
case "1004045004":
if (firstAntiVEGF == null) {

firstAntiVEGF = p;
person.attributes.put("first_anti_vegf", firstAntiVEGF);
}
break;

}
}

Observation hba1c = person.record.getLatestObservation("4548-4");

if (((Double)hba1c.value) > 6.5 && person.rand() > .7) {
if (drStage == 0) {
encounterNote.append("Discussed the nature of DM and its potential effects on the eye in detail with the patient. Discussed the importance of maintaining strict glycemic control to avoid developing retinopathy.");
encounterNote.append("Discussed the nature of DM and its potential effects on the eye in detail with the patient. Discussed the importance of maintaining strict glycemic control to avoid developing retinopathy.\n");
} else {
encounterNote.append("I discussed the effects of elevated glucose on the eye, and the importance of strict control in preventing progression of retinopathy.");
encounterNote.append("I discussed the effects of elevated glucose on the eye, and the importance of strict control in preventing progression of retinopathy.\n");
}
}

if (prevEncounter == null) {
encounterNote.append("Discussed the signs of vision changes that require immediate medical attention.\n");
}

// TODO: line about follow-up

currEncounter.note = encounterNote.toString();

// System.out.println(currEncounter.note);
// System.out.println("\n");


person.attributes.put("previous_ophthalmic_encounter", currEncounter);

// note return options here, see State$CallSubmodule
Expand Down
31 changes: 26 additions & 5 deletions src/main/resources/modules/diabetic_retinopathy_treatment.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@
"codes": [
{
"system": "SNOMED-CT",
"code": 389153003,
"code": 413180006,
"display": "Pan retinal photocoagulation for diabetes (procedure)"
}
],
Expand Down Expand Up @@ -488,7 +488,7 @@
"display": "proparacaine hydrochloride 5 MG/ML Ophthalmic Solution"
}
],
"direct_transition": "Panretinal Laser",
"direct_transition": "End_Drops_Panretinal",
"administration": true
},
"Numbing_Drops_Grid_Laser": {
Expand All @@ -500,7 +500,7 @@
"display": "proparacaine hydrochloride 5 MG/ML Ophthalmic Solution"
}
],
"direct_transition": "Grid_Laser",
"direct_transition": "End_Drops_Grid",
"administration": true
},
"Numbing_Drops_AntiVEGF_Injection": {
Expand All @@ -512,7 +512,7 @@
"display": "proparacaine hydrochloride 5 MG/ML Ophthalmic Solution"
}
],
"direct_transition": "AntiVEGF_Therapy_Med",
"direct_transition": "End_Drops_AntiVEGF",
"administration": true
},
"Dilation": {
Expand All @@ -524,7 +524,8 @@
"display": "tropicamide 5 MG/ML Ophthalmic Solution"
}
],
"direct_transition": "Gonioscopy"
"direct_transition": "End_Dilation_Med",
"administration": true
},
"Guard_for_Vision_Impact": {
"type": "Guard",
Expand Down Expand Up @@ -607,6 +608,26 @@
}
],
"direct_transition": "Progress_DR_Vitals"
},
"End_Drops_Panretinal": {
"type": "MedicationEnd",
"direct_transition": "Panretinal Laser",
"medication_order": "Numbing_Drops_Panretinal_Laser"
},
"End_Drops_AntiVEGF": {
"type": "MedicationEnd",
"direct_transition": "AntiVEGF_Therapy_Med",
"medication_order": "Numbing_Drops_AntiVEGF_Injection"
},
"End_Drops_Grid": {
"type": "MedicationEnd",
"direct_transition": "Grid_Laser",
"medication_order": "Numbing_Drops_Grid_Laser"
},
"End_Dilation_Med": {
"type": "MedicationEnd",
"direct_transition": "Gonioscopy",
"medication_order": "Dilation"
}
},
"gmf_version": 2
Expand Down
Loading

0 comments on commit d0e4371

Please sign in to comment.