endoreg-db 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- endoreg_db/admin.py +3 -3
- endoreg_db/apps.py +6 -6
- endoreg_db/data/__init__.py +65 -16
- endoreg_db/data/active_model/data.yaml +2 -2
- endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
- endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
- endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
- endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
- endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
- endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
- endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
- endoreg_db/data/case_template/template/base.yaml +8 -0
- endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
- endoreg_db/data/case_template/tmp/_rule_value +13 -0
- endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
- endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
- endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
- endoreg_db/data/center/data.yaml +60 -52
- endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
- endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
- endoreg_db/data/disease/cardiovascular.yaml +37 -0
- endoreg_db/data/disease/hepatology.yaml +5 -0
- endoreg_db/data/disease/misc.yaml +6 -0
- endoreg_db/data/disease/renal.yaml +5 -0
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
- endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
- endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
- endoreg_db/data/distribution/date/patient.yaml +7 -0
- endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
- endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
- endoreg_db/data/endoscope_type/data.yaml +10 -10
- endoreg_db/data/endoscopy_processor/data.yaml +45 -45
- endoreg_db/data/event/cardiology.yaml +28 -0
- endoreg_db/data/event/neurology.yaml +14 -0
- endoreg_db/data/event/surgery.yaml +13 -0
- endoreg_db/data/event/thrombembolism.yaml +20 -0
- endoreg_db/data/examination/examinations/data.yaml +65 -16
- endoreg_db/data/examination/time/data.yaml +47 -47
- endoreg_db/data/examination/time-type/data.yaml +7 -7
- endoreg_db/data/examination/type/data.yaml +5 -5
- endoreg_db/data/gender/data.yaml +18 -0
- endoreg_db/data/information_source/data.yaml +30 -30
- endoreg_db/data/information_source/medication.yaml +6 -0
- endoreg_db/data/lab_value/cardiac_enzymes.yaml +31 -0
- endoreg_db/data/lab_value/coagulation.yaml +49 -0
- endoreg_db/data/lab_value/electrolytes.yaml +190 -0
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +121 -0
- endoreg_db/data/lab_value/hematology.yaml +169 -0
- endoreg_db/data/lab_value/hormones.yaml +53 -0
- endoreg_db/data/lab_value/lipids.yaml +44 -0
- endoreg_db/data/lab_value/misc.yaml +30 -0
- endoreg_db/data/lab_value/renal_function.yaml +11 -0
- endoreg_db/data/label/label/data.yaml +62 -62
- endoreg_db/data/label/label-set/data.yaml +17 -17
- endoreg_db/data/label/label-type/data.yaml +6 -6
- endoreg_db/data/material/material.yaml +91 -0
- endoreg_db/data/medication/anticoagulation.yaml +65 -0
- endoreg_db/data/medication/tah.yaml +70 -0
- endoreg_db/data/medication_indication/anticoagulation.yaml +120 -0
- endoreg_db/data/medication_indication_type/data.yaml +11 -0
- endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
- endoreg_db/data/medication_intake_time/base.yaml +31 -0
- endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
- endoreg_db/data/medication_schedule/ass.yaml +12 -0
- endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
- endoreg_db/data/model_type/data.yaml +6 -6
- endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
- endoreg_db/data/pdf_type/data.yaml +28 -28
- endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
- endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
- endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
- endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
- endoreg_db/data/profession/data.yaml +70 -70
- endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +26 -26
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +19 -19
- endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
- endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
- endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
- endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
- endoreg_db/data/unit/concentration.yaml +92 -0
- endoreg_db/data/unit/data.yaml +17 -17
- endoreg_db/data/unit/length.yaml +30 -30
- endoreg_db/data/unit/misc.yaml +20 -0
- endoreg_db/data/unit/rate.yaml +6 -0
- endoreg_db/data/unit/time.yaml +13 -0
- endoreg_db/data/unit/volume.yaml +35 -26
- endoreg_db/data/unit/weight.yaml +37 -30
- endoreg_db/data/waste/data.yaml +12 -0
- endoreg_db/forms/__init__.py +2 -2
- endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -23
- endoreg_db/forms/settings/__init__.py +8 -8
- endoreg_db/forms/unit.py +5 -5
- endoreg_db/management/commands/_load_model_template.py +40 -40
- endoreg_db/management/commands/delete_all.py +18 -18
- endoreg_db/management/commands/delete_legacy_images.py +19 -19
- endoreg_db/management/commands/delete_legacy_videos.py +16 -16
- endoreg_db/management/commands/extract_legacy_video_frames.py +18 -18
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +32 -32
- endoreg_db/management/commands/fix_auth_permission.py +20 -20
- endoreg_db/management/commands/import_legacy_images.py +94 -94
- endoreg_db/management/commands/import_legacy_videos.py +76 -76
- endoreg_db/management/commands/load_active_model_data.py +44 -44
- endoreg_db/management/commands/load_ai_model_data.py +44 -44
- endoreg_db/management/commands/load_base_db_data.py +128 -71
- endoreg_db/management/commands/load_center_data.py +42 -42
- endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
- endoreg_db/management/commands/load_disease_classification_data.py +41 -0
- endoreg_db/management/commands/load_disease_data.py +40 -0
- endoreg_db/management/commands/load_distribution_data.py +66 -0
- endoreg_db/management/commands/load_endoscope_type_data.py +44 -44
- endoreg_db/management/commands/load_endoscopy_processor_data.py +44 -44
- endoreg_db/management/commands/load_event_data.py +41 -0
- endoreg_db/management/commands/load_examination_data.py +74 -74
- endoreg_db/management/commands/load_g_play_data.py +113 -0
- endoreg_db/management/commands/load_gender_data.py +44 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +133 -0
- endoreg_db/management/commands/load_information_source.py +44 -44
- endoreg_db/management/commands/load_lab_value_data.py +50 -0
- endoreg_db/management/commands/load_label_data.py +66 -66
- endoreg_db/management/commands/load_medication_data.py +41 -0
- endoreg_db/management/commands/load_medication_indication_data.py +63 -0
- endoreg_db/management/commands/load_medication_indication_type_data.py +41 -0
- endoreg_db/management/commands/load_medication_intake_time_data.py +41 -0
- endoreg_db/management/commands/load_medication_schedule_data.py +55 -0
- endoreg_db/management/commands/load_pdf_type_data.py +60 -60
- endoreg_db/management/commands/load_profession_data.py +43 -43
- endoreg_db/management/commands/load_report_reader_flag.py +45 -45
- endoreg_db/management/commands/load_unit_data.py +45 -45
- endoreg_db/management/commands/load_user_groups.py +28 -28
- endoreg_db/management/commands/register_ai_model.py +65 -65
- endoreg_db/management/commands/reset_celery_schedule.py +9 -9
- endoreg_db/migrations/0001_initial.py +582 -582
- endoreg_db/migrations/0002_rawvideofile.py +26 -26
- endoreg_db/migrations/0003_rawvideofile_frames_required.py +18 -18
- endoreg_db/migrations/0004_rename_hash_rawvideofile_video_hash.py +18 -18
- endoreg_db/migrations/0005_ffmpegmeta_remove_videoimportmeta_center_and_more.py +56 -56
- endoreg_db/migrations/0006_rawvideofile_center_alter_videometa_processor.py +25 -25
- endoreg_db/migrations/0007_rawvideofile_processor.py +19 -19
- endoreg_db/migrations/0008_rename_frames_required_rawvideofile_state_frames_required.py +18 -18
- endoreg_db/migrations/0009_sensitivemeta_rawvideofile_sensitive_meta.py +31 -31
- endoreg_db/migrations/0010_rename_endoscope_serial_number_sensitivemeta_endoscope_sn.py +18 -18
- endoreg_db/migrations/0011_rawvideofile_state_sensitive_data_retrieved.py +18 -18
- endoreg_db/migrations/0012_rawvideofile_prediction_dir_and_more.py +109 -109
- endoreg_db/migrations/0013_rawpdffile.py +31 -31
- endoreg_db/migrations/0014_pdftype_alter_rawpdffile_file_pdfmeta.py +38 -38
- endoreg_db/migrations/0015_rename_report_processed_rawpdffile_state_report_processed_and_more.py +31 -31
- endoreg_db/migrations/0016_rawpdffile_state_report_processing_required.py +18 -18
- endoreg_db/migrations/0017_firstname_lastname_center_first_names_and_more.py +37 -37
- endoreg_db/migrations/0018_reportreaderflag_reportreaderconfig.py +37 -37
- endoreg_db/migrations/0019_pdftype_cut_off_above_lines_and_more.py +42 -42
- endoreg_db/migrations/0020_rename_endoscopy_info_line_pdftype_endoscope_info_line.py +18 -18
- endoreg_db/migrations/0021_alter_pdftype_endoscope_info_line.py +19 -19
- endoreg_db/migrations/0022_alter_pdftype_endoscope_info_line.py +19 -19
- endoreg_db/migrations/0023_ttoquestionnaire_alter_pdftype_endoscope_info_line.py +59 -59
- endoreg_db/migrations/0024_remove_ttoquestionnaire_infections_and_more.py +27 -27
- endoreg_db/migrations/0025_event_alter_rawpdffile_file_patientevent.py +42 -0
- endoreg_db/migrations/0026_disease_diseaseclassification_and_more.py +166 -0
- endoreg_db/migrations/0027_labvalue_abbreviation_labvalue_default_normal_range_and_more.py +38 -0
- endoreg_db/migrations/0028_alter_unit_abbreviation.py +18 -0
- endoreg_db/migrations/0029_medicationintaketime_and_more.py +75 -0
- endoreg_db/migrations/0030_medicationindicationtype_and_more.py +101 -0
- endoreg_db/migrations/0031_rename_adapt_to_liver_function_medication_adapt_to_age_and_more.py +38 -0
- endoreg_db/migrations/0032_alter_medicationschedule_therapy_duration_d.py +18 -0
- endoreg_db/migrations/0033_medicationindication_sources.py +18 -0
- endoreg_db/migrations/0034_alter_rawpdffile_file.py +20 -0
- endoreg_db/migrations/0035_alter_medicationindication_sources.py +18 -0
- endoreg_db/migrations/0036_alter_rawpdffile_file.py +20 -0
- endoreg_db/migrations/0037_alter_medicationindication_sources.py +18 -0
- endoreg_db/migrations/0038_emissionfactor_material_product_productgroup_and_more.py +164 -0
- endoreg_db/migrations/0039_referenceproduct_name.py +19 -0
- endoreg_db/migrations/0040_quizanswertype_quizquestiontype_quizquestion_and_more.py +50 -0
- endoreg_db/migrations/0041_gender_patientmedication_medication_indication_and_more.py +40 -0
- endoreg_db/migrations/0042_casetemplateruletype_casetemplaterulevalue_and_more.py +74 -0
- endoreg_db/migrations/0043_casetemplatetype_name_de_casetemplatetype_name_en.py +23 -0
- endoreg_db/migrations/0044_casetemplateruletype_name_de_and_more.py +23 -0
- endoreg_db/migrations/0045_casetemplaterulevalue_value_type.py +19 -0
- endoreg_db/migrations/0046_casetemplaterulevalue_target_field.py +18 -0
- endoreg_db/migrations/0047_casetemplaterule_target_model.py +18 -0
- endoreg_db/migrations/0048_remove_casetemplaterule_chained_rules_and_more.py +22 -0
- endoreg_db/migrations/0049_remove_casetemplaterule_rule_values.py +17 -0
- endoreg_db/migrations/0050_casetemplaterule_rule_values.py +18 -0
- endoreg_db/migrations/0051_remove_casetemplaterule_calling_rules_and_more.py +27 -0
- endoreg_db/migrations/0052_rename_case_template_type_casetemplate_template_type.py +18 -0
- endoreg_db/migrations/0053_patientlabsampletype_patientlabsample_and_more.py +38 -0
- endoreg_db/migrations/0054_multiplecategoricalvaluedistribution_and_more.py +69 -0
- endoreg_db/migrations/0055_remove_casetemplaterule_rule_values_and_more.py +59 -0
- endoreg_db/migrations/0056_datevaluedistribution_and_more.py +32 -0
- endoreg_db/migrations/0057_remove_datevaluedistribution_max_date_and_more.py +72 -0
- endoreg_db/migrations/0058_datevaluedistribution_description_and_more.py +28 -0
- endoreg_db/migrations/0059_casetemplaterule_rule_values.py +18 -0
- endoreg_db/migrations/0060_labvalue__default_date_value_distribution_and_more.py +44 -0
- endoreg_db/migrations/0061_remove_patientlabvalue_date_patientlabvalue_datetime.py +24 -0
- endoreg_db/migrations/0062_labvalue_numeric_precision.py +18 -0
- endoreg_db/migrations/0063_alter_labvalue_numeric_precision.py +18 -0
- endoreg_db/migrations/0064_casetemplaterule_extra_parameters_and_more.py +23 -0
- endoreg_db/migrations/0065_rename__date_value_distribution_casetemplaterule_date_value_distribution_and_more.py +58 -0
- endoreg_db/migrations/0066_alter_patientlabvalue_patient_and_more.py +29 -0
- endoreg_db/migrations/0067_alter_medicationindication_indication_type.py +19 -0
- endoreg_db/models/__init__.py +74 -57
- endoreg_db/models/ai_model/__init__.py +3 -3
- endoreg_db/models/ai_model/active_model.py +9 -9
- endoreg_db/models/ai_model/model_meta.py +24 -24
- endoreg_db/models/ai_model/model_type.py +25 -25
- endoreg_db/models/ai_model/utils.py +8 -8
- endoreg_db/models/annotation/__init__.py +1 -1
- endoreg_db/models/annotation/binary_classification_annotation_task.py +80 -80
- endoreg_db/models/annotation/image_classification.py +26 -26
- endoreg_db/models/case_template/__init__.py +6 -0
- endoreg_db/models/case_template/case_template.py +81 -0
- endoreg_db/models/case_template/case_template_rule.py +276 -0
- endoreg_db/models/case_template/case_template_rule_value.py +73 -0
- endoreg_db/models/case_template/case_template_type.py +28 -0
- endoreg_db/models/center/__init__.py +4 -0
- endoreg_db/models/{center.py → center/center.py} +24 -24
- endoreg_db/models/center/center_product.py +34 -0
- endoreg_db/models/center/center_resource.py +19 -0
- endoreg_db/models/center/center_waste.py +11 -0
- endoreg_db/models/data_file/__init__.py +5 -5
- endoreg_db/models/data_file/base_classes/__init__.py +2 -2
- endoreg_db/models/data_file/base_classes/abstract_frame.py +50 -50
- endoreg_db/models/data_file/base_classes/abstract_video.py +200 -200
- endoreg_db/models/data_file/frame.py +45 -45
- endoreg_db/models/data_file/import_classes/__init__.py +31 -31
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +34 -34
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +28 -28
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +260 -260
- endoreg_db/models/data_file/import_classes/raw_pdf.py +188 -185
- endoreg_db/models/data_file/import_classes/raw_video.py +343 -343
- endoreg_db/models/data_file/metadata/__init__.py +3 -3
- endoreg_db/models/data_file/metadata/pdf_meta.py +70 -70
- endoreg_db/models/data_file/metadata/sensitive_meta.py +31 -31
- endoreg_db/models/data_file/metadata/video_meta.py +132 -131
- endoreg_db/models/data_file/report_file.py +89 -89
- endoreg_db/models/data_file/video/__init__.py +6 -6
- endoreg_db/models/data_file/video/import_meta.py +25 -25
- endoreg_db/models/data_file/video/video.py +25 -25
- endoreg_db/models/data_file/video_segment.py +107 -107
- endoreg_db/models/disease.py +56 -0
- endoreg_db/models/emission/__init__.py +1 -0
- endoreg_db/models/emission/emission_factor.py +20 -0
- endoreg_db/models/event.py +22 -0
- endoreg_db/models/examination/__init__.py +3 -3
- endoreg_db/models/examination/examination.py +26 -26
- endoreg_db/models/examination/examination_time.py +27 -27
- endoreg_db/models/examination/examination_time_type.py +24 -24
- endoreg_db/models/examination/examination_type.py +18 -18
- endoreg_db/models/hardware/__init__.py +1 -1
- endoreg_db/models/hardware/endoscope.py +44 -44
- endoreg_db/models/hardware/endoscopy_processor.py +143 -143
- endoreg_db/models/information_source.py +29 -22
- endoreg_db/models/label/label.py +84 -84
- endoreg_db/models/laboratory/__init__.py +1 -0
- endoreg_db/models/laboratory/lab_value.py +102 -0
- endoreg_db/models/legacy_data/__init__.py +3 -3
- endoreg_db/models/legacy_data/image.py +34 -34
- endoreg_db/models/medication/__init__.py +1 -0
- endoreg_db/models/medication/medication.py +148 -0
- endoreg_db/models/other/__init__.py +5 -0
- endoreg_db/models/other/distribution.py +215 -0
- endoreg_db/models/other/material.py +16 -0
- endoreg_db/models/other/resource.py +18 -0
- endoreg_db/models/other/transport_route.py +21 -0
- endoreg_db/models/other/waste.py +20 -0
- endoreg_db/models/patient_examination/__init__.py +35 -35
- endoreg_db/models/permissions/__init__.py +44 -44
- endoreg_db/models/persons/__init__.py +7 -6
- endoreg_db/models/persons/examiner/__init__.py +1 -1
- endoreg_db/models/persons/examiner/examiner.py +15 -15
- endoreg_db/models/persons/examiner/examiner_type.py +1 -1
- endoreg_db/models/persons/first_name.py +17 -17
- endoreg_db/models/persons/gender.py +22 -0
- endoreg_db/models/persons/last_name.py +19 -19
- endoreg_db/models/persons/patient/__init__.py +8 -0
- endoreg_db/models/persons/patient/case/__init__.py +0 -0
- endoreg_db/models/persons/patient/case/case.py +30 -0
- endoreg_db/models/persons/patient/patient.py +216 -0
- endoreg_db/models/persons/patient/patient_disease.py +16 -0
- endoreg_db/models/persons/patient/patient_event.py +22 -0
- endoreg_db/models/persons/patient/patient_lab_sample.py +106 -0
- endoreg_db/models/persons/patient/patient_lab_value.py +176 -0
- endoreg_db/models/persons/patient/patient_medication.py +44 -0
- endoreg_db/models/persons/patient/patient_medication_schedule.py +28 -0
- endoreg_db/models/persons/person.py +31 -34
- endoreg_db/models/persons/portal_user_information.py +27 -29
- endoreg_db/models/prediction/__init__.py +1 -1
- endoreg_db/models/prediction/image_classification.py +37 -37
- endoreg_db/models/prediction/video_prediction_meta.py +244 -244
- endoreg_db/models/product/__init__.py +5 -0
- endoreg_db/models/product/product.py +97 -0
- endoreg_db/models/product/product_group.py +19 -0
- endoreg_db/models/product/product_material.py +24 -0
- endoreg_db/models/product/product_weight.py +26 -0
- endoreg_db/models/product/reference_product.py +99 -0
- endoreg_db/models/questionnaires/__init__.py +114 -114
- endoreg_db/models/quiz/__init__.py +2 -0
- endoreg_db/models/quiz/quiz_answer.py +41 -0
- endoreg_db/models/quiz/quiz_question.py +54 -0
- endoreg_db/models/report_reader/__init__.py +1 -1
- endoreg_db/models/report_reader/report_reader_config.py +53 -53
- endoreg_db/models/report_reader/report_reader_flag.py +19 -19
- endoreg_db/models/rules/__init__.py +5 -0
- endoreg_db/models/rules/rule.py +24 -0
- endoreg_db/models/rules/rule_applicator.py +224 -0
- endoreg_db/models/rules/rule_attribute_dtype.py +19 -0
- endoreg_db/models/rules/rule_type.py +22 -0
- endoreg_db/models/rules/ruleset.py +19 -0
- endoreg_db/models/unit.py +21 -19
- endoreg_db/queries/__init__.py +4 -4
- endoreg_db/queries/annotations/__init__.py +2 -2
- endoreg_db/queries/annotations/legacy.py +159 -159
- endoreg_db/queries/get/__init__.py +5 -5
- endoreg_db/queries/get/center.py +42 -42
- endoreg_db/queries/get/model.py +13 -13
- endoreg_db/queries/get/patient.py +14 -14
- endoreg_db/queries/get/patient_examination.py +20 -20
- endoreg_db/queries/get/report_file.py +33 -33
- endoreg_db/queries/get/video.py +31 -31
- endoreg_db/serializers/__init__.py +9 -9
- endoreg_db/serializers/ai_model.py +18 -18
- endoreg_db/serializers/annotation.py +17 -17
- endoreg_db/serializers/center.py +11 -11
- endoreg_db/serializers/examination.py +32 -32
- endoreg_db/serializers/frame.py +13 -13
- endoreg_db/serializers/hardware.py +20 -20
- endoreg_db/serializers/label.py +22 -22
- endoreg_db/serializers/patient.py +10 -10
- endoreg_db/serializers/prediction.py +15 -15
- endoreg_db/serializers/report_file.py +7 -7
- endoreg_db/serializers/video.py +27 -27
- endoreg_db/tests.py +3 -3
- endoreg_db/utils/cropping.py +28 -28
- endoreg_db/utils/dataloader.py +92 -185
- endoreg_db/utils/file_operations.py +30 -30
- endoreg_db/utils/hashs.py +33 -33
- endoreg_db/utils/legacy_ocr.py +201 -201
- endoreg_db/utils/ocr.py +197 -197
- endoreg_db/utils/uuid.py +4 -4
- endoreg_db/utils/video_metadata.py +87 -87
- endoreg_db/views.py +3 -3
- {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/LICENSE +674 -674
- {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/METADATA +2 -2
- endoreg_db-0.3.6.dist-info/RECORD +357 -0
- {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/WHEEL +1 -1
- endoreg_db/models/persons/patient.py +0 -58
- endoreg_db/models.py +0 -3
- endoreg_db-0.3.4.dist-info/RECORD +0 -185
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
from django.db import models
|
|
2
|
-
|
|
3
|
-
# Serializer located in serializers/examination.py
|
|
4
|
-
class PatientExamination(models.Model):
|
|
5
|
-
patient = models.ForeignKey('Patient', on_delete=models.CASCADE, related_name='patient_examinations')
|
|
6
|
-
examination = models.ForeignKey('Examination', on_delete=models.CASCADE, null = True, blank = True)
|
|
7
|
-
video = models.OneToOneField('Video', on_delete=models.CASCADE, null = True, blank = True, related_name='patient_examination')
|
|
8
|
-
report_file = models.OneToOneField('ReportFile', on_delete=models.CASCADE, null = True, blank = True, related_name='patient_examination')
|
|
9
|
-
|
|
10
|
-
class Meta:
|
|
11
|
-
verbose_name = 'Patient Examination'
|
|
12
|
-
verbose_name_plural = 'Patient Examinations'
|
|
13
|
-
ordering = ['patient', 'examination']
|
|
14
|
-
|
|
15
|
-
def __str__(self):
|
|
16
|
-
return f"{self.patient} - {self.report_file}"
|
|
17
|
-
|
|
18
|
-
def find_matching_video_from_patient(self):
|
|
19
|
-
"""
|
|
20
|
-
Finds a video for this patient examination based on the patient's videos.
|
|
21
|
-
For this, the videos date must be the same as the report file's date.
|
|
22
|
-
#TODO add more criteria for matching: Examination type
|
|
23
|
-
"""
|
|
24
|
-
videos = self.patient.video_set.filter(date=self.report_file.date, patient_examination__isnull=True)
|
|
25
|
-
if videos:
|
|
26
|
-
if len(videos) > 1:
|
|
27
|
-
print(f"Warning: Found more than one video for patient {self.patient} on date {self.report_file.date}. Choosing the first one.")
|
|
28
|
-
return videos[0]
|
|
29
|
-
else:
|
|
30
|
-
videos = self.patient.video_set.filter(patient_examination__isnull=True)
|
|
31
|
-
if len(videos)==1:
|
|
32
|
-
return videos[0]
|
|
33
|
-
|
|
34
|
-
return None
|
|
35
|
-
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
# Serializer located in serializers/examination.py
|
|
4
|
+
class PatientExamination(models.Model):
|
|
5
|
+
patient = models.ForeignKey('Patient', on_delete=models.CASCADE, related_name='patient_examinations')
|
|
6
|
+
examination = models.ForeignKey('Examination', on_delete=models.CASCADE, null = True, blank = True)
|
|
7
|
+
video = models.OneToOneField('Video', on_delete=models.CASCADE, null = True, blank = True, related_name='patient_examination')
|
|
8
|
+
report_file = models.OneToOneField('ReportFile', on_delete=models.CASCADE, null = True, blank = True, related_name='patient_examination')
|
|
9
|
+
|
|
10
|
+
class Meta:
|
|
11
|
+
verbose_name = 'Patient Examination'
|
|
12
|
+
verbose_name_plural = 'Patient Examinations'
|
|
13
|
+
ordering = ['patient', 'examination']
|
|
14
|
+
|
|
15
|
+
def __str__(self):
|
|
16
|
+
return f"{self.patient} - {self.report_file}"
|
|
17
|
+
|
|
18
|
+
def find_matching_video_from_patient(self):
|
|
19
|
+
"""
|
|
20
|
+
Finds a video for this patient examination based on the patient's videos.
|
|
21
|
+
For this, the videos date must be the same as the report file's date.
|
|
22
|
+
#TODO add more criteria for matching: Examination type
|
|
23
|
+
"""
|
|
24
|
+
videos = self.patient.video_set.filter(date=self.report_file.date, patient_examination__isnull=True)
|
|
25
|
+
if videos:
|
|
26
|
+
if len(videos) > 1:
|
|
27
|
+
print(f"Warning: Found more than one video for patient {self.patient} on date {self.report_file.date}. Choosing the first one.")
|
|
28
|
+
return videos[0]
|
|
29
|
+
else:
|
|
30
|
+
videos = self.patient.video_set.filter(patient_examination__isnull=True)
|
|
31
|
+
if len(videos)==1:
|
|
32
|
+
return videos[0]
|
|
33
|
+
|
|
34
|
+
return None
|
|
35
|
+
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
from django.contrib.contenttypes.models import ContentType
|
|
2
|
-
from django.contrib.auth.models import Permission
|
|
3
|
-
from endoreg_db.models import * # Import your models here
|
|
4
|
-
from django.db import transaction
|
|
5
|
-
|
|
6
|
-
# Step 1: Define model to category mappings
|
|
7
|
-
# Assuming every model class name is unique across your entire Django project
|
|
8
|
-
model_categories = {
|
|
9
|
-
'SensitiveModel1': 'sensitive',
|
|
10
|
-
'SensitiveModel2': 'sensitive',
|
|
11
|
-
'DevelopmentModel1': 'development',
|
|
12
|
-
'DevelopmentModel2': 'development',
|
|
13
|
-
# Add all models you have, mapping them to either 'sensitive', 'development', or 'all'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
# Step 2: Define permissions for each category
|
|
17
|
-
category_permissions = {
|
|
18
|
-
'sensitive': ['view', 'edit', 'delete'],
|
|
19
|
-
'development': ['view', 'edit'],
|
|
20
|
-
'all': ['view'],
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@transaction.atomic
|
|
24
|
-
def create_permissions_for_all_models():
|
|
25
|
-
for model_class_name, category in model_categories.items():
|
|
26
|
-
model_class = globals().get(model_class_name)
|
|
27
|
-
if model_class is None:
|
|
28
|
-
print(f"Model {model_class_name} not found.")
|
|
29
|
-
continue
|
|
30
|
-
|
|
31
|
-
content_type = ContentType.objects.get_for_model(model_class)
|
|
32
|
-
permissions = category_permissions.get(category, [])
|
|
33
|
-
|
|
34
|
-
for permission_codename in permissions:
|
|
35
|
-
permission_name = f"Can {permission_codename} {model_class_name}"
|
|
36
|
-
permission, created = Permission.objects.get_or_create(
|
|
37
|
-
codename=f"{permission_codename}_{model_class_name.lower()}",
|
|
38
|
-
defaults={'name': permission_name, 'content_type': content_type},
|
|
39
|
-
)
|
|
40
|
-
if created:
|
|
41
|
-
print(f"Created permission: {permission_name}")
|
|
42
|
-
|
|
43
|
-
# Run the function to create and assign permissions based on categories
|
|
44
|
-
create_permissions_for_all_models()
|
|
1
|
+
from django.contrib.contenttypes.models import ContentType
|
|
2
|
+
from django.contrib.auth.models import Permission
|
|
3
|
+
from endoreg_db.models import * # Import your models here
|
|
4
|
+
from django.db import transaction
|
|
5
|
+
|
|
6
|
+
# Step 1: Define model to category mappings
|
|
7
|
+
# Assuming every model class name is unique across your entire Django project
|
|
8
|
+
model_categories = {
|
|
9
|
+
'SensitiveModel1': 'sensitive',
|
|
10
|
+
'SensitiveModel2': 'sensitive',
|
|
11
|
+
'DevelopmentModel1': 'development',
|
|
12
|
+
'DevelopmentModel2': 'development',
|
|
13
|
+
# Add all models you have, mapping them to either 'sensitive', 'development', or 'all'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
# Step 2: Define permissions for each category
|
|
17
|
+
category_permissions = {
|
|
18
|
+
'sensitive': ['view', 'edit', 'delete'],
|
|
19
|
+
'development': ['view', 'edit'],
|
|
20
|
+
'all': ['view'],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@transaction.atomic
|
|
24
|
+
def create_permissions_for_all_models():
|
|
25
|
+
for model_class_name, category in model_categories.items():
|
|
26
|
+
model_class = globals().get(model_class_name)
|
|
27
|
+
if model_class is None:
|
|
28
|
+
print(f"Model {model_class_name} not found.")
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
content_type = ContentType.objects.get_for_model(model_class)
|
|
32
|
+
permissions = category_permissions.get(category, [])
|
|
33
|
+
|
|
34
|
+
for permission_codename in permissions:
|
|
35
|
+
permission_name = f"Can {permission_codename} {model_class_name}"
|
|
36
|
+
permission, created = Permission.objects.get_or_create(
|
|
37
|
+
codename=f"{permission_codename}_{model_class_name.lower()}",
|
|
38
|
+
defaults={'name': permission_name, 'content_type': content_type},
|
|
39
|
+
)
|
|
40
|
+
if created:
|
|
41
|
+
print(f"Created permission: {permission_name}")
|
|
42
|
+
|
|
43
|
+
# Run the function to create and assign permissions based on categories
|
|
44
|
+
create_permissions_for_all_models()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from .
|
|
2
|
-
from .
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
1
|
+
from .gender import Gender
|
|
2
|
+
from .person import Person
|
|
3
|
+
from .patient import *
|
|
4
|
+
from .examiner import Examiner, ExaminerSerializer
|
|
5
|
+
from .portal_user_information import PortalUserInfo, Profession
|
|
6
|
+
from .first_name import FirstName
|
|
7
|
+
from .last_name import LastName
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .examiner import Examiner, ExaminerSerializer
|
|
1
|
+
from .examiner import Examiner, ExaminerSerializer
|
|
2
2
|
# from .examiner_type import ExaminerType
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
from django.db import models
|
|
2
|
-
from ..person import Person
|
|
3
|
-
from rest_framework import serializers
|
|
4
|
-
|
|
5
|
-
class Examiner(Person):
|
|
6
|
-
center = models.ForeignKey('Center', on_delete=models.CASCADE, blank=True, null=True)
|
|
7
|
-
|
|
8
|
-
def __str__(self):
|
|
9
|
-
return self.first_name + " " + self.last_name
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ExaminerSerializer(serializers.ModelSerializer):
|
|
13
|
-
|
|
14
|
-
class Meta:
|
|
15
|
-
model = Examiner
|
|
1
|
+
from django.db import models
|
|
2
|
+
from ..person import Person
|
|
3
|
+
from rest_framework import serializers
|
|
4
|
+
|
|
5
|
+
class Examiner(Person):
|
|
6
|
+
center = models.ForeignKey('Center', on_delete=models.CASCADE, blank=True, null=True)
|
|
7
|
+
|
|
8
|
+
def __str__(self):
|
|
9
|
+
return self.first_name + " " + self.last_name
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExaminerSerializer(serializers.ModelSerializer):
|
|
13
|
+
|
|
14
|
+
class Meta:
|
|
15
|
+
model = Examiner
|
|
16
16
|
fields = '__all__'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .examiner import Examiner
|
|
1
|
+
from .examiner import Examiner
|
|
2
2
|
# from .examiner_type import ExaminerType
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# class to represent unique first-names
|
|
2
|
-
# name attribute is natural key
|
|
3
|
-
|
|
4
|
-
from django.db import models
|
|
5
|
-
|
|
6
|
-
class FirstNameManager(models.Manager):
|
|
7
|
-
def get_by_natural_key(self, name):
|
|
8
|
-
return self.get(name=name)
|
|
9
|
-
|
|
10
|
-
class FirstName(models.Model):
|
|
11
|
-
objects = FirstNameManager()
|
|
12
|
-
name = models.CharField(max_length=255, unique=True)
|
|
13
|
-
|
|
14
|
-
def natural_key(self):
|
|
15
|
-
return (self.name,)
|
|
16
|
-
|
|
17
|
-
def __str__(self):
|
|
1
|
+
# class to represent unique first-names
|
|
2
|
+
# name attribute is natural key
|
|
3
|
+
|
|
4
|
+
from django.db import models
|
|
5
|
+
|
|
6
|
+
class FirstNameManager(models.Manager):
|
|
7
|
+
def get_by_natural_key(self, name):
|
|
8
|
+
return self.get(name=name)
|
|
9
|
+
|
|
10
|
+
class FirstName(models.Model):
|
|
11
|
+
objects = FirstNameManager()
|
|
12
|
+
name = models.CharField(max_length=255, unique=True)
|
|
13
|
+
|
|
14
|
+
def natural_key(self):
|
|
15
|
+
return (self.name,)
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
18
|
return self.name
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
class GenderManager(models.Manager):
|
|
4
|
+
def get_by_natural_key(self, name):
|
|
5
|
+
return self.get(name=name)
|
|
6
|
+
|
|
7
|
+
class Gender(models.Model):
|
|
8
|
+
"""A class representing gender."""
|
|
9
|
+
objects = GenderManager()
|
|
10
|
+
|
|
11
|
+
name = models.CharField(max_length=255)
|
|
12
|
+
name_de = models.CharField(max_length=255, null=True)
|
|
13
|
+
name_en = models.CharField(max_length=255, null=True)
|
|
14
|
+
abbreviation = models.CharField(max_length=255, null=True)
|
|
15
|
+
description = models.TextField(blank=True, null=True)
|
|
16
|
+
|
|
17
|
+
def natural_key(self):
|
|
18
|
+
return (self.name,)
|
|
19
|
+
|
|
20
|
+
def __str__(self):
|
|
21
|
+
return self.name
|
|
22
|
+
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# class to represent unique last_names
|
|
2
|
-
# name attribute is natural key
|
|
3
|
-
from django.db import models
|
|
4
|
-
|
|
5
|
-
class LastNameManager(models.Manager):
|
|
6
|
-
def get_by_natural_key(self, name):
|
|
7
|
-
return self.get(name=name)
|
|
8
|
-
|
|
9
|
-
class LastName(models.Model):
|
|
10
|
-
objects = LastNameManager()
|
|
11
|
-
name = models.CharField(max_length=255, unique=True)
|
|
12
|
-
|
|
13
|
-
def natural_key(self):
|
|
14
|
-
return (self.name,)
|
|
15
|
-
|
|
16
|
-
def __str__(self):
|
|
17
|
-
return self.name
|
|
18
|
-
|
|
19
|
-
# Path: endoreg_db/models/persons/first_name.py
|
|
1
|
+
# class to represent unique last_names
|
|
2
|
+
# name attribute is natural key
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
5
|
+
class LastNameManager(models.Manager):
|
|
6
|
+
def get_by_natural_key(self, name):
|
|
7
|
+
return self.get(name=name)
|
|
8
|
+
|
|
9
|
+
class LastName(models.Model):
|
|
10
|
+
objects = LastNameManager()
|
|
11
|
+
name = models.CharField(max_length=255, unique=True)
|
|
12
|
+
|
|
13
|
+
def natural_key(self):
|
|
14
|
+
return (self.name,)
|
|
15
|
+
|
|
16
|
+
def __str__(self):
|
|
17
|
+
return self.name
|
|
18
|
+
|
|
19
|
+
# Path: endoreg_db/models/persons/first_name.py
|
|
20
20
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .patient import Patient, PatientForm
|
|
2
|
+
from .patient_event import PatientEvent
|
|
3
|
+
from .patient_disease import PatientDisease
|
|
4
|
+
from .patient_lab_sample import PatientLabSample, PatientLabSampleType
|
|
5
|
+
from .patient_lab_value import PatientLabValue
|
|
6
|
+
from .patient_medication import PatientMedication
|
|
7
|
+
from .patient_medication_schedule import PatientMedicationSchedule
|
|
8
|
+
from .case import *
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
class Case(models.Model):
|
|
4
|
+
"""
|
|
5
|
+
A class representing a case.
|
|
6
|
+
|
|
7
|
+
Attributes:
|
|
8
|
+
name (str): The name of the case.
|
|
9
|
+
description (str): A description of the case.
|
|
10
|
+
case_template (CaseTemplate): The case template of the case.
|
|
11
|
+
patient (Patient): The patient of the case.
|
|
12
|
+
start_date (datetime): The start date of the case.
|
|
13
|
+
end_date (datetime): The end date of the case.
|
|
14
|
+
is_active (bool): A flag indicating whether the case is active.
|
|
15
|
+
is_closed (bool): A flag indicating whether the case is closed.
|
|
16
|
+
is_deleted (bool): A flag indicating whether the case is deleted.
|
|
17
|
+
created_at (datetime): The creation date of the case.
|
|
18
|
+
updated_at (datetime): The last update date of the case.
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
start_date = models.DateTimeField()
|
|
22
|
+
end_date = models.DateTimeField(null=True)
|
|
23
|
+
is_active = models.BooleanField(default=True)
|
|
24
|
+
is_closed = models.BooleanField(default=False)
|
|
25
|
+
is_deleted = models.BooleanField(default=False)
|
|
26
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
27
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
28
|
+
|
|
29
|
+
def __str__(self):
|
|
30
|
+
return self.name
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from ..person import Person
|
|
2
|
+
from django import forms
|
|
3
|
+
from django.forms import DateInput
|
|
4
|
+
from rest_framework import serializers
|
|
5
|
+
from ...patient_examination import PatientExamination
|
|
6
|
+
from ...data_file import ReportFile
|
|
7
|
+
from django.db import models
|
|
8
|
+
from faker import Faker
|
|
9
|
+
import random
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
class Patient(Person):
|
|
13
|
+
"""
|
|
14
|
+
A class representing a patient.
|
|
15
|
+
|
|
16
|
+
Attributes inhereted from Person:
|
|
17
|
+
first_name (str): The first name of the patient.
|
|
18
|
+
last_name (str): The last name of the patient.
|
|
19
|
+
dob (datetime.date): The date of birth of the patient.
|
|
20
|
+
gender (Foreign Key): The gender of the patient.
|
|
21
|
+
email (str): The email address of the patient.
|
|
22
|
+
phone (str): The phone number of the patient.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
center = models.ForeignKey("Center", on_delete=models.CASCADE, blank=True, null=True)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __str__(self):
|
|
29
|
+
return self.first_name + " " + self.last_name + " (" + str(self.dob) + ")"
|
|
30
|
+
|
|
31
|
+
def get_unmatched_report_files(self): #field: self.report_files; filter: report_file.patient_examination = None
|
|
32
|
+
'''Returns all report files for this patient that are not matched to a patient examination.'''
|
|
33
|
+
|
|
34
|
+
return self.reportfile_set.filter(patient_examination=None)
|
|
35
|
+
|
|
36
|
+
def get_unmatched_video_files(self): #field: self.videos; filter: video.patient_examination = None
|
|
37
|
+
'''Returns all video files for this patient that are not matched to a patient examination.'''
|
|
38
|
+
return self.videos.filter(patient_examination=None)
|
|
39
|
+
|
|
40
|
+
def get_patient_examinations(self): #field: self.patient_examinations
|
|
41
|
+
'''Returns all patient examinations for this patient ordered by date (most recent is first).'''
|
|
42
|
+
return self.patient_examinations.order_by('-date')
|
|
43
|
+
|
|
44
|
+
def create_examination_by_report_file(self, report_file:ReportFile):
|
|
45
|
+
'''Creates a patient examination for this patient based on the given report file.'''
|
|
46
|
+
patient_examination = PatientExamination(patient=self, report_file=report_file)
|
|
47
|
+
patient_examination.save()
|
|
48
|
+
return patient_examination
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def get_random_gender(self, p_male=0.5, p_female=0.5):
|
|
52
|
+
"""
|
|
53
|
+
Get a Gender object by name (male, female) from the database with given probability.
|
|
54
|
+
|
|
55
|
+
:param p_male: Probability of selecting 'male' gender.
|
|
56
|
+
:param p_female: Probability of selecting 'female' gender.
|
|
57
|
+
:return: Gender object selected based on given probabilities.
|
|
58
|
+
"""
|
|
59
|
+
from endoreg_db.models import Gender
|
|
60
|
+
|
|
61
|
+
# Extract names and probabilities
|
|
62
|
+
gender_names = ["male", "female"]
|
|
63
|
+
probabilities = [0.5, 0.5]
|
|
64
|
+
|
|
65
|
+
# Debug: print the names and probabilities
|
|
66
|
+
print(f"Gender names: {gender_names}")
|
|
67
|
+
print(f"Probabilities: {probabilities}")
|
|
68
|
+
|
|
69
|
+
# Select a gender based on the given probabilities
|
|
70
|
+
selected_gender = random.choices(gender_names, probabilities)[0]
|
|
71
|
+
# Debug: print the selected gender
|
|
72
|
+
print(f"Selected gender: {selected_gender}")
|
|
73
|
+
|
|
74
|
+
# Fetch the corresponding Gender object from the database
|
|
75
|
+
gender_obj = Gender.objects.get(name=selected_gender)
|
|
76
|
+
|
|
77
|
+
return gender_obj
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def get_random_age(self,
|
|
82
|
+
min_age = 55,
|
|
83
|
+
max_age = 90,
|
|
84
|
+
mean_age = 65,
|
|
85
|
+
std_age = 10,
|
|
86
|
+
distribution = "normal"
|
|
87
|
+
):
|
|
88
|
+
"""
|
|
89
|
+
Get a random age based on the given distribution.
|
|
90
|
+
|
|
91
|
+
:param min_age: Minimum age.
|
|
92
|
+
:param max_age: Maximum age.
|
|
93
|
+
:param mean_age: Mean age.
|
|
94
|
+
:param std_age: Standard deviation of the age.
|
|
95
|
+
:param distribution: Distribution of the age.
|
|
96
|
+
:return: Random age based on the given distribution.
|
|
97
|
+
"""
|
|
98
|
+
if distribution == "normal":
|
|
99
|
+
age = int(random.normalvariate(mean_age, std_age))
|
|
100
|
+
else:
|
|
101
|
+
age = int(random.uniform(min_age, max_age))
|
|
102
|
+
|
|
103
|
+
return age
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def get_dob_from_age(self, age, current_date=None):
|
|
107
|
+
"""
|
|
108
|
+
Get a date of birth based on the given age and current date.
|
|
109
|
+
|
|
110
|
+
:param age: Age of the patient.
|
|
111
|
+
:param current_date: Current date.
|
|
112
|
+
:return: Date of birth based on the given age and current date.
|
|
113
|
+
"""
|
|
114
|
+
if current_date is None:
|
|
115
|
+
current_date = datetime.now()
|
|
116
|
+
dob = current_date.replace(year=current_date.year - age).date()
|
|
117
|
+
|
|
118
|
+
# TODO
|
|
119
|
+
# randomize the day and month by adding a random number of days (0-364) to the date
|
|
120
|
+
|
|
121
|
+
return dob
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def get_random_name_for_gender(self, gender_obj, locale="de_DE"):
|
|
125
|
+
gender = gender_obj.name
|
|
126
|
+
fake = Faker(locale)
|
|
127
|
+
|
|
128
|
+
if gender == "male":
|
|
129
|
+
first_name = fake.first_name_male()
|
|
130
|
+
last_name = fake.last_name_male()
|
|
131
|
+
|
|
132
|
+
else:
|
|
133
|
+
first_name = fake.first_name_female()
|
|
134
|
+
last_name = fake.last_name_female()
|
|
135
|
+
|
|
136
|
+
return last_name, first_name
|
|
137
|
+
|
|
138
|
+
@classmethod
|
|
139
|
+
def create_generic(self, center="gplay_case_generator"):
|
|
140
|
+
"""
|
|
141
|
+
Create a generic patient with random attributes.
|
|
142
|
+
|
|
143
|
+
:param center: The center of the patient.
|
|
144
|
+
:return: The created patient.
|
|
145
|
+
"""
|
|
146
|
+
from endoreg_db.models import Center
|
|
147
|
+
gender = Patient.get_random_gender()
|
|
148
|
+
last_name, first_name = Patient.get_random_name_for_gender(gender)
|
|
149
|
+
|
|
150
|
+
age = Patient.get_random_age()
|
|
151
|
+
dob = Patient.get_dob_from_age(age)
|
|
152
|
+
|
|
153
|
+
center = Center.objects.get(name=center)
|
|
154
|
+
|
|
155
|
+
patient = Patient.objects.create(
|
|
156
|
+
first_name=first_name,
|
|
157
|
+
last_name=last_name,
|
|
158
|
+
dob=dob
|
|
159
|
+
)
|
|
160
|
+
patient.save()
|
|
161
|
+
return patient
|
|
162
|
+
|
|
163
|
+
def age(self):
|
|
164
|
+
"""
|
|
165
|
+
Get the age of the patient.
|
|
166
|
+
|
|
167
|
+
:return: The age of the patient.
|
|
168
|
+
"""
|
|
169
|
+
# calculate correct age based on current date including day and month
|
|
170
|
+
current_date = datetime.now()
|
|
171
|
+
dob = self.dob
|
|
172
|
+
age = current_date.year - dob.year - ((current_date.month, current_date.day) < (dob.month, dob.day))
|
|
173
|
+
return age
|
|
174
|
+
|
|
175
|
+
def create_lab_sample(self, sample_type="generic", date=None, save=True):
|
|
176
|
+
"""
|
|
177
|
+
Create a lab sample for this patient.
|
|
178
|
+
|
|
179
|
+
:param sample_type: The sample type. Should be either string of the sample types
|
|
180
|
+
name or the sample type object. If not set, the default sample type ("generic") is used.
|
|
181
|
+
:param date: The date of the lab sample.
|
|
182
|
+
:return: The created lab sample.
|
|
183
|
+
"""
|
|
184
|
+
from endoreg_db.models import PatientLabSample, PatientLabSampleType
|
|
185
|
+
if date is None:
|
|
186
|
+
date = datetime.now()
|
|
187
|
+
|
|
188
|
+
if isinstance(sample_type, str):
|
|
189
|
+
sample_type = PatientLabSampleType.objects.get(name=sample_type)
|
|
190
|
+
assert sample_type is not None, f"Sample type with name '{sample_type}' not found."#
|
|
191
|
+
elif not isinstance(sample_type, PatientLabSampleType):
|
|
192
|
+
raise ValueError("Sample type must be either a string or a PatientLabSampleType object.")
|
|
193
|
+
|
|
194
|
+
patient_lab_sample = PatientLabSample.objects.create(
|
|
195
|
+
patient=self,
|
|
196
|
+
sample_type=sample_type,
|
|
197
|
+
date=date
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if save:
|
|
201
|
+
patient_lab_sample.save()
|
|
202
|
+
|
|
203
|
+
return patient_lab_sample
|
|
204
|
+
|
|
205
|
+
class PatientForm(forms.ModelForm):
|
|
206
|
+
class Meta:
|
|
207
|
+
model = Patient
|
|
208
|
+
fields = '__all__'
|
|
209
|
+
widgets = {
|
|
210
|
+
'dob': DateInput(attrs={'type': 'date'}),
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
def __init__(self, *args, **kwargs):
|
|
214
|
+
super().__init__(*args, **kwargs)
|
|
215
|
+
for field in self.fields.values():
|
|
216
|
+
field.widget.attrs['class'] = 'form-control'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PatientDisease(models.Model):
|
|
6
|
+
patient = models.ForeignKey("Patient", on_delete=models.CASCADE)
|
|
7
|
+
disease = models.ForeignKey("Disease", on_delete=models.CASCADE)
|
|
8
|
+
classification_choices = models.ManyToManyField("DiseaseClassificationChoice")
|
|
9
|
+
start_date = models.DateField(blank=True, null=True)
|
|
10
|
+
end_date = models.DateField(blank=True, null=True)
|
|
11
|
+
|
|
12
|
+
last_update = models.DateTimeField(auto_now=True)
|
|
13
|
+
|
|
14
|
+
def __str__(self):
|
|
15
|
+
return f"{self.patient} - {self.disease}"
|
|
16
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from .patient import Patient
|
|
3
|
+
|
|
4
|
+
class PatientEvent(models.Model):
|
|
5
|
+
"""
|
|
6
|
+
A class representing an event for a patient.
|
|
7
|
+
|
|
8
|
+
Attributes:
|
|
9
|
+
patient (Patient): The patient associated with this event.
|
|
10
|
+
date (datetime.date): The date of the event.
|
|
11
|
+
description (str): A description of the event.
|
|
12
|
+
"""
|
|
13
|
+
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
14
|
+
event = models.ForeignKey("Event", on_delete=models.CASCADE)
|
|
15
|
+
date_start = models.DateField()
|
|
16
|
+
date_end = models.DateField(blank=True, null=True)
|
|
17
|
+
description = models.TextField(blank=True, null=True)
|
|
18
|
+
|
|
19
|
+
last_update = models.DateTimeField(auto_now=True)
|
|
20
|
+
|
|
21
|
+
def __str__(self):
|
|
22
|
+
return str(self.date_start) + ": " + self.event
|