The key components of the mock EHR interface interacts with the users through the decorator ehr
decorators.py - where the main decorator function is located. It wraps around a function that returns the data a user wants the EHR object to simulate sending. The main arguments users should supply is workflow, which is usually the name of the CDS hook, and num, which is the number of requests to generate. The body of the function this decorator wraps around should define the config and specs for what they want the synthetic data generator to return. The decorator validates the use case (CDS or clinical documentation), workflow (CDS hook name), and returns an EHRClient object which contains a queue of validated requests ready to be sent off.
clients.py - this is where the backend behaviour of healthcare objects is located (in most cases it's an EHR, but there could be other objects such as CPOE, payment systems etc.). EHRClient is the bridge between the data passed in from the decorator class and the backend strategy pattern (use_cases) that processes the data in a specific way. The primary method is .send_request(), where it sends all request jsons in its queue as POST requests.
use_cases/cds.py - the strategy for generating request data specific to a use case (CDS or clindoc). The strategy class should validate that the data given contains all necessary attributes and can be used to construct a request. It then wraps the data and returns appropriate pydantic model, in this case CDSRequest.
All pydantic models are in models/ directory. Currently, I have implemented the hooks
patient-view
order-sign
order-select
encounter-discharge
Each hook is actually the context field of CDSRequest as that's the only thing that's different for each type of hook. (I might rename to make this clearer).
Things to generate synthetic data for in CDSRequest:
N.B. I'm using a dummy class like this for testing:
@dataclasses.dataclass
class synth_data:
context: dict
uuid: str
prefetch: dict
hookInstance
The hook instance is just a uuid. I've been using uuid.uuid4(). Easy peasy.
context
The context provides context relevant to the specific hook in question, but in most cases it just contains userId, patientId, encounterId. Note these are NOT FHIR resources - they are strings that must follow specific patterns (e.g. "Practitioner/123"). See each hook context for more details.
Some hooks, however, MAY contain FHIR resources in its context - see order-select, order-sign. In these cases it usually asks for a Bundle of FHIR resources that satisfies specific requirements given the hook, so you might want to filter down to a list of sensible FHIR resources. For the hackathon release, this is not essential, because encounter-discharge doesn't have any extra fhir stuff.
prefetch
This is where it might get complicated. A CDS service is supposed to have prefetched templates which specify what FHIR resources they would like access to. This is a dictionary of key to FHIR query, example:
However, I think we can skip past the FHIR query (if they wanted to do all that, they could query a real test FHIR server which there are several available out there) and restrict to a specific set of options for the users, for example, Observation, Condition (more specifically, a problem list), or even just specific profiles of patients (e.g. Diabetic, Healthy, Recovered). More on that later.
The key components of the mock EHR interface interacts with the users through the decorator
ehr
decorators.py
- where the main decorator function is located. It wraps around a function that returns the data a user wants the EHR object to simulate sending. The main arguments users should supply isworkflow
, which is usually the name of the CDS hook, andnum
, which is the number of requests to generate. The body of the function this decorator wraps around should define the config and specs for what they want the synthetic data generator to return. The decorator validates the use case (CDS or clinical documentation), workflow (CDS hook name), and returns anEHRClient
object which contains a queue of validated requests ready to be sent off.clients.py
- this is where the backend behaviour of healthcare objects is located (in most cases it's an EHR, but there could be other objects such as CPOE, payment systems etc.).EHRClient
is the bridge between the data passed in from the decorator class and the backend strategy pattern (use_cases
) that processes the data in a specific way. The primary method is.send_request()
, where it sends all request jsons in its queue as POST requests.use_cases/cds.py
- the strategy for generating request data specific to a use case (CDS or clindoc). The strategy class should validate that the data given contains all necessary attributes and can be used to construct a request. It then wraps the data and returns appropriate pydantic model, in this caseCDSRequest
.All pydantic models are in
models/
directory. Currently, I have implemented the hookspatient-view
order-sign
order-select
encounter-discharge
Each hook is actually the
context
field ofCDSRequest
as that's the only thing that's different for each type of hook. (I might rename to make this clearer).Things to generate synthetic data for in
CDSRequest
:Examples
N.B. I'm using a dummy class like this for testing:
hookInstance
The hook instance is just a uuid. I've been usinguuid.uuid4()
. Easy peasy.context
The context provides context relevant to the specific hook in question, but in most cases it just containsuserId
,patientId
,encounterId
. Note these are NOT FHIR resources - they are strings that must follow specific patterns (e.g. "Practitioner/123"). See each hook context for more details. Some hooks, however, MAY contain FHIR resources in its context - seeorder-select
,order-sign
. In these cases it usually asks for aBundle
of FHIR resources that satisfies specific requirements given the hook, so you might want to filter down to a list of sensible FHIR resources. For the hackathon release, this is not essential, becauseencounter-discharge
doesn't have any extra fhir stuff.prefetch
This is where it might get complicated. A CDS service is supposed to have prefetched templates which specify what FHIR resources they would like access to. This is a dictionary of key to FHIR query, example:However, I think we can skip past the FHIR query (if they wanted to do all that, they could query a real test FHIR server which there are several available out there) and restrict to a specific set of options for the users, for example,
Observation
,Condition
(more specifically, a problem list), or even just specific profiles of patients (e.g. Diabetic, Healthy, Recovered). More on that later.@adamkells