opal
opal copied to clipboard
Extract rules
This branch is a proposal it works and returns the same as the old function (with a change of order) but is mostly just for debate.
1. I just want to add a bunch of csvs... you can declare extract_rule.ExtractRule.
This is initialised with the list of episodes and the user.
Add a write_to_file
(which takes the directory to write to as an argument and returns a list of the file names that you wrote, or None)
Add a get_data_dictionary
method which returns
{
{{ display_name }}: [{
display_name: {{ field display name }},
description: {{ field description }},
type_display_name: {{ field type }},
}]
}
2. I want to change the fields that are in every csv.
You can declare a function in settings called EXTRACT_BASE_FIELDS that takes a user and returns the fields that the user should see in all files.
Cookbook
1. Rather than have an extract rule for allergies I want 1 row per patient with the allergy.drugs as a comma seperated list.
Add _exclude_from_extract=True
to allergies
class Allergy(extract_rule.ExtractRule):
def write_to_file(self, directory):
allergies = Allergy.objects.filter(episode_id__in=[i.id for i in self.episode_list])
episode_id_to_drug = defaultdict(list)
base_field_dict = self.get_episode_id_to_base_fields_dict()
for allergy in allergies:
episode_id_to_drug[allergy.episode_id].append(allergy.drug)
rows = []
for episode_id, drugs in episode_id_to_drug.items():
row = {"drugs": ",".join(drugs)}
row.update(base_field_dict[episode_id])
rows.append(row)
file_name = os.path.join(directory, "allergies.csv")
with open(file_name, "w"): as f:
# sort your rows and write them to file.
def get_data_dictionary(self):
return {
models.Allergy.get_display_name(): [{
"display_name": "Drugs",
"description": "A list of the patients drug allergies",
"type_display_name": "A comma seperated list"
}]
}
2. I want to add the field 'within the last week' to PatientConsultation
Add _exclude_from_extract=True
to PatientConsulation. This is not strictly necessary as the rule will run after the subrecord extract is done, but it stops additional computation.
Then add the extract rule.
class PatientConsultation(extract_rule.ModelRule):
model = Episode
path_to_episode_id = "patient__episode__id"
additional_fields = ["within_the_last_week"]
def get_within_the_last_week_description(self):
return {
"display_name": "Within the last week",
"description": "returns True if the consultation was within the last week.",
"type_display_name": "Either True, False or None"
}
def extract_within_the_last_week(self, instance):
if instance.when:
seven_days_ago = datetime.today() - timedelta(days=7)
return seven_days_ago > instance.when:
3. I want to remove the field drug
from allergies
In the models.py change
class Allergy(opal_models.Allergy):
@classmethod
def _get_fieldnames_to_extract(cls):
field_names = super()._get_fieldnames_to_extract()
field_names.remove("drug")
return field_names
4. I want to add first_name, surname for all users
settings.py
EXTRACT_BASE_FIELDS "my_app.extract_rule.get_base_fields'
extract_rule.py
def get_base_fields(user):
return {
"patient__demographics__first_name",
"patient__demographics__surname",
}