Programmatically accessing patient data loaded from a file

I’m loading the Soldier@0s.json patient file, and I’d like to extract data from it programmatically (e.g. the patient’s age).

This code (Java) doesn’t work:

boolean success = this.pulseEngine.serializeFromFile("isaac-pulse.log", patientStateFile, dataRequests);
this.pulseEngine.patient.getSex();

The issue is that the sex is null, even though it is defined in the patient file. (The patient is not null, but every field in it is null.) Is there a way to get this data populated in the patient data structures? Or maybe it should be and I’m doing something else wrong?

Actually, I’m not loading a patient file directly, I’m loading a state file, in case that makes a difference.

I should also say that it looks like for many patient fields the intention is for the getter to return a default if the field is null, but getSex() just returns the value, which is null. I wasn’t expecting this, so I got a NullPointerException.

As for getting the patient instantiated, it looks like I can do it if I don’t use a state file, but then I have a longer startup time. As a workaround, I can probably load the state file and the patient file separately, but I’m not sure if this is what is intended.

You can load a state file and grab patient data from the engine.
But anything you want to get passed over a language barrier (C++ to Java in this case) has to be specified as a Data Request.

So you need to add this to your Data Requests:

   SEDataRequest age = new SEDataRequest();
   age.setCategory(eCategory.Patient);
   age.setPropertyName("Age");
   age.setUnit(TimeUnit.yr.toString());
   dataRequests.getRequestedData().add(age);

Then you will get a value back for

    Log.info("Patient Age "+ pe.patient.getAge());

Again, I think the Java API should be refactored to behave more like the Python and C# API’s

Also note, that I do not have a way of getting enum values back for any language currently.

The enum values are pretty important. Here’s what I’m doing now:

SEPatient patient = new SEPatient();
StateData.Builder builder = StateData.newBuilder();
JsonFormat.parser().merge(FileUtils.readFile(patientStateFile), builder);
SEPatient.load(builder.getCurrentPatient(), patient); 

Then I create the PulseEngine with the patient state file and just keep the SEPatient around to get the various patient info from as needed.

That works!

It would also be nice for Java/C#/Python to be able to get whole systems/objects from the engine.

Something like,

  engine.getPatient(patient)

You provide the patient object, and this method would automatically pull the entire object out of the engine and populate it with that data. (Of course you should not do this each time step, unless you really need all values. For optimal data that needs to be updated each time step, still use Data Requests)

Yes, I agree that would be nice. In my case, I just need it at startup, because the values I care about (age, sex, etc.) will never change. It’s “background” information about the patient that I want to display.

Here’s a potentially nicer solution that gets the data into the pulse engine, so I don’t have to track another object, and it seems more natural to me to have this data in the engine anyway.

PulseEngine pulseEngine = new PulseEngine();
pulseEngine.serializeFromFile("my.log", patientStateFile, dataRequests);

// have to do this after engine initialization because otherwise the patient fields will be reset back to null
StateData.Builder builder = StateData.newBuilder();
JsonFormat.parser().merge(FileUtils.readFile(patientStateFile), builder);
SEPatient.load(builder.getCurrentPatient(), pulseEngine.patient); 

That is pretty nice

I could add that to always happen in the serializeFromFile method, so the patient object is always updated on a load

1 Like

I like that idea a lot. It would be more efficient since I wouldn’t have to deserialize the state file twice, and it seems like it would generally be useful. Are there other parts of the pulse engine that are null without a data request that could be initialized this way? (I don’t need anything else yet, it just seems like it may be useful to do this for as much as possible.)

Well, technically there are some patient parameters that do change during the simulation.
So I would really want to selectively copy a subset of properties out of the state file into the patient object, not all of them. Depending on what you do, baseline values can change.

There are no other ‘static’ properties in the state file that could change in the next time step…

What we do in C++ is have 2 patient object, the original patient, and the current patient.
Which might actually be in the state… or they should be… and I should automagically set the ‘original’ patient object in the PulseEngine…

Makes sense! I think this would be a good addition to the behavior.