endoreg-db 0.4.5__py3-none-any.whl → 0.8.6.3__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 +90 -1
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +12 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +92 -0
- endoreg_db/config/env.py +101 -0
- endoreg_db/data/__init__.py +76 -4
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
- endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
- endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
- endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
- endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
- endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
- endoreg_db/data/center/data.yaml +40 -9
- endoreg_db/data/center_shift/ukw.yaml +9 -0
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/db_summary.csv +58 -0
- endoreg_db/data/db_summary.xlsx +0 -0
- endoreg_db/data/disease/misc.yaml +1 -2
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +2 -2
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +6 -6
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/endoscopy_processor/data.yaml +3 -0
- endoreg_db/data/event/cardiology.yaml +0 -13
- endoreg_db/data/examination/examinations/data.yaml +34 -28
- endoreg_db/data/examination/type/data.yaml +12 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +424 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +160 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/finding/complication.yaml +16 -0
- endoreg_db/data/finding/data.yaml +105 -0
- endoreg_db/data/finding/examination_setting.yaml +16 -0
- endoreg_db/data/finding/medication_related.yaml +18 -0
- endoreg_db/data/finding/outcome.yaml +12 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +43 -0
- endoreg_db/data/gender/data.yaml +24 -0
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
- endoreg_db/data/information_source/prediction.yaml +7 -0
- endoreg_db/data/information_source_type/data.yaml +8 -0
- endoreg_db/data/lab_value/cardiac_enzymes.yaml +7 -1
- endoreg_db/data/lab_value/coagulation.yaml +6 -1
- endoreg_db/data/lab_value/electrolytes.yaml +39 -1
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
- endoreg_db/data/lab_value/hematology.yaml +17 -2
- endoreg_db/data/lab_value/hormones.yaml +6 -0
- endoreg_db/data/lab_value/lipids.yaml +12 -3
- endoreg_db/data/lab_value/misc.yaml +48 -2
- endoreg_db/data/lab_value/renal_function.yaml +2 -1
- endoreg_db/data/lx_client_tag/base.yaml +54 -0
- endoreg_db/data/lx_client_type/base.yaml +30 -0
- endoreg_db/data/lx_permission/base.yaml +24 -0
- endoreg_db/data/lx_permission/endoreg.yaml +52 -0
- endoreg_db/data/medication/anticoagulation.yaml +5 -5
- endoreg_db/data/medication/tah.yaml +5 -5
- endoreg_db/data/medication_indication/anticoagulation.yaml +48 -53
- endoreg_db/data/medication_intake_time/base.yaml +4 -4
- endoreg_db/data/names_first/first_names.yaml +54 -0
- endoreg_db/data/names_last/last_names.yaml +51 -0
- endoreg_db/data/network_device/data.yaml +30 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/pdf_type/data.yaml +27 -9
- endoreg_db/data/qualification/endoscopy.yaml +36 -0
- endoreg_db/data/qualification/m2.yaml +39 -0
- endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
- endoreg_db/data/qualification/sonography.yaml +36 -0
- endoreg_db/data/qualification_type/base.yaml +29 -0
- endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +5 -0
- endoreg_db/data/requirement/age.yaml +26 -0
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/gender.yaml +25 -0
- endoreg_db/data/requirement/lab_value.yaml +441 -0
- endoreg_db/data/requirement/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/age.yaml +13 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +52 -0
- endoreg_db/data/requirement_set_type/data.yaml +20 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
- endoreg_db/data/risk/bleeding.yaml +26 -0
- endoreg_db/data/risk/thrombosis.yaml +37 -0
- endoreg_db/data/risk_type/data.yaml +27 -0
- endoreg_db/data/setup_config.yaml +38 -0
- endoreg_db/data/shift/endoscopy.yaml +21 -0
- endoreg_db/data/shift_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
- endoreg_db/data/unit/concentration.yaml +23 -0
- endoreg_db/data/unit/time.yaml +36 -1
- endoreg_db/exceptions.py +19 -0
- endoreg_db/forms/__init__.py +3 -1
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +18 -0
- endoreg_db/forms/patient_form.py +27 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/questionnaires/tto_questionnaire.py +19 -19
- endoreg_db/helpers/count_db.py +45 -0
- endoreg_db/helpers/data_loader.py +208 -0
- endoreg_db/helpers/default_objects.py +378 -0
- endoreg_db/helpers/download_segmentation_model.py +31 -0
- endoreg_db/helpers/interact.py +6 -0
- endoreg_db/helpers/test_video_helper.py +119 -0
- endoreg_db/logger_conf.py +140 -0
- endoreg_db/management/__init__.py +1 -0
- endoreg_db/management/commands/__init__.py +1 -0
- endoreg_db/management/commands/anonymize_video.py +0 -0
- endoreg_db/management/commands/check_auth.py +125 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +115 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
- endoreg_db/management/commands/fix_video_paths.py +165 -0
- endoreg_db/management/commands/import_fallback_video.py +203 -0
- endoreg_db/management/commands/import_report.py +298 -0
- endoreg_db/management/commands/import_video.py +423 -0
- endoreg_db/management/commands/import_video_with_classification.py +367 -0
- endoreg_db/management/commands/init_default_ai_model.py +112 -0
- endoreg_db/management/commands/load_ai_model_data.py +58 -26
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +174 -118
- endoreg_db/management/commands/load_center_data.py +46 -21
- endoreg_db/management/commands/{load_logging_data.py → load_contraindication_data.py} +4 -2
- endoreg_db/management/commands/load_disease_data.py +29 -7
- endoreg_db/management/commands/{load_endoscope_type_data.py → load_endoscope_data.py} +30 -7
- endoreg_db/management/commands/load_examination_indication_data.py +86 -0
- endoreg_db/management/commands/load_finding_data.py +128 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +0 -1
- endoreg_db/management/commands/load_information_source.py +13 -7
- endoreg_db/management/commands/load_lab_value_data.py +3 -3
- endoreg_db/management/commands/load_medication_data.py +83 -21
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/{load_medication_intake_time_data.py → load_organ_data.py} +7 -5
- endoreg_db/management/commands/load_qualification_data.py +59 -0
- endoreg_db/management/commands/load_requirement_data.py +180 -0
- endoreg_db/management/commands/load_risk_data.py +56 -0
- endoreg_db/management/commands/load_shift_data.py +60 -0
- endoreg_db/management/commands/load_tag_data.py +57 -0
- endoreg_db/management/commands/register_ai_model.py +1 -1
- endoreg_db/management/commands/setup_endoreg_db.py +381 -0
- endoreg_db/management/commands/start_filewatcher.py +106 -0
- endoreg_db/management/commands/storage_management.py +548 -0
- endoreg_db/management/commands/summarize_db_content.py +189 -0
- endoreg_db/management/commands/validate_video.py +204 -0
- endoreg_db/management/commands/validate_video_files.py +161 -0
- endoreg_db/management/commands/video_validation.py +22 -0
- endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
- endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
- endoreg_db/mermaid/binary_classification_annotation.md +50 -0
- endoreg_db/mermaid/classification.md +8 -0
- endoreg_db/mermaid/examination.md +8 -0
- endoreg_db/mermaid/findings.md +7 -0
- endoreg_db/mermaid/image_classification.md +28 -0
- endoreg_db/mermaid/interventions.md +8 -0
- endoreg_db/mermaid/morphology.md +8 -0
- endoreg_db/mermaid/patient_creation.md +14 -0
- endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
- endoreg_db/migrations/0001_initial.py +1234 -944
- endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
- endoreg_db/migrations/0003_add_center_display_name.py +30 -0
- endoreg_db/models/__init__.py +339 -53
- endoreg_db/models/administration/__init__.py +116 -0
- endoreg_db/models/administration/ai/__init__.py +9 -0
- endoreg_db/models/administration/ai/active_model.py +35 -0
- endoreg_db/models/administration/ai/ai_model.py +156 -0
- endoreg_db/models/{ai_model → administration/ai}/model_type.py +19 -4
- endoreg_db/models/administration/case/__init__.py +19 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/{case_template → administration/case/case_template}/__init__.py +10 -1
- endoreg_db/models/{case_template → administration/case/case_template}/case_template.py +60 -16
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule.py +6 -13
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule_value.py +21 -8
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_type.py +1 -3
- endoreg_db/models/{center → administration/center}/__init__.py +9 -0
- endoreg_db/models/administration/center/center.py +67 -0
- endoreg_db/models/administration/center/center_product.py +64 -0
- endoreg_db/models/administration/center/center_resource.py +49 -0
- endoreg_db/models/administration/center/center_shift.py +88 -0
- endoreg_db/models/administration/center/center_waste.py +30 -0
- endoreg_db/models/administration/permissions/__init__.py +44 -0
- endoreg_db/models/administration/person/__init__.py +24 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +35 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
- endoreg_db/models/administration/person/employee/employee_type.py +42 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +54 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/{persons → administration/person/names}/first_name.py +1 -1
- endoreg_db/models/{persons → administration/person/names}/last_name.py +2 -3
- endoreg_db/models/administration/person/patient/__init__.py +5 -0
- endoreg_db/models/administration/person/patient/patient.py +460 -0
- endoreg_db/models/administration/person/profession/__init__.py +24 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
- endoreg_db/models/administration/product/__init__.py +14 -0
- endoreg_db/models/administration/product/product.py +97 -0
- endoreg_db/models/administration/product/product_group.py +39 -0
- endoreg_db/models/administration/product/product_material.py +54 -0
- endoreg_db/models/{product → administration/product}/product_weight.py +21 -0
- endoreg_db/models/{product → administration/product}/reference_product.py +44 -13
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +37 -0
- endoreg_db/models/administration/qualification/qualification_type.py +35 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +69 -0
- endoreg_db/models/administration/shift/shift.py +51 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/label/__init__.py +24 -1
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +84 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
- endoreg_db/models/label/label.py +53 -54
- endoreg_db/models/label/label_set.py +53 -0
- endoreg_db/models/label/label_type.py +29 -0
- endoreg_db/models/label/label_video_segment/__init__.py +3 -0
- endoreg_db/models/label/label_video_segment/_create_from_video.py +41 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
- endoreg_db/models/label/video_segmentation_label.py +31 -0
- endoreg_db/models/label/video_segmentation_labelset.py +27 -0
- endoreg_db/models/media/__init__.py +16 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +111 -0
- endoreg_db/models/media/pdf/__init__.py +11 -0
- endoreg_db/models/media/pdf/raw_pdf.py +757 -0
- endoreg_db/models/media/pdf/report_file.py +162 -0
- endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +77 -0
- endoreg_db/models/media/video/__init__.py +8 -0
- endoreg_db/models/media/video/create_from_file.py +358 -0
- endoreg_db/models/media/video/pipe_1.py +213 -0
- endoreg_db/models/media/video/pipe_2.py +105 -0
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file.py +825 -0
- endoreg_db/models/media/video/video_file_ai.py +443 -0
- endoreg_db/models/media/video/video_file_anonymize.py +349 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -0
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +104 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +141 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/media/video/video_file_io.py +168 -0
- endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +45 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
- endoreg_db/models/media/video/video_file_segments.py +209 -0
- endoreg_db/models/media/video/video_metadata.py +65 -0
- endoreg_db/models/media/video/video_processing.py +152 -0
- endoreg_db/models/medical/__init__.py +146 -0
- endoreg_db/models/medical/contraindication/__init__.py +17 -0
- endoreg_db/models/medical/disease.py +156 -0
- endoreg_db/models/medical/event.py +137 -0
- endoreg_db/models/medical/examination/__init__.py +9 -0
- endoreg_db/models/medical/examination/examination.py +148 -0
- endoreg_db/models/medical/examination/examination_indication.py +278 -0
- endoreg_db/models/medical/examination/examination_time.py +49 -0
- endoreg_db/models/medical/examination/examination_time_type.py +41 -0
- endoreg_db/models/medical/examination/examination_type.py +48 -0
- endoreg_db/models/medical/finding/__init__.py +18 -0
- endoreg_db/models/medical/finding/finding.py +96 -0
- endoreg_db/models/medical/finding/finding_classification.py +142 -0
- endoreg_db/models/medical/finding/finding_intervention.py +52 -0
- endoreg_db/models/medical/finding/finding_type.py +35 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +65 -0
- endoreg_db/models/{hardware → medical/hardware}/endoscopy_processor.py +68 -29
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +419 -0
- endoreg_db/models/medical/medication/__init__.py +19 -0
- endoreg_db/models/medical/medication/medication.py +31 -0
- endoreg_db/models/medical/medication/medication_indication.py +50 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +39 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +44 -0
- endoreg_db/models/medical/medication/medication_schedule.py +45 -0
- endoreg_db/models/medical/organ/__init__.py +35 -0
- endoreg_db/models/medical/patient/__init__.py +56 -0
- endoreg_db/models/medical/patient/medication_examples.py +38 -0
- endoreg_db/models/medical/patient/patient_disease.py +63 -0
- endoreg_db/models/medical/patient/patient_event.py +75 -0
- endoreg_db/models/medical/patient/patient_examination.py +249 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +44 -0
- endoreg_db/models/medical/patient/patient_finding.py +357 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +40 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
- endoreg_db/models/{persons → medical}/patient/patient_lab_value.py +68 -22
- endoreg_db/models/medical/patient/patient_medication.py +104 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +72 -0
- endoreg_db/models/medical/risk/risk_type.py +51 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/metadata/model_meta.py +206 -0
- endoreg_db/models/metadata/model_meta_logic.py +343 -0
- endoreg_db/models/{data_file/metadata → metadata}/pdf_meta.py +32 -13
- endoreg_db/models/metadata/sensitive_meta.py +288 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +1048 -0
- endoreg_db/models/metadata/video_meta.py +332 -0
- endoreg_db/models/metadata/video_prediction_logic.py +190 -0
- endoreg_db/models/metadata/video_prediction_meta.py +270 -0
- endoreg_db/models/other/__init__.py +36 -1
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +125 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +94 -0
- endoreg_db/models/{persons → other}/gender.py +8 -3
- endoreg_db/models/other/information_source.py +159 -0
- endoreg_db/models/other/material.py +14 -2
- endoreg_db/models/other/resource.py +6 -2
- endoreg_db/models/other/tag.py +27 -0
- endoreg_db/models/other/transport_route.py +15 -3
- endoreg_db/models/{unit.py → other/unit.py} +16 -6
- endoreg_db/models/other/waste.py +10 -3
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +767 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +95 -0
- endoreg_db/models/requirement/requirement_operator.py +176 -0
- endoreg_db/models/requirement/requirement_set.py +287 -0
- endoreg_db/models/rule/__init__.py +13 -0
- endoreg_db/models/{rules → rule}/rule.py +6 -3
- endoreg_db/models/{rules → rule}/rule_attribute_dtype.py +0 -2
- endoreg_db/models/{rules → rule}/rule_type.py +0 -2
- endoreg_db/models/{rules → rule}/ruleset.py +0 -2
- endoreg_db/models/state/__init__.py +12 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/audit_ledger.py +150 -0
- endoreg_db/models/state/label_video_segment.py +22 -0
- endoreg_db/models/state/raw_pdf.py +187 -0
- endoreg_db/models/state/sensitive_meta.py +46 -0
- endoreg_db/models/state/video.py +232 -0
- endoreg_db/models/upload_job.py +99 -0
- endoreg_db/models/utils.py +135 -0
- endoreg_db/renames.yml +8 -0
- endoreg_db/root_urls.py +9 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +27 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
- endoreg_db/serializers/__init__.py +118 -10
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +223 -0
- endoreg_db/serializers/_old/raw_video_meta_validation.py +179 -0
- endoreg_db/serializers/_old/video.py +71 -0
- endoreg_db/serializers/administration/__init__.py +14 -0
- endoreg_db/serializers/administration/ai/__init__.py +10 -0
- endoreg_db/serializers/administration/ai/active_model.py +10 -0
- endoreg_db/serializers/administration/ai/ai_model.py +18 -0
- endoreg_db/serializers/administration/ai/model_type.py +10 -0
- endoreg_db/serializers/administration/center.py +9 -0
- endoreg_db/serializers/administration/gender.py +9 -0
- endoreg_db/serializers/anonymization.py +69 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +46 -0
- endoreg_db/serializers/examination/dropdown.py +21 -0
- endoreg_db/serializers/examination_serializer.py +12 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +54 -0
- endoreg_db/serializers/finding_classification/__init__.py +7 -0
- endoreg_db/serializers/finding_classification/choice.py +19 -0
- endoreg_db/serializers/finding_classification/classification.py +13 -0
- endoreg_db/serializers/label/__init__.py +7 -0
- endoreg_db/serializers/label/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/__init__.py +7 -0
- endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
- endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
- endoreg_db/serializers/meta/__init__.py +19 -0
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
- endoreg_db/serializers/meta/report_meta.py +53 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -0
- endoreg_db/serializers/meta/video_meta.py +39 -0
- endoreg_db/serializers/misc/__init__.py +14 -0
- endoreg_db/serializers/misc/file_overview.py +182 -0
- endoreg_db/serializers/misc/sensitive_patient_data.py +120 -0
- endoreg_db/serializers/misc/stats.py +33 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +71 -0
- endoreg_db/serializers/patient/__init__.py +11 -0
- endoreg_db/serializers/patient/patient.py +86 -0
- endoreg_db/serializers/patient/patient_dropdown.py +27 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
- endoreg_db/serializers/pdf/__init__.py +5 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
- endoreg_db/serializers/report/__init__.py +9 -0
- endoreg_db/serializers/report/mixins.py +45 -0
- endoreg_db/serializers/report/report.py +105 -0
- endoreg_db/serializers/report/report_list.py +22 -0
- endoreg_db/serializers/report/secure_file_url.py +26 -0
- endoreg_db/serializers/requirements/requirement_schema.py +25 -0
- endoreg_db/serializers/requirements/requirement_sets.py +29 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/segmentation.py +263 -0
- endoreg_db/serializers/video/video_file_brief.py +10 -0
- endoreg_db/serializers/video/video_file_detail.py +83 -0
- endoreg_db/serializers/video/video_file_list.py +67 -0
- endoreg_db/serializers/video/video_metadata.py +105 -0
- endoreg_db/serializers/video/video_processing_history.py +153 -0
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +223 -0
- endoreg_db/services/examination_evaluation.py +149 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +411 -0
- endoreg_db/services/lookup_store.py +266 -0
- endoreg_db/services/pdf_import.py +1382 -0
- endoreg_db/services/polling_coordinator.py +288 -0
- endoreg_db/services/pseudonym_service.py +89 -0
- endoreg_db/services/requirements_object.py +147 -0
- endoreg_db/services/segment_sync.py +155 -0
- endoreg_db/services/storage_aware_video_processor.py +344 -0
- endoreg_db/services/video_import.py +1259 -0
- endoreg_db/tasks/upload_tasks.py +207 -0
- endoreg_db/tasks/video_ingest.py +157 -0
- endoreg_db/tasks/video_processing_tasks.py +327 -0
- endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
- endoreg_db/templates/admin/start_examination.html +12 -0
- endoreg_db/templates/timeline.html +176 -0
- endoreg_db/urls/__init__.py +83 -0
- endoreg_db/urls/anonymization.py +32 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +39 -0
- endoreg_db/urls/examination.py +54 -0
- endoreg_db/urls/files.py +6 -0
- endoreg_db/urls/label_video_segment_validate.py +33 -0
- endoreg_db/urls/label_video_segments.py +46 -0
- endoreg_db/urls/media.py +227 -0
- endoreg_db/urls/patient.py +19 -0
- endoreg_db/urls/report.py +48 -0
- endoreg_db/urls/requirements.py +13 -0
- endoreg_db/urls/sensitive_meta.py +0 -0
- endoreg_db/urls/stats.py +46 -0
- endoreg_db/urls/upload.py +20 -0
- endoreg_db/urls/video.py +61 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +88 -1
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/{models/ai_model/utils.py → utils/ai/get.py} +1 -4
- endoreg_db/utils/ai/inference_dataset.py +52 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +159 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +291 -0
- endoreg_db/utils/ai/preprocess.py +68 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +0 -0
- endoreg_db/utils/case_generator/case_generator.py +159 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/utils/case_generator/utils.py +30 -0
- endoreg_db/utils/check_video_files.py +148 -0
- endoreg_db/utils/dataloader.py +118 -35
- endoreg_db/utils/dates.py +60 -0
- endoreg_db/utils/env.py +33 -0
- endoreg_db/utils/extract_specific_frames.py +72 -0
- endoreg_db/utils/file_operations.py +29 -1
- endoreg_db/utils/fix_video_path_direct.py +141 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +123 -4
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +193 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +76 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/paths.py +95 -0
- endoreg_db/utils/permissions.py +143 -0
- endoreg_db/utils/pipelines/Readme.md +235 -0
- endoreg_db/utils/pipelines/__init__.py +0 -0
- endoreg_db/utils/pipelines/process_video_dir.py +120 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +20 -0
- endoreg_db/utils/product/sum_weights.py +18 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/requirement_helpers.py +0 -0
- endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
- endoreg_db/utils/requirement_operator_logic/lab_value_operators.py +578 -0
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/utils/translation.py +27 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/validate_video_detailed.py +357 -0
- endoreg_db/utils/video/__init__.py +26 -0
- endoreg_db/utils/video/extract_frames.py +88 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +835 -0
- endoreg_db/utils/video/names.py +42 -0
- endoreg_db/utils/video/streaming_processor.py +312 -0
- endoreg_db/utils/video/video_splitter.py +94 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
- endoreg_db/views/__init__.py +274 -0
- endoreg_db/views/anonymization/__init__.py +27 -0
- endoreg_db/views/anonymization/media_management.py +454 -0
- endoreg_db/views/anonymization/overview.py +216 -0
- endoreg_db/views/anonymization/validate.py +107 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +113 -0
- endoreg_db/views/examination/__init__.py +33 -0
- endoreg_db/views/examination/examination.py +37 -0
- endoreg_db/views/examination/examination_manifest_cache.py +26 -0
- endoreg_db/views/examination/get_finding_classification_choices.py +59 -0
- endoreg_db/views/examination/get_finding_classifications.py +36 -0
- endoreg_db/views/examination/get_findings.py +41 -0
- endoreg_db/views/examination/get_instruments.py +18 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +112 -0
- endoreg_db/views/finding/get_classifications.py +14 -0
- endoreg_db/views/finding/get_interventions.py +17 -0
- endoreg_db/views/finding_classification/__init__.py +13 -0
- endoreg_db/views/finding_classification/base.py +0 -0
- endoreg_db/views/finding_classification/finding_classification.py +42 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
- endoreg_db/views/label/__init__.py +5 -0
- endoreg_db/views/label/label.py +15 -0
- endoreg_db/views/label_video_segment/__init__.py +16 -0
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
- endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
- endoreg_db/views/label_video_segment/validate.py +226 -0
- endoreg_db/views/media/__init__.py +45 -0
- endoreg_db/views/media/pdf_media.py +388 -0
- endoreg_db/views/media/segments.py +71 -0
- endoreg_db/views/media/sensitive_metadata.py +314 -0
- endoreg_db/views/media/video_media.py +272 -0
- endoreg_db/views/media/video_segments.py +524 -0
- endoreg_db/views/meta/__init__.py +15 -0
- endoreg_db/views/meta/available_files_list.py +146 -0
- endoreg_db/views/meta/report_meta.py +53 -0
- endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
- endoreg_db/views/meta/sensitive_meta_list.py +104 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
- endoreg_db/views/misc/__init__.py +63 -0
- endoreg_db/views/misc/center.py +13 -0
- endoreg_db/views/misc/csrf.py +7 -0
- endoreg_db/views/misc/gender.py +14 -0
- endoreg_db/views/misc/secure_file_serving_view.py +80 -0
- endoreg_db/views/misc/secure_file_url_view.py +84 -0
- endoreg_db/views/misc/secure_url_validate.py +79 -0
- endoreg_db/views/misc/stats.py +220 -0
- endoreg_db/views/misc/translation.py +182 -0
- endoreg_db/views/misc/upload_views.py +240 -0
- endoreg_db/views/patient/__init__.py +5 -0
- endoreg_db/views/patient/patient.py +210 -0
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +140 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
- endoreg_db/views/patient_examination/video.py +194 -0
- endoreg_db/views/patient_finding/__init__.py +7 -0
- endoreg_db/views/patient_finding/base.py +0 -0
- endoreg_db/views/patient_finding/patient_finding.py +64 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
- endoreg_db/views/patient_finding_location/__init__.py +5 -0
- endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
- endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
- endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
- endoreg_db/views/pdf/__init__.py +8 -0
- endoreg_db/views/pdf/pdf_stream.py +187 -0
- endoreg_db/views/pdf/reimport.py +177 -0
- endoreg_db/views/report/__init__.py +9 -0
- endoreg_db/views/report/report_list.py +112 -0
- endoreg_db/views/report/report_with_secure_url.py +28 -0
- endoreg_db/views/report/start_examination.py +7 -0
- endoreg_db/views/requirement/__init__.py +10 -0
- endoreg_db/views/requirement/evaluate.py +279 -0
- endoreg_db/views/requirement/lookup.py +367 -0
- endoreg_db/views/requirement/lookup_store.py +252 -0
- endoreg_db/views/requirement_lookup/lookup.py +0 -0
- endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
- endoreg_db/views/stats/__init__.py +13 -0
- endoreg_db/views/stats/stats_views.py +229 -0
- endoreg_db/views/video/__init__.py +59 -0
- endoreg_db/views/video/correction.py +530 -0
- endoreg_db/views/video/reimport.py +195 -0
- endoreg_db/views/video/segmentation.py +274 -0
- endoreg_db/views/video/task_status.py +49 -0
- endoreg_db/views/video/timeline.py +46 -0
- endoreg_db/views/video/video_analyze.py +52 -0
- endoreg_db/views/video/video_apply_mask.py +48 -0
- endoreg_db/views/video/video_correction.py +21 -0
- endoreg_db/views/video/video_download_processed.py +58 -0
- endoreg_db/views/video/video_examination_viewset.py +242 -0
- endoreg_db/views/video/video_meta.py +29 -0
- endoreg_db/views/video/video_processing_history.py +24 -0
- endoreg_db/views/video/video_remove_frames.py +48 -0
- endoreg_db/views/video/video_stream.py +306 -0
- endoreg_db/views.py +0 -3
- endoreg_db-0.8.6.3.dist-info/METADATA +383 -0
- endoreg_db-0.8.6.3.dist-info/RECORD +793 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info}/WHEEL +1 -1
- endoreg_db/data/active_model/data.yaml +0 -3
- endoreg_db/data/agl_service/data.yaml +0 -19
- endoreg_db/data/label/label-set/data.yaml +0 -18
- endoreg_db/management/commands/_load_model_template.py +0 -41
- endoreg_db/management/commands/delete_all.py +0 -18
- endoreg_db/management/commands/delete_legacy_images.py +0 -19
- endoreg_db/management/commands/delete_legacy_videos.py +0 -17
- endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +0 -32
- endoreg_db/management/commands/fix_auth_permission.py +0 -20
- endoreg_db/management/commands/import_legacy_images.py +0 -94
- endoreg_db/management/commands/import_legacy_videos.py +0 -76
- endoreg_db/management/commands/load_active_model_data.py +0 -45
- endoreg_db/management/commands/load_endoscopy_processor_data.py +0 -45
- endoreg_db/management/commands/load_g_play_data.py +0 -113
- endoreg_db/management/commands/load_label_data.py +0 -67
- endoreg_db/management/commands/load_medication_indication_data.py +0 -63
- endoreg_db/management/commands/load_medication_indication_type_data.py +0 -41
- endoreg_db/management/commands/load_medication_schedule_data.py +0 -55
- endoreg_db/management/commands/load_network_data.py +0 -57
- endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
- endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
- endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
- endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
- endoreg_db/models/ai_model/__init__.py +0 -3
- endoreg_db/models/ai_model/active_model.py +0 -9
- endoreg_db/models/ai_model/model_meta.py +0 -24
- endoreg_db/models/annotation/__init__.py +0 -3
- endoreg_db/models/annotation/anonymized_image_annotation.py +0 -60
- endoreg_db/models/annotation/binary_classification_annotation_task.py +0 -80
- endoreg_db/models/annotation/image_classification.py +0 -27
- endoreg_db/models/center/center.py +0 -25
- endoreg_db/models/center/center_product.py +0 -34
- endoreg_db/models/center/center_resource.py +0 -19
- endoreg_db/models/center/center_waste.py +0 -11
- endoreg_db/models/data_file/__init__.py +0 -6
- endoreg_db/models/data_file/base_classes/__init__.py +0 -2
- endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -51
- endoreg_db/models/data_file/base_classes/abstract_video.py +0 -201
- endoreg_db/models/data_file/frame.py +0 -45
- endoreg_db/models/data_file/import_classes/__init__.py +0 -32
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +0 -35
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +0 -28
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +0 -260
- endoreg_db/models/data_file/import_classes/raw_pdf.py +0 -188
- endoreg_db/models/data_file/import_classes/raw_video.py +0 -343
- endoreg_db/models/data_file/metadata/__init__.py +0 -3
- endoreg_db/models/data_file/metadata/sensitive_meta.py +0 -31
- endoreg_db/models/data_file/metadata/video_meta.py +0 -133
- endoreg_db/models/data_file/report_file.py +0 -89
- endoreg_db/models/data_file/video/__init__.py +0 -7
- endoreg_db/models/data_file/video/import_meta.py +0 -25
- endoreg_db/models/data_file/video/video.py +0 -25
- endoreg_db/models/data_file/video_segment.py +0 -107
- endoreg_db/models/disease.py +0 -56
- endoreg_db/models/emission/__init__.py +0 -1
- endoreg_db/models/emission/emission_factor.py +0 -20
- endoreg_db/models/event.py +0 -22
- endoreg_db/models/examination/__init__.py +0 -4
- endoreg_db/models/examination/examination.py +0 -26
- endoreg_db/models/examination/examination_time.py +0 -27
- endoreg_db/models/examination/examination_time_type.py +0 -24
- endoreg_db/models/examination/examination_type.py +0 -18
- endoreg_db/models/hardware/__init__.py +0 -2
- endoreg_db/models/hardware/endoscope.py +0 -44
- endoreg_db/models/information_source.py +0 -29
- endoreg_db/models/laboratory/__init__.py +0 -1
- endoreg_db/models/laboratory/lab_value.py +0 -102
- endoreg_db/models/legacy_data/__init__.py +0 -3
- endoreg_db/models/legacy_data/image.py +0 -34
- endoreg_db/models/logging/__init__.py +0 -4
- endoreg_db/models/logging/agl_service.py +0 -19
- endoreg_db/models/logging/base.py +0 -22
- endoreg_db/models/logging/log_type.py +0 -23
- endoreg_db/models/logging/network_device.py +0 -24
- endoreg_db/models/medication/__init__.py +0 -1
- endoreg_db/models/medication/medication.py +0 -148
- endoreg_db/models/network/__init__.py +0 -3
- endoreg_db/models/network/agl_service.py +0 -38
- endoreg_db/models/network/network_device.py +0 -53
- endoreg_db/models/network/network_device_type.py +0 -23
- endoreg_db/models/other/distribution.py +0 -215
- endoreg_db/models/patient_examination/__init__.py +0 -35
- endoreg_db/models/permissions/__init__.py +0 -44
- endoreg_db/models/persons/__init__.py +0 -7
- endoreg_db/models/persons/examiner/__init__.py +0 -2
- endoreg_db/models/persons/examiner/examiner.py +0 -16
- endoreg_db/models/persons/examiner/examiner_type.py +0 -2
- endoreg_db/models/persons/patient/__init__.py +0 -8
- endoreg_db/models/persons/patient/case/case.py +0 -30
- endoreg_db/models/persons/patient/patient.py +0 -216
- endoreg_db/models/persons/patient/patient_disease.py +0 -16
- endoreg_db/models/persons/patient/patient_event.py +0 -22
- endoreg_db/models/persons/patient/patient_lab_sample.py +0 -106
- endoreg_db/models/persons/patient/patient_medication.py +0 -44
- endoreg_db/models/persons/patient/patient_medication_schedule.py +0 -28
- endoreg_db/models/persons/portal_user_information.py +0 -27
- endoreg_db/models/prediction/__init__.py +0 -2
- endoreg_db/models/prediction/image_classification.py +0 -37
- endoreg_db/models/prediction/video_prediction_meta.py +0 -244
- endoreg_db/models/product/__init__.py +0 -5
- endoreg_db/models/product/product.py +0 -97
- endoreg_db/models/product/product_group.py +0 -19
- endoreg_db/models/product/product_material.py +0 -24
- endoreg_db/models/questionnaires/__init__.py +0 -114
- endoreg_db/models/quiz/__init__.py +0 -2
- endoreg_db/models/quiz/quiz_answer.py +0 -41
- endoreg_db/models/quiz/quiz_question.py +0 -54
- endoreg_db/models/report_reader/__init__.py +0 -2
- endoreg_db/models/report_reader/report_reader_config.py +0 -53
- endoreg_db/models/rules/__init__.py +0 -5
- endoreg_db/queries/get/__init__.py +0 -6
- endoreg_db/queries/get/center.py +0 -42
- endoreg_db/queries/get/model.py +0 -13
- endoreg_db/queries/get/patient.py +0 -14
- endoreg_db/queries/get/patient_examination.py +0 -20
- endoreg_db/queries/get/report_file.py +0 -33
- endoreg_db/queries/get/video.py +0 -31
- endoreg_db/serializers/ai_model.py +0 -19
- endoreg_db/serializers/annotation.py +0 -17
- endoreg_db/serializers/center.py +0 -11
- endoreg_db/serializers/examination.py +0 -33
- endoreg_db/serializers/frame.py +0 -13
- endoreg_db/serializers/hardware.py +0 -21
- endoreg_db/serializers/label.py +0 -22
- endoreg_db/serializers/patient.py +0 -10
- endoreg_db/serializers/prediction.py +0 -15
- endoreg_db/serializers/report_file.py +0 -7
- endoreg_db/serializers/video.py +0 -27
- endoreg_db/tests.py +0 -3
- endoreg_db/utils/legacy_ocr.py +0 -201
- endoreg_db/utils/video_metadata.py +0 -87
- endoreg_db-0.4.5.dist-info/METADATA +0 -34
- endoreg_db-0.4.5.dist-info/RECORD +0 -316
- /endoreg_db/{data/distribution/numeric/.init → api/serializers/finding_descriptions.py} +0 -0
- /endoreg_db/{models/persons/patient/case/__init__.py → api/views/finding_descriptions.py} +0 -0
- /endoreg_db/{queries/get/annotation.py → config/__init__.py} +0 -0
- /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
- /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
- /endoreg_db/{queries/get/prediction.py → data/shift/m2.yaml} +0 -0
- /endoreg_db/{queries/get/video_import_meta.py → factories/__init__.py} +0 -0
- /endoreg_db/{queries/get/video_prediction_meta.py → helpers/__init__.py} +0 -0
- /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
- /endoreg_db/models/{persons → administration/person}/person.py +0 -0
- /endoreg_db/models/{report_reader → media/pdf/report_reader}/report_reader_flag.py +0 -0
- /endoreg_db/models/{rules → rule}/rule_applicator.py +0 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
import warnings
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models.other.unit import Unit
|
|
7
|
+
from ...other.distribution import (
|
|
8
|
+
SingleCategoricalValueDistribution,
|
|
9
|
+
NumericValueDistribution,
|
|
10
|
+
MultipleCategoricalValueDistribution,
|
|
11
|
+
DateValueDistribution,
|
|
12
|
+
)
|
|
13
|
+
from ...administration.person.patient import Patient # Added Patient for type hinting
|
|
14
|
+
|
|
15
|
+
LANG = "de"
|
|
16
|
+
|
|
17
|
+
from pydantic import BaseModel, ConfigDict
|
|
18
|
+
|
|
19
|
+
class CommonLabValues(BaseModel):
|
|
20
|
+
"""
|
|
21
|
+
A Pydantic model representing a lookup for common lab values.
|
|
22
|
+
It is used to provide a structured way to access common lab values like
|
|
23
|
+
hemoglobin, creatinine, and others
|
|
24
|
+
"""
|
|
25
|
+
hb: "LabValue"
|
|
26
|
+
wbc: "LabValue"
|
|
27
|
+
plt: "LabValue"
|
|
28
|
+
cr: "LabValue"
|
|
29
|
+
na: "LabValue"
|
|
30
|
+
k: "LabValue"
|
|
31
|
+
glc: "LabValue"
|
|
32
|
+
inr: "LabValue"
|
|
33
|
+
crp: "LabValue"
|
|
34
|
+
|
|
35
|
+
model_config = ConfigDict(
|
|
36
|
+
from_attributes = True,
|
|
37
|
+
arbitrary_types_allowed = True
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
class LabValueManager(models.Manager):
|
|
41
|
+
def get_by_natural_key(self, name):
|
|
42
|
+
"""
|
|
43
|
+
Retrieves a LabValue instance by its unique name.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
name: The unique name of the LabValue.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
The LabValue instance with the specified name.
|
|
50
|
+
"""
|
|
51
|
+
return self.get(name=name)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class LabValue(models.Model):
|
|
55
|
+
name = models.CharField(max_length=255, unique=True)
|
|
56
|
+
abbreviation = models.CharField(max_length=10, blank=True, null=True)
|
|
57
|
+
default_unit = models.ForeignKey(
|
|
58
|
+
"Unit", on_delete=models.CASCADE, blank=True, null=True
|
|
59
|
+
)
|
|
60
|
+
numeric_precision = models.IntegerField(default=3)
|
|
61
|
+
default_single_categorical_value_distribution = models.ForeignKey(
|
|
62
|
+
"SingleCategoricalValueDistribution",
|
|
63
|
+
on_delete=models.CASCADE,
|
|
64
|
+
blank=True,
|
|
65
|
+
null=True,
|
|
66
|
+
related_name="default_single_categorical_value_distribution",
|
|
67
|
+
)
|
|
68
|
+
default_numerical_value_distribution = models.ForeignKey(
|
|
69
|
+
"NumericValueDistribution",
|
|
70
|
+
on_delete=models.CASCADE,
|
|
71
|
+
blank=True,
|
|
72
|
+
null=True,
|
|
73
|
+
related_name="default_numerical_value_distribution",
|
|
74
|
+
)
|
|
75
|
+
default_multiple_categorical_value_distribution = models.ForeignKey(
|
|
76
|
+
"MultipleCategoricalValueDistribution",
|
|
77
|
+
on_delete=models.CASCADE,
|
|
78
|
+
blank=True,
|
|
79
|
+
null=True,
|
|
80
|
+
related_name="default_multiple_categorical_value_distribution",
|
|
81
|
+
)
|
|
82
|
+
default_date_value_distribution = models.ForeignKey(
|
|
83
|
+
"DateValueDistribution",
|
|
84
|
+
on_delete=models.CASCADE,
|
|
85
|
+
blank=True,
|
|
86
|
+
null=True,
|
|
87
|
+
related_name="default_date_value_distribution",
|
|
88
|
+
)
|
|
89
|
+
default_normal_range = models.JSONField(blank=True, null=True)
|
|
90
|
+
normal_range_age_dependent = models.BooleanField(default=False)
|
|
91
|
+
normal_range_gender_dependent = models.BooleanField(default=False)
|
|
92
|
+
normal_range_special_case = models.BooleanField(default=False)
|
|
93
|
+
bound_adjustment_factor = models.FloatField(
|
|
94
|
+
default=0.1,
|
|
95
|
+
help_text="Factor for adjusting bounds when generating increased/decreased values, e.g., 0.1 for 10%."
|
|
96
|
+
)
|
|
97
|
+
objects = LabValueManager()
|
|
98
|
+
|
|
99
|
+
if TYPE_CHECKING:
|
|
100
|
+
default_unit: "Unit"
|
|
101
|
+
default_single_categorical_value_distribution: "SingleCategoricalValueDistribution"
|
|
102
|
+
default_numerical_value_distribution: "NumericValueDistribution"
|
|
103
|
+
default_multiple_categorical_value_distribution: "MultipleCategoricalValueDistribution"
|
|
104
|
+
default_date_value_distribution: "DateValueDistribution"
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def get_common_lab_values(cls):
|
|
108
|
+
"""
|
|
109
|
+
Retrieves a structured set of common laboratory values as a CommonLabValues instance.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
A CommonLabValues Pydantic model populated with LabValue objects for hemoglobin, white blood cells, platelets, creatinine, sodium, potassium, glucose, international normalized ratio, and C-reactive protein.
|
|
113
|
+
"""
|
|
114
|
+
from endoreg_db.models.medical.laboratory.lab_value import CommonLabValues
|
|
115
|
+
|
|
116
|
+
return CommonLabValues(
|
|
117
|
+
hb=cls.objects.get(name="hemoglobin"),
|
|
118
|
+
wbc=cls.objects.get(name="white_blood_cells"),
|
|
119
|
+
plt=cls.objects.get(name="platelets"),
|
|
120
|
+
cr=cls.objects.get(name="creatinine"),
|
|
121
|
+
na=cls.objects.get(name="sodium"),
|
|
122
|
+
k=cls.objects.get(name="potassium"),
|
|
123
|
+
glc=cls.objects.get(name="glucose"),
|
|
124
|
+
inr=cls.objects.get(name="international_normalized_ratio"),
|
|
125
|
+
crp=cls.objects.get(name="c_reactive_protein")
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def natural_key(self):
|
|
130
|
+
"""Returns a tuple containing the unique name of this lab value instance."""
|
|
131
|
+
return (self.name,)
|
|
132
|
+
|
|
133
|
+
def __str__(self):
|
|
134
|
+
"""
|
|
135
|
+
Return the lab value name as a string.
|
|
136
|
+
|
|
137
|
+
Converts the lab value's `name` attribute into its string representation for
|
|
138
|
+
display purposes.
|
|
139
|
+
"""
|
|
140
|
+
return str(self.name)
|
|
141
|
+
|
|
142
|
+
def get_default_default_distribution(self):
|
|
143
|
+
"""
|
|
144
|
+
Returns the first available default distribution for the lab value.
|
|
145
|
+
|
|
146
|
+
Checks the default distribution fields in the following order:
|
|
147
|
+
default_single_categorical_value_distribution, default_numerical_value_distribution,
|
|
148
|
+
default_multiple_categorical_value_distribution, and default_date_value_distribution.
|
|
149
|
+
If none are set, a warning is issued and None is returned.
|
|
150
|
+
"""
|
|
151
|
+
if self.default_single_categorical_value_distribution:
|
|
152
|
+
return self.default_single_categorical_value_distribution
|
|
153
|
+
elif self.default_numerical_value_distribution:
|
|
154
|
+
return self.default_numerical_value_distribution
|
|
155
|
+
elif self.default_multiple_categorical_value_distribution:
|
|
156
|
+
return self.default_multiple_categorical_value_distribution
|
|
157
|
+
elif self.default_date_value_distribution:
|
|
158
|
+
return self.default_date_value_distribution
|
|
159
|
+
else:
|
|
160
|
+
warnings.warn("No default distribution set for lab value")
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
def get_normal_range(self, age: int = None, gender=None):
|
|
164
|
+
"""
|
|
165
|
+
Returns the normal range for this lab value, considering age and gender dependencies.
|
|
166
|
+
|
|
167
|
+
If the normal range is gender-dependent, attempts to use the provided gender; defaults to "male" if gender is missing or unknown. Falls back to general min/max values if gender-specific data is unavailable. Issues warnings for unimplemented age-dependent or special case ranges, and when min or max values cannot be determined. Returns a dictionary with keys "min" and "max", which may be None if the range is not defined.
|
|
168
|
+
"""
|
|
169
|
+
from ...other.gender import Gender
|
|
170
|
+
|
|
171
|
+
assert isinstance(age, int) or age is None
|
|
172
|
+
assert isinstance(gender, Gender) or gender is None
|
|
173
|
+
|
|
174
|
+
age_dependent = self.normal_range_age_dependent
|
|
175
|
+
gender_dependent = self.normal_range_gender_dependent
|
|
176
|
+
special_case = self.normal_range_special_case
|
|
177
|
+
|
|
178
|
+
min_value = None
|
|
179
|
+
max_value = None
|
|
180
|
+
current_range_source = self.default_normal_range or {}
|
|
181
|
+
|
|
182
|
+
gender_name_to_use = None
|
|
183
|
+
if gender_dependent:
|
|
184
|
+
if gender and hasattr(gender, 'name') and gender.name:
|
|
185
|
+
gender_name_to_use = gender.name
|
|
186
|
+
if gender_name_to_use not in current_range_source:
|
|
187
|
+
warnings.warn(
|
|
188
|
+
f"Normal range for gender '{gender_name_to_use}' not found for LabValue '{self.name}'. "
|
|
189
|
+
f"Defaulting to 'male' range.",
|
|
190
|
+
UserWarning
|
|
191
|
+
)
|
|
192
|
+
gender_name_to_use = "male"
|
|
193
|
+
else:
|
|
194
|
+
warnings.warn(
|
|
195
|
+
f"Gender not provided for gender-dependent LabValue '{self.name}'. Defaulting to 'male' range.",
|
|
196
|
+
UserWarning
|
|
197
|
+
)
|
|
198
|
+
gender_name_to_use = "male"
|
|
199
|
+
|
|
200
|
+
# Attempt gender-specific lookup
|
|
201
|
+
gender_specific_data = current_range_source.get(gender_name_to_use)
|
|
202
|
+
if isinstance(gender_specific_data, dict):
|
|
203
|
+
min_value = gender_specific_data.get("min")
|
|
204
|
+
max_value = gender_specific_data.get("max")
|
|
205
|
+
else:
|
|
206
|
+
warnings.warn(
|
|
207
|
+
f"No gender-specific data found for '{gender_name_to_use}' in LabValue '{self.name}'. "
|
|
208
|
+
f"Falling back to general range if available.",
|
|
209
|
+
UserWarning
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Fallback to general min/max if needed
|
|
213
|
+
if (min_value is None or max_value is None) and isinstance(current_range_source, dict):
|
|
214
|
+
if min_value is None:
|
|
215
|
+
min_value = current_range_source.get("min")
|
|
216
|
+
if max_value is None:
|
|
217
|
+
max_value = current_range_source.get("max")
|
|
218
|
+
|
|
219
|
+
if age_dependent:
|
|
220
|
+
warnings.warn(f"Age dependent normal range not implemented yet for LabValue '{self.name}'. Age: {age}.")
|
|
221
|
+
|
|
222
|
+
if special_case:
|
|
223
|
+
warnings.warn(f"Special case normal range not implemented yet for LabValue '{self.name}'.")
|
|
224
|
+
|
|
225
|
+
# Final contextual warning
|
|
226
|
+
if min_value is None and max_value is None:
|
|
227
|
+
# Do not warn here; let get_normal_value handle the warning for missing range
|
|
228
|
+
return {"min": min_value, "max": max_value}
|
|
229
|
+
if min_value is None:
|
|
230
|
+
context_parts = []
|
|
231
|
+
if gender_dependent:
|
|
232
|
+
gender_repr = (gender.name if gender and hasattr(gender, 'name') else 'None')
|
|
233
|
+
if gender_name_to_use and gender_name_to_use != gender_repr:
|
|
234
|
+
gender_repr = f"{gender_repr} (lookup attempted for: {gender_name_to_use})"
|
|
235
|
+
context_parts.append(f"gender: {gender_repr}")
|
|
236
|
+
if age_dependent:
|
|
237
|
+
context_parts.append(f"age: {age}")
|
|
238
|
+
|
|
239
|
+
warning_message = (
|
|
240
|
+
f"Could not determine a 'min' normal range for LabValue '{self.name}'"
|
|
241
|
+
)
|
|
242
|
+
if context_parts:
|
|
243
|
+
warning_message += f" with context ({', '.join(context_parts)})."
|
|
244
|
+
else:
|
|
245
|
+
warning_message += " (general context)."
|
|
246
|
+
warning_message += " Check LabValue's default_normal_range definition."
|
|
247
|
+
warnings.warn(warning_message, UserWarning)
|
|
248
|
+
|
|
249
|
+
return {"min": min_value, "max": max_value}
|
|
250
|
+
|
|
251
|
+
def get_increased_value(self, patient: "Patient" = None):
|
|
252
|
+
"""
|
|
253
|
+
Returns a value that is considered increased for this lab value.
|
|
254
|
+
It prioritizes sampling from a numerical distribution if available,
|
|
255
|
+
otherwise uses the upper bound of the normal range.
|
|
256
|
+
"""
|
|
257
|
+
_age = patient.age() if patient else None
|
|
258
|
+
_gender = patient.gender if patient else None
|
|
259
|
+
normal_range = self.get_normal_range(age=_age, gender=_gender)
|
|
260
|
+
upper_bound = normal_range.get("max")
|
|
261
|
+
|
|
262
|
+
if self.default_numerical_value_distribution:
|
|
263
|
+
if patient:
|
|
264
|
+
# Attempt to sample above the upper bound, or a high value if no bound
|
|
265
|
+
for _ in range(10): # Try a few times to get a value if bounds are restrictive
|
|
266
|
+
generated_value = self.default_numerical_value_distribution.generate_value(
|
|
267
|
+
lab_value=self, patient=patient
|
|
268
|
+
)
|
|
269
|
+
if upper_bound is not None:
|
|
270
|
+
if generated_value > upper_bound:
|
|
271
|
+
return generated_value
|
|
272
|
+
# Heuristic for "high" if no upper_bound, compare against mean + stddev
|
|
273
|
+
elif hasattr(self.default_numerical_value_distribution, "mean") and \
|
|
274
|
+
hasattr(self.default_numerical_value_distribution, "stddev") and \
|
|
275
|
+
self.default_numerical_value_distribution.mean is not None and \
|
|
276
|
+
self.default_numerical_value_distribution.stddev is not None and \
|
|
277
|
+
generated_value > (
|
|
278
|
+
self.default_numerical_value_distribution.mean + self.default_numerical_value_distribution.stddev
|
|
279
|
+
):
|
|
280
|
+
return generated_value
|
|
281
|
+
# Fallback if sampling fails to produce a clearly increased value
|
|
282
|
+
if upper_bound is not None:
|
|
283
|
+
return upper_bound + (abs(upper_bound * self.bound_adjustment_factor) if upper_bound != 0 else 1) # Increase by factor or 1
|
|
284
|
+
# If no upper bound and sampling didn't provide a clear high value, return a generated value as last resort
|
|
285
|
+
return self.default_numerical_value_distribution.generate_value(lab_value=self, patient=patient)
|
|
286
|
+
else: # No patient, cannot use distribution
|
|
287
|
+
warnings.warn(
|
|
288
|
+
f"Cannot use numerical distribution for {self.name} without patient context. Falling back to normal range logic for increased value."
|
|
289
|
+
)
|
|
290
|
+
if upper_bound is not None:
|
|
291
|
+
return upper_bound + (abs(upper_bound * self.bound_adjustment_factor) if upper_bound != 0 else 1)
|
|
292
|
+
else:
|
|
293
|
+
warnings.warn(
|
|
294
|
+
f"Cannot determine an increased value for {self.name} without an upper normal range or patient context for distribution."
|
|
295
|
+
)
|
|
296
|
+
return None
|
|
297
|
+
|
|
298
|
+
elif upper_bound is not None:
|
|
299
|
+
return upper_bound + (abs(upper_bound * self.bound_adjustment_factor) if upper_bound != 0 else 1)
|
|
300
|
+
else:
|
|
301
|
+
warnings.warn(
|
|
302
|
+
f"Cannot determine an increased value for {self.name} without a numerical distribution or an upper normal range."
|
|
303
|
+
)
|
|
304
|
+
return None
|
|
305
|
+
|
|
306
|
+
def get_normal_value(self, patient: "Patient" = None):
|
|
307
|
+
"""
|
|
308
|
+
Returns a value considered normal for this lab value.
|
|
309
|
+
|
|
310
|
+
If a numerical distribution and patient context are available, attempts to generate a value within the normal range. Falls back to the midpoint of the normal range or to available bounds if sampling fails or context is insufficient. Returns None if neither a normal range nor a distribution is available.
|
|
311
|
+
"""
|
|
312
|
+
_age = patient.age() if patient else None
|
|
313
|
+
_gender = patient.gender if patient else None
|
|
314
|
+
normal_range = self.get_normal_range(age=_age, gender=_gender)
|
|
315
|
+
lower_bound = normal_range.get("min")
|
|
316
|
+
upper_bound = normal_range.get("max")
|
|
317
|
+
|
|
318
|
+
if self.default_numerical_value_distribution:
|
|
319
|
+
if patient:
|
|
320
|
+
for _ in range(10): # Try a few times
|
|
321
|
+
generated_value = self.default_numerical_value_distribution.generate_value(
|
|
322
|
+
lab_value=self, patient=patient
|
|
323
|
+
)
|
|
324
|
+
if lower_bound is not None and upper_bound is not None:
|
|
325
|
+
if lower_bound <= generated_value <= upper_bound:
|
|
326
|
+
return generated_value
|
|
327
|
+
elif lower_bound is not None and generated_value >= lower_bound: # No upper bound
|
|
328
|
+
return generated_value
|
|
329
|
+
elif upper_bound is not None and generated_value <= upper_bound: # No lower bound
|
|
330
|
+
return generated_value
|
|
331
|
+
elif lower_bound is None and upper_bound is None: # No range defined
|
|
332
|
+
return generated_value
|
|
333
|
+
# Fallback if sampling fails to produce a value in range
|
|
334
|
+
if lower_bound is not None and upper_bound is not None:
|
|
335
|
+
return (lower_bound + upper_bound) / 2.0
|
|
336
|
+
# Return any generated value as last resort
|
|
337
|
+
return self.default_numerical_value_distribution.generate_value(lab_value=self, patient=patient)
|
|
338
|
+
else: # No patient, cannot use distribution
|
|
339
|
+
warnings.warn(
|
|
340
|
+
f"Cannot use numerical distribution for {self.name} without patient context. Falling back to normal range logic for normal value."
|
|
341
|
+
)
|
|
342
|
+
if lower_bound is not None and upper_bound is not None:
|
|
343
|
+
return (lower_bound + upper_bound) / 2.0
|
|
344
|
+
elif lower_bound is not None:
|
|
345
|
+
return lower_bound
|
|
346
|
+
elif upper_bound is not None:
|
|
347
|
+
return upper_bound
|
|
348
|
+
else:
|
|
349
|
+
warnings.warn(
|
|
350
|
+
f"Cannot determine a normal value for {self.name} without a normal range or patient context for distribution.",
|
|
351
|
+
UserWarning
|
|
352
|
+
)
|
|
353
|
+
return None
|
|
354
|
+
|
|
355
|
+
elif lower_bound is not None and upper_bound is not None:
|
|
356
|
+
return (lower_bound + upper_bound) / 2.0
|
|
357
|
+
elif lower_bound is not None: # Only min is defined
|
|
358
|
+
return lower_bound
|
|
359
|
+
elif upper_bound is not None: # Only max is defined
|
|
360
|
+
return upper_bound
|
|
361
|
+
else:
|
|
362
|
+
warnings.warn(
|
|
363
|
+
f"Cannot determine a normal value for {self.name} without a numerical distribution or a normal range."
|
|
364
|
+
)
|
|
365
|
+
return None
|
|
366
|
+
|
|
367
|
+
def get_decreased_value(self, patient: "Patient" = None):
|
|
368
|
+
"""
|
|
369
|
+
Returns a value that is considered decreased for this lab value.
|
|
370
|
+
It prioritizes sampling from a numerical distribution if available,
|
|
371
|
+
otherwise uses the lower bound of the normal range.
|
|
372
|
+
"""
|
|
373
|
+
_age = patient.age() if patient else None
|
|
374
|
+
_gender = patient.gender if patient else None
|
|
375
|
+
normal_range = self.get_normal_range(age=_age, gender=_gender)
|
|
376
|
+
lower_bound = normal_range.get("min")
|
|
377
|
+
|
|
378
|
+
if self.default_numerical_value_distribution:
|
|
379
|
+
if patient:
|
|
380
|
+
for _ in range(10): # Try a few times
|
|
381
|
+
generated_value = self.default_numerical_value_distribution.generate_value(
|
|
382
|
+
lab_value=self, patient=patient
|
|
383
|
+
)
|
|
384
|
+
if lower_bound is not None:
|
|
385
|
+
if generated_value < lower_bound:
|
|
386
|
+
return generated_value
|
|
387
|
+
# Heuristic for "low" if no lower_bound, compare against mean - stddev
|
|
388
|
+
elif hasattr(self.default_numerical_value_distribution, "mean") and \
|
|
389
|
+
hasattr(self.default_numerical_value_distribution, "stddev") and \
|
|
390
|
+
self.default_numerical_value_distribution.mean is not None and \
|
|
391
|
+
self.default_numerical_value_distribution.stddev is not None and \
|
|
392
|
+
generated_value < (
|
|
393
|
+
self.default_numerical_value_distribution.mean - self.default_numerical_value_distribution.stddev
|
|
394
|
+
):
|
|
395
|
+
return generated_value
|
|
396
|
+
# Fallback
|
|
397
|
+
if lower_bound is not None:
|
|
398
|
+
return lower_bound - (abs(lower_bound * self.bound_adjustment_factor) if lower_bound != 0 else 1) # Decrease by factor or 1
|
|
399
|
+
# Return any generated value as last resort
|
|
400
|
+
return self.default_numerical_value_distribution.generate_value(lab_value=self, patient=patient)
|
|
401
|
+
else: # No patient, cannot use distribution
|
|
402
|
+
warnings.warn(
|
|
403
|
+
f"Cannot use numerical distribution for {self.name} without patient context. Falling back to normal range logic for decreased value."
|
|
404
|
+
)
|
|
405
|
+
if lower_bound is not None:
|
|
406
|
+
return lower_bound - (abs(lower_bound * self.bound_adjustment_factor) if lower_bound != 0 else 1)
|
|
407
|
+
else:
|
|
408
|
+
warnings.warn(
|
|
409
|
+
f"Cannot determine a decreased value for {self.name} without a lower normal range or patient context for distribution."
|
|
410
|
+
)
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
elif lower_bound is not None:
|
|
414
|
+
return lower_bound - (abs(lower_bound * self.bound_adjustment_factor) if lower_bound != 0 else 1)
|
|
415
|
+
else:
|
|
416
|
+
warnings.warn(
|
|
417
|
+
f"Cannot determine a decreased value for {self.name} without a numerical distribution or a lower normal range."
|
|
418
|
+
)
|
|
419
|
+
return None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Medication models initialization module."""
|
|
2
|
+
from .medication import Medication, MedicationManager
|
|
3
|
+
from .medication_schedule import MedicationSchedule, MedicationScheduleManager
|
|
4
|
+
from .medication_intake_time import MedicationIntakeTime, MedicationIntakeTimeManager
|
|
5
|
+
from .medication_indication_type import MedicationIndicationType, MedicationIndicationTypeManager
|
|
6
|
+
from .medication_indication import MedicationIndication, MedicationIndicationManager
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Medication",
|
|
10
|
+
"MedicationManager",
|
|
11
|
+
"MedicationSchedule",
|
|
12
|
+
"MedicationScheduleManager",
|
|
13
|
+
"MedicationIntakeTime",
|
|
14
|
+
"MedicationIntakeTimeManager",
|
|
15
|
+
"MedicationIndicationType",
|
|
16
|
+
"MedicationIndicationTypeManager",
|
|
17
|
+
"MedicationIndication",
|
|
18
|
+
"MedicationIndicationManager"
|
|
19
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'''Model for the medication.'''
|
|
2
|
+
from django.db import models
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MedicationManager(models.Manager):
|
|
6
|
+
'''Manager for the medication model.'''
|
|
7
|
+
def get_by_natural_key(self, name):
|
|
8
|
+
'''Retrieve a medication by its natural key.'''
|
|
9
|
+
return self.get(name=name)
|
|
10
|
+
|
|
11
|
+
class Medication(models.Model):
|
|
12
|
+
'''Model representing a medication.'''
|
|
13
|
+
name = models.CharField(max_length=255, unique=True)
|
|
14
|
+
adapt_to_renal_function = models.BooleanField(default = False)
|
|
15
|
+
adapt_to_hepatic_function = models.BooleanField(default=False)
|
|
16
|
+
adapt_to_indication = models.BooleanField(default=False)
|
|
17
|
+
adapt_to_age = models.BooleanField(default=False)
|
|
18
|
+
adapt_to_weight = models.BooleanField(default=False)
|
|
19
|
+
adapt_to_risk = models.BooleanField(default=False)
|
|
20
|
+
default_unit = models.ForeignKey('Unit', on_delete=models.CASCADE)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
objects = MedicationManager()
|
|
24
|
+
|
|
25
|
+
def natural_key(self):
|
|
26
|
+
'''Return the natural key for the medication.'''
|
|
27
|
+
return (self.name,)
|
|
28
|
+
|
|
29
|
+
def __str__(self):
|
|
30
|
+
return str(self.name)
|
|
31
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Model for medication indication."""
|
|
2
|
+
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MedicationIndicationManager(models.Manager):
|
|
7
|
+
"""Manager for the medication indication model."""
|
|
8
|
+
|
|
9
|
+
def get_by_natural_key(self, name):
|
|
10
|
+
"""Retrieve a medication indication by its natural key."""
|
|
11
|
+
return self.get(name=name)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MedicationIndication(models.Model):
|
|
15
|
+
"""Model representing a medication indication."""
|
|
16
|
+
|
|
17
|
+
name = models.CharField(max_length=255, unique=True)
|
|
18
|
+
indication_type = models.ForeignKey(
|
|
19
|
+
"MedicationIndicationType",
|
|
20
|
+
on_delete=models.CASCADE,
|
|
21
|
+
related_name="medication_indications",
|
|
22
|
+
)
|
|
23
|
+
medication_schedules = models.ManyToManyField(
|
|
24
|
+
"MedicationSchedule",
|
|
25
|
+
)
|
|
26
|
+
diseases = models.ManyToManyField("Disease")
|
|
27
|
+
events = models.ManyToManyField("Event")
|
|
28
|
+
disease_classification_choices = models.ManyToManyField(
|
|
29
|
+
"DiseaseClassificationChoice"
|
|
30
|
+
)
|
|
31
|
+
sources = models.ManyToManyField("InformationSource")
|
|
32
|
+
|
|
33
|
+
def get_indication_links(self) -> dict:
|
|
34
|
+
"""Return a dictionary of all linked objects for this medication indication."""
|
|
35
|
+
links = {
|
|
36
|
+
"medication_schedules": self.medication_schedules,
|
|
37
|
+
"diseases": self.diseases,
|
|
38
|
+
"events": self.events,
|
|
39
|
+
"disease_classification_choices": self.disease_classification_choices,
|
|
40
|
+
}
|
|
41
|
+
return links
|
|
42
|
+
|
|
43
|
+
objects = MedicationIndicationManager()
|
|
44
|
+
|
|
45
|
+
def natural_key(self):
|
|
46
|
+
"""Return the natural key for the medication indication."""
|
|
47
|
+
return (self.name,)
|
|
48
|
+
|
|
49
|
+
def __str__(self):
|
|
50
|
+
return str(self.name)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'''Model for medication indication type.'''
|
|
2
|
+
from django.db import models
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models import MedicationIndication
|
|
7
|
+
|
|
8
|
+
class MedicationIndicationTypeManager(models.Manager):
|
|
9
|
+
'''Manager for the medication indication type model.'''
|
|
10
|
+
def get_by_natural_key(self, name):
|
|
11
|
+
'''Retrieve a medication indication type by its natural key.'''
|
|
12
|
+
return self.get(name=name)
|
|
13
|
+
|
|
14
|
+
class MedicationIndicationType(models.Model):
|
|
15
|
+
'''Model representing a medication indication type.'''
|
|
16
|
+
name = models.CharField(max_length=255, unique=True)
|
|
17
|
+
|
|
18
|
+
objects = MedicationIndicationTypeManager()
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
medication_indications: models.QuerySet["MedicationIndication"]
|
|
22
|
+
|
|
23
|
+
def natural_key(self):
|
|
24
|
+
'''Return the natural key for the medication indication type.'''
|
|
25
|
+
return (self.name,)
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return str(self.name)
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def get_random_indication_by_type(cls, name) -> "MedicationIndication":
|
|
32
|
+
'''Return a random medication indication of the given type.'''
|
|
33
|
+
return cls.objects.get(name=name).medication_indications.order_by('?').first()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_random_medication_indication(self):
|
|
37
|
+
'''Return a random medication indication of this type.'''
|
|
38
|
+
from endoreg_db.models import MedicationIndication
|
|
39
|
+
return MedicationIndication.objects.filter(indication_type=self).order_by('?').first()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'''Model for medication intake time'''
|
|
2
|
+
from django.db import models
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MedicationIntakeTimeManager(models.Manager):
|
|
6
|
+
'''Manager for the medication intake time model.'''
|
|
7
|
+
def get_by_natural_key(self, name):
|
|
8
|
+
'''Retrieve a medication intake time by its natural key.'''
|
|
9
|
+
return self.get(name=name)
|
|
10
|
+
|
|
11
|
+
class MedicationIntakeTime(models.Model):
|
|
12
|
+
'''Model representing a medication intake time.'''
|
|
13
|
+
name = models.CharField(max_length=255, unique=True) # Made unique=True
|
|
14
|
+
repeats = models.CharField(max_length=20, default = "daily")
|
|
15
|
+
time = models.TimeField()
|
|
16
|
+
|
|
17
|
+
objects = MedicationIntakeTimeManager()
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def dm(cls):
|
|
21
|
+
'''Return the daily morning intake time object.'''
|
|
22
|
+
return cls.objects.get(name='daily-morning')
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def dno(cls):
|
|
26
|
+
'''Return the daily noon intake time object.'''
|
|
27
|
+
return cls.objects.get(name='daily-noon')
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def de(cls):
|
|
31
|
+
'''Return the daily evening intake time object.'''
|
|
32
|
+
return cls.objects.get(name='daily-evening')
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def dn(cls):
|
|
36
|
+
'''Return the daily night intake time object.'''
|
|
37
|
+
return cls.objects.get(name='daily-night')
|
|
38
|
+
|
|
39
|
+
def natural_key(self):
|
|
40
|
+
'''Return the natural key for the medication intake time.'''
|
|
41
|
+
return (self.name,)
|
|
42
|
+
|
|
43
|
+
def __str__(self):
|
|
44
|
+
return self.name + " at " + str(self.time) + " (" + self.repeats + ")"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'''Model for the medication schedule.'''
|
|
2
|
+
from typing import List, TYPE_CHECKING
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models import MedicationIntakeTime
|
|
7
|
+
class MedicationScheduleManager(models.Manager):
|
|
8
|
+
'''Manager for the medication schedule model.'''
|
|
9
|
+
def get_by_natural_key(self, name):
|
|
10
|
+
"""
|
|
11
|
+
Retrieve a MedicationSchedule instance by its name.
|
|
12
|
+
|
|
13
|
+
Parameters:
|
|
14
|
+
name (str): The name of the medication schedule to retrieve.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
MedicationSchedule: The matching medication schedule instance.
|
|
18
|
+
"""
|
|
19
|
+
return self.get(name=name)
|
|
20
|
+
|
|
21
|
+
class MedicationSchedule(models.Model):
|
|
22
|
+
'''Model representing a medication schedule.'''
|
|
23
|
+
name = models.CharField(max_length=255, unique=True)
|
|
24
|
+
description = models.TextField(blank=True, null=True)
|
|
25
|
+
medication = models.ForeignKey("Medication", on_delete=models.CASCADE)
|
|
26
|
+
unit = models.ForeignKey("Unit", on_delete=models.CASCADE)
|
|
27
|
+
therapy_duration_d = models.FloatField(blank=True, null=True)
|
|
28
|
+
dose = models.FloatField()
|
|
29
|
+
intake_times = models.ManyToManyField(
|
|
30
|
+
"MedicationIntakeTime",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
objects = MedicationScheduleManager()
|
|
34
|
+
|
|
35
|
+
def natural_key(self):
|
|
36
|
+
'''Return the natural key for the medication schedule.'''
|
|
37
|
+
return (self.name,)
|
|
38
|
+
|
|
39
|
+
def __str__(self):
|
|
40
|
+
return str(self.name)
|
|
41
|
+
|
|
42
|
+
def get_intake_times(self) -> List["MedicationIntakeTime"]:
|
|
43
|
+
'''Return a list of all intake times for this medication schedule.'''
|
|
44
|
+
return [_ for _ in self.intake_times.all()] # type: ignore # pylint: disable=E1101
|
|
45
|
+
|