Add documentation

This commit is contained in:
2020-11-27 12:49:03 +01:00
parent e4c51874dc
commit c9b94ed6c6
26 changed files with 743 additions and 98 deletions

View File

@@ -1,4 +1,4 @@
# Generated by Django 3.0.8 on 2020-07-30 14:15
# Generated by Django 3.1.3 on 2020-11-27 11:47
import apps.api.models
from django.conf import settings

View File

@@ -55,7 +55,7 @@ class Token(MetaDataModel):
"""Boolean check if the token is belonging to a user with super user rights. Then this token is a super token.
Returns:
bool: Returns true when the token belongs to a super user.
Boolean: Returns true when the token belongs to a super user.
"""
# TODO: Is it allowed to be a super user and researcher? Could give conflict of interests. With the API token you can read other researchers data...
return self.user.is_superuser == True

View File

@@ -17,7 +17,7 @@ def create_user_token(sender, instance=None, created=False, **kwargs):
instance: :attr:`~django.contrib.auth.models.User`
The newly created user model data
created : boolean
created : Boolean
Wether the object was created (True) or updated (False).
"""
if created:

View File

@@ -27,21 +27,12 @@ class SyntheaConfig(AppConfig):
# We only load this setting, if it is not available in the overall settings.py file
settings.SYNTHEA_MODULE_DIR = settings.SYNTHEA_BASE_DIR / 'src/main/resources/modules/'
try:
assert settings.SYNTHEA_RESOURCE_DIR
except AttributeError:
# We only load this setting, if it is not available in the overall settings.py file
settings.SYNTHEA_RESOURCE_DIR = settings.SYNTHEA_BASE_DIR / 'src/main/resources/'
try:
assert settings.SYNTHEA_STATES_DIR
except AttributeError:
# We only load this setting, if it is not available in the overall settings.py file
settings.SYNTHEA_STATES_DIR = settings.SYNTHEA_BASE_DIR / 'src/main/resources/geography/'
try:
assert settings.SYNTHEA_EXPORT_TYPE
except AttributeError:

View File

@@ -8,20 +8,31 @@ import json
from django.conf import settings
from uuid import uuid4
def available_states():
"""This method will return a sorted list of available states based on the 'geography/demographics.csv' in the `settings.SYNTHEA_RESOURCE_DIR` folder.
Returns:
List: Sorted list on state name with dicts holding the id and name of the state.
"""
states = []
# Read the demographics.csv file from the Synthea resources and get all the unique state names
# Important, the state name for synthea is case sensitive (field id)
df = pd.read_csv(settings.SYNTHEA_STATES_DIR / 'demographics.csv', index_col=False)
df = pd.read_csv(settings.SYNTHEA_RESOURCE_DIR / 'geography/demographics.csv', index_col=False)
for state in df.STNAME.unique():
states.append({'id' : state , 'name' : state})
# Sort on name
states = sorted(states, key=lambda k: k['name'].lower())
states = sorted(states, key=lambda s: s['name'].lower())
return states
def available_modules():
"""This method will load all the available modules that are in the folder `settings.SYNTHEA_MODULE_DIR`. Only files ending on .json will be loaded.
Returns:
List: Sorted list on module name with dicts holding the id and name of the module.
"""
# Assumption here: Only .json files in the main folder are modules. The rest are submodules...
modules = []
for module in settings.SYNTHEA_MODULE_DIR.iterdir():
@@ -29,10 +40,29 @@ def available_modules():
data = json.loads(module.read_text())
modules.append({'id' : module.name.replace('.json',''), 'name' : data['name']})
modules = sorted(modules, key=lambda k: k['name'].lower())
modules = sorted(modules, key=lambda m: m['name'].lower())
return modules
def run_synthea(state = None, population = None, gender = None, age = None, module = None):
def run_synthea(state, population = 50, gender = None, age = None, module = None):
"""This module will run the Synthea application on the background. This method expects Synthea to be installed on the `settings.SYNTHEA_BASE_DIR` location.
The output will be written to a unique folder in `settings.SYNTHEA_OUTPUT_DIR` that will be zipped and returned.
It will return the log and the zipfile location for futher processing. The zip file will not be deleted afterwards. So cleanup needs to be done manually.
Args:
state (str, required): The state where to generate synthetic patient data for.
population (int, optional): The amount of patients to generate. Defaults to 50.
gender (str, optional): Either generate only male(m), only female(f), or None for both. Defaults to None.
age (str, optional): This is the age range of the generated patients. Input is always like [min_age]-[max_age]. Defaults to None.
module (str, optional): The module to use for generating patient data When None, all modules are used. Defaults to None.
Raises:
Exception: When the Synthea run fails it will return an Exception witht he Java error in it.
Returns:
(str,Path): The returning zipfile has the enabled options in the file name.
"""
# Add a unique dir to the output, so multiple Synthea processes can run parallel
temp_id = uuid4().hex
output_folder = settings.SYNTHEA_OUTPUT_DIR / temp_id

View File

@@ -1,4 +1,4 @@
# Generated by Django 3.1.3 on 2020-11-13 09:36
# Generated by Django 3.1.3 on 2020-11-27 11:47
from django.db import migrations, models
import uuid
@@ -18,15 +18,16 @@ class Migration(migrations.Migration):
('created_at', models.DateTimeField(auto_now_add=True, help_text='The date and time this model has been created', verbose_name='Date created')),
('updated_at', models.DateTimeField(auto_now=True, help_text='The date and time this model has been updated', verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='A unique id', primary_key=True, serialize=False, unique=True, verbose_name='ID')),
('state', models.CharField(help_text='The state for which synthea generate data.', max_length=200, verbose_name='Stage')),
('state', models.CharField(help_text='The state for which synthea generate data.', max_length=200, verbose_name='State')),
('population', models.PositiveSmallIntegerField(default=50, help_text='The size of the population', verbose_name='Population')),
('gender', models.CharField(help_text='Select the gender type', max_length=1, verbose_name='Gender')),
('age', models.CharField(help_text='Select the age range', max_length=10, verbose_name='Age range')),
('module', models.CharField(help_text='Select the module', max_length=50, verbose_name='Mopdule')),
('gender', models.CharField(blank=True, help_text='Select the gender type', max_length=1, verbose_name='Gender')),
('age', models.CharField(blank=True, default='18-100', help_text='Select the age range. Enter [min age]-[max age]', max_length=10, verbose_name='Age range')),
('module', models.CharField(blank=True, help_text='Select the module', max_length=50, verbose_name='Module')),
('log', models.TextField(blank=True, help_text='Synthea logfile output', verbose_name='Log')),
],
options={
'verbose_name': 'token',
'verbose_name_plural': 'tokens',
'verbose_name': 'synthea',
'verbose_name_plural': 'synthea',
},
),
]

View File

@@ -1,38 +0,0 @@
# Generated by Django 3.1.3 on 2020-11-16 13:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('synthea', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='synthea',
name='log',
field=models.TextField(blank=True, help_text='Synthea logfile output', verbose_name='Log'),
),
migrations.AlterField(
model_name='synthea',
name='age',
field=models.CharField(blank=True, default='18-100', help_text='Select the age range. Enter [min age]-[max age]', max_length=10, verbose_name='Age range'),
),
migrations.AlterField(
model_name='synthea',
name='gender',
field=models.CharField(blank=True, help_text='Select the gender type', max_length=1, verbose_name='Gender'),
),
migrations.AlterField(
model_name='synthea',
name='module',
field=models.CharField(blank=True, help_text='Select the module', max_length=50, verbose_name='Module'),
),
migrations.AlterField(
model_name='synthea',
name='state',
field=models.CharField(help_text='The state for which synthea generate data.', max_length=200, verbose_name='State'),
),
]

View File

@@ -13,10 +13,32 @@ import uuid
# Create your models here.
class Synthea(MetaDataModel):
"""Synthea model that holds some iformation about a generated output.
Attributes
----------
id : uuid
A unique ID for every Synthea run. Leave empty for auto generating a new value.
state : str
The state for which you want to generate Synthea patient data
population : int
The amount of patients you want to generate
gender : datetime
Generate only male (m), only female(f) or leave empty for male and female
age : str
The age range for the patients. Enter like [min_age]-[max_age]
module : str
The module to use for patient generating. Leave empty for random use by Synthea
log : str
The outcome of a single patient generating run. This can be read in the admin area.
Returns:
Synthea: A new Synthea model
"""
class Meta:
verbose_name = _('token')
verbose_name_plural = _('tokens')
verbose_name = _('synthea')
verbose_name_plural = _('synthea')
id = models.UUIDField(_('ID'), primary_key=True, unique=True, default=uuid.uuid4, editable=False, help_text=_('A unique id'))
state = models.CharField(_('State'), max_length=200, help_text=_('The state for which synthea generate data.'))
@@ -26,8 +48,15 @@ class Synthea(MetaDataModel):
module = models.CharField(_('Module'),blank=True, max_length=50, help_text=_('Select the module'))
log = models.TextField(_('Log'),blank=True, help_text=_('Synthea logfile output'))
def generate(self):
"""Run the patient generation. This will return a logfile and a zipfile location for download.
The log will be stored in the model when done. This log can then be seen/readed in the admin section of Django
Returns:
str: The zip file location on disk.
"""
# Start generating patient data.
log,zip_file = run_synthea(
self.state,
self.population,
@@ -35,10 +64,9 @@ class Synthea(MetaDataModel):
self.age,
self.module
)
# Store the log from the Synthea run in the database.
self.log = log
self.save()
# Return the zip file locaton for download
return zip_file