use of org.mitre.synthea.input.FixedRecordGroup in project synthea by synthetichealth.
the class Exporter method export.
/**
* Export a single patient, into all the formats supported. (Formats may be enabled or disabled by
* configuration)
*
* @param person Patient to export
* @param stopTime Time at which the simulation stopped
* @param options Runtime exporter options
*/
public static void export(Person person, long stopTime, ExporterRuntimeOptions options) {
if (options.deferExports) {
deferredExports.add(new ImmutablePair<Person, Long>(person, stopTime));
} else {
if (options.yearsOfHistory > 0) {
person = filterForExport(person, options.yearsOfHistory, stopTime);
}
if (!person.alive(stopTime)) {
filterAfterDeath(person);
}
if (person.hasMultipleRecords) {
int i = 0;
for (String key : person.records.keySet()) {
person.record = person.records.get(key);
// If the person fixed Records, overwrite their attributes from the fixed records.
if (person.attributes.get(Person.RECORD_GROUP) != null) {
FixedRecordGroup rg = (FixedRecordGroup) person.attributes.get(Person.RECORD_GROUP);
int recordToPull = i;
if (recordToPull >= rg.count) {
recordToPull = rg.count - 1;
}
FixedRecord fr = rg.records.get(recordToPull);
fr.totalOverwrite(person);
}
exportRecord(person, Integer.toString(i), stopTime, options);
i++;
}
} else {
exportRecord(person, "", stopTime, options);
}
}
}
use of org.mitre.synthea.input.FixedRecordGroup in project synthea by synthetichealth.
the class Generator method checkCriteria.
/**
* Determines if a patient meets the requested criteria.
* If a patient does not meet the criteria the process will be repeated so a new one is generated
* @param person the patient to check if we want to export them
* @param finishTime the time simulation finished
* @param index Target index in the whole set of people to generate
* @param isAlive Whether the patient is alive at end of simulation.
* @return CriteriaCheck to determine if the patient should be exported/re-simulated
*/
public CriteriaCheck checkCriteria(Person person, long finishTime, int index, boolean isAlive) {
CriteriaCheck check = new CriteriaCheck();
check.rejectDeadButOverflow = !isAlive && !onlyDeadPatients && this.options.overflow;
// if patient is not alive and the criteria isn't dead patients new patient is needed
// however in this one case we still want to export the patient
check.isAliveButDeadRequired = isAlive && onlyDeadPatients;
// if patient is alive and the criteria is dead patients new patient is needed
check.isDeadButAliveRequired = !isAlive && onlyAlivePatients;
// if patient is not alive and the criteria is alive patients new patient is needed
int providerCount = person.providerCount();
int providerMinimum = 1;
if (this.recordGroups != null) {
// If fixed records are used, there must be 1 provider for each of this person's records.
FixedRecordGroup recordGroup = this.recordGroups.get(index);
providerMinimum = recordGroup.count;
}
check.insufficientProviders = providerCount < providerMinimum;
if (this.keepPatientsModule != null) {
// this one might be slow to process, so only do it if the other things are true
if (!check.isAliveButDeadRequired && !check.isDeadButAliveRequired) {
this.keepPatientsModule.process(person, finishTime, false);
State terminal = person.history.get(0);
check.failedKeepModule = !terminal.name.equals("Keep");
}
}
return check;
}
use of org.mitre.synthea.input.FixedRecordGroup in project synthea by synthetichealth.
the class FixedRecordTest method fixedDemographicsImportTest.
@Test
public void fixedDemographicsImportTest() {
// List of raw RecordGroups imported directly from the input file for later comparison.
List<FixedRecordGroup> rawRecordGroups = generator.importFixedPatientDemographicsFile();
// Generate each patient from the fixed record input file.
for (int i = 0; i < generator.options.population; i++) {
generator.generatePerson(i);
}
// Make sure that the correct number of people were imported from the fixed records.
assertEquals(4, generator.internalStore.size());
assertEquals(generator.internalStore.size(), rawRecordGroups.size());
// Check that each person has HealthRecords that match their fixed demographic records.
for (int p = 0; p < generator.internalStore.size(); p++) {
// Get the current person and pull their list of records.
Person currentPerson = generator.internalStore.get(p);
FixedRecordGroup recordGroup = (FixedRecordGroup) currentPerson.attributes.get(Person.RECORD_GROUP);
// Make sure the person has the correct number of records.
assertTrue(currentPerson.records.size() >= 3);
assertTrue(recordGroup.records.size() == 3);
// Track the number of fixed records that match the person's attributes exactly.
int fixedRecordMatches = 0;
// Cycle the person's FixedRecords to compare them to the raw imported FixedRecords.
for (int r = 0; r < currentPerson.records.size(); r++) {
int recordToPull = Math.min(r, recordGroup.count - 1);
FixedRecord personFixedRecord = recordGroup.records.get(recordToPull);
recordToPull = Math.min(r, rawRecordGroups.get(p).records.size() - 1);
FixedRecord rawFixedRecord = rawRecordGroups.get(p).records.get(recordToPull);
// Compare the person's current FixedRecord with the raw imported FixedRecords.
assertEquals(personFixedRecord.firstName, rawFixedRecord.firstName);
assertEquals(personFixedRecord.lastName, rawFixedRecord.lastName);
assertEquals(personFixedRecord.getBirthDate(), rawFixedRecord.getBirthDate());
assertEquals(personFixedRecord.gender, rawFixedRecord.gender);
assertEquals(personFixedRecord.phoneAreaCode, rawFixedRecord.phoneAreaCode);
assertEquals(personFixedRecord.phoneNumber, rawFixedRecord.phoneNumber);
assertEquals(personFixedRecord.addressLineOne, rawFixedRecord.addressLineOne);
assertEquals(personFixedRecord.addressLineTwo, rawFixedRecord.addressLineTwo);
assertEquals(personFixedRecord.city, rawFixedRecord.city);
assertEquals(personFixedRecord.zipcode, rawFixedRecord.zipcode);
assertEquals(personFixedRecord.parentFirstName, rawFixedRecord.parentFirstName);
assertEquals(personFixedRecord.parentLastName, rawFixedRecord.parentLastName);
assertEquals(personFixedRecord.parentEmail, rawFixedRecord.parentEmail);
// One FixedRecord should match the person's attributes exactly as the "gold standard".
if ((currentPerson.attributes.get(Person.FIRST_NAME).equals(rawFixedRecord.firstName)) && (currentPerson.attributes.get(Person.LAST_NAME).equals(rawFixedRecord.lastName)) && (currentPerson.attributes.get(Person.ADDRESS).equals(rawFixedRecord.addressLineOne)) && (currentPerson.attributes.get(Person.BIRTHDATE).equals(rawFixedRecord.getBirthDate())) && (currentPerson.attributes.get(Person.GENDER).equals(rawFixedRecord.gender)) && (currentPerson.attributes.get(Person.TELECOM).equals(rawFixedRecord.getTelecom())) && (currentPerson.attributes.get(Person.STATE).equals(rawFixedRecord.state)) && (currentPerson.attributes.get(Person.CITY).equals(rawFixedRecord.city)) && (currentPerson.attributes.get(Person.ZIP).equals(rawFixedRecord.zipcode)) && (currentPerson.attributes.get(Person.IDENTIFIER_RECORD_ID).equals(rawFixedRecord.recordId)) && (currentPerson.attributes.get(Person.IDENTIFIER_SITE).equals(rawFixedRecord.site))) {
fixedRecordMatches++;
}
}
// One FixedRecord should match the person's attributes exactly as a "gold standard" record.
assertTrue(fixedRecordMatches >= 1);
}
}
use of org.mitre.synthea.input.FixedRecordGroup in project synthea by synthetichealth.
the class Generator method pickFixedDemographics.
/**
* Pick a person's demographics based on their FixedRecords.
* @param index The index to use.
* @param random Random object.
*/
private Map<String, Object> pickFixedDemographics(int index, Random random) {
// Get the first FixedRecord from the current RecordGroup
FixedRecordGroup recordGroup = this.recordGroups.get(index);
FixedRecord fr = recordGroup.records.get(0);
// Get the city from the location in the fixed record.
this.location = new Location(fr.state, recordGroup.getSafeCity());
Demographics city = this.location.randomCity(random);
// Pick the rest of the demographics based on the location of the fixed record.
Map<String, Object> demoAttributes = pickDemographics(random, city);
// Overwrite the person's attributes with the FixedRecord.
demoAttributes.put(Person.BIRTHDATE, recordGroup.getValidBirthdate());
demoAttributes.put(Person.BIRTH_CITY, city.city);
String g = fr.gender;
if (g.equalsIgnoreCase("None") || StringUtils.isBlank(g)) {
g = "F";
}
demoAttributes.put(Person.GENDER, g);
// Give the person their FixedRecordGroup of FixedRecords.
demoAttributes.put(Person.RECORD_GROUP, recordGroup);
demoAttributes.put(Person.LINK_ID, recordGroup.linkId);
// Return the Demographic Attributes of the current person.
return demoAttributes;
}
use of org.mitre.synthea.input.FixedRecordGroup in project synthea by synthetichealth.
the class LifecycleModule method birth.
/**
* For unto us a child is born.
* @param person The baby.
* @param time The time of birth.
*/
public static void birth(Person person, long time) {
Map<String, Object> attributes = person.attributes;
attributes.put(Person.ID, person.randUUID().toString());
attributes.put(Person.BIRTHDATE, time);
String gender = (String) attributes.get(Person.GENDER);
String language = (String) attributes.get(Person.FIRST_LANGUAGE);
String firstName = Names.fakeFirstName(gender, language, person);
String lastName = Names.fakeLastName(language, person);
attributes.put(Person.FIRST_NAME, firstName);
attributes.put(Person.LAST_NAME, lastName);
attributes.put(Person.NAME, firstName + " " + lastName);
String motherFirstName = Names.fakeFirstName("F", language, person);
String motherLastName = Names.fakeLastName(language, person);
attributes.put(Person.NAME_MOTHER, motherFirstName + " " + motherLastName);
String fatherFirstName = Names.fakeFirstName("M", language, person);
// this is anglocentric where the baby gets the father's last name
attributes.put(Person.NAME_FATHER, fatherFirstName + " " + lastName);
double prevalenceOfTwins = (double) BiometricsConfig.get("lifecycle.prevalence_of_twins", 0.02);
if ((person.rand() < prevalenceOfTwins)) {
attributes.put(Person.MULTIPLE_BIRTH_STATUS, person.randInt(3) + 1);
}
String phoneNumber = "555-" + ((person.randInt(999 - 100 + 1) + 100)) + "-" + ((person.randInt(9999 - 1000 + 1) + 1000));
attributes.put(Person.TELECOM, phoneNumber);
boolean hasStreetAddress2 = person.rand() < 0.5;
attributes.put(Person.ADDRESS, Names.fakeAddress(hasStreetAddress2, person));
// If using FixedRecords, overwrite the person's attributes with the FixedRecord attributes.
if (person.attributes.get(Person.RECORD_GROUP) != null) {
FixedRecordGroup recordGroup = (FixedRecordGroup) person.attributes.get(Person.RECORD_GROUP);
FixedRecord fr = recordGroup.records.get(0);
attributes.putAll(fr.getFixedRecordAttributes());
}
String ssn = "999-" + ((person.randInt(99 - 10 + 1) + 10)) + "-" + ((person.randInt(9999 - 1000 + 1) + 1000));
attributes.put(Person.IDENTIFIER_SSN, ssn);
String city = (String) attributes.get(Person.CITY);
Location location = (Location) attributes.get(Person.LOCATION);
if (location != null) {
// should never happen in practice, but can happen in unit tests
location.assignPoint(person, city);
person.attributes.put(Person.ZIP, location.getZipCode(city, person));
String[] birthPlace;
if ("english".equalsIgnoreCase((String) attributes.get(Person.FIRST_LANGUAGE))) {
birthPlace = location.randomBirthPlace(person);
} else {
birthPlace = location.randomBirthplaceByLanguage(person, (String) person.attributes.get(Person.FIRST_LANGUAGE));
}
attributes.put(Person.BIRTH_CITY, birthPlace[0]);
attributes.put(Person.BIRTH_STATE, birthPlace[1]);
attributes.put(Person.BIRTH_COUNTRY, birthPlace[2]);
// For CSV exports so we don't break any existing schemas
attributes.put(Person.BIRTHPLACE, birthPlace[3]);
}
attributes.put(Person.ACTIVE_WEIGHT_MANAGEMENT, false);
// TODO: Why are the percentiles a vital sign? Sounds more like an attribute?
double heightPercentile = person.rand();
PediatricGrowthTrajectory pgt = new PediatricGrowthTrajectory(person.seed, time);
double weightPercentile = pgt.reverseWeightPercentile(gender, heightPercentile);
person.setVitalSign(VitalSign.HEIGHT_PERCENTILE, heightPercentile);
person.setVitalSign(VitalSign.WEIGHT_PERCENTILE, weightPercentile);
person.attributes.put(Person.GROWTH_TRAJECTORY, pgt);
// Temporarily generate a mother
Person mother = new Person(person.randLong());
mother.attributes.put(Person.GENDER, "F");
mother.attributes.put("pregnant", true);
mother.attributes.put(Person.RACE, person.attributes.get(Person.RACE));
mother.attributes.put(Person.ETHNICITY, person.attributes.get(Person.ETHNICITY));
mother.attributes.put(BirthStatistics.BIRTH_SEX, person.attributes.get(Person.GENDER));
BirthStatistics.setBirthStatistics(mother, time);
person.setVitalSign(VitalSign.HEIGHT, // cm
(double) mother.attributes.get(BirthStatistics.BIRTH_HEIGHT));
person.setVitalSign(VitalSign.WEIGHT, // kg
(double) mother.attributes.get(BirthStatistics.BIRTH_WEIGHT));
// cm
person.setVitalSign(VitalSign.HEAD, childHeadCircumference(person, time));
attributes.put(AGE, 0);
attributes.put(AGE_MONTHS, 0);
boolean isRHNeg = person.rand() < 0.15;
attributes.put("RH_NEG", isRHNeg);
double adherenceBaseline = Config.getAsDouble("lifecycle.adherence.baseline", 0.05);
person.attributes.put(ADHERENCE_PROBABILITY, adherenceBaseline);
// set initial height and weight from percentiles
grow(person, time);
// Set initial values for many vital signs.
calculateVitalSigns(person, time);
String orientation = sexualOrientationData.next(person);
attributes.put(Person.SEXUAL_ORIENTATION, orientation);
// Setup vital signs which follow the generator approach
setupVitalSignGenerators(person);
}
Aggregations