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,357 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.core.exceptions import ValidationError
|
|
3
|
+
from django.utils import timezone
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from endoreg_db.models import (
|
|
8
|
+
PatientExamination,
|
|
9
|
+
Finding,
|
|
10
|
+
PatientFindingIntervention,
|
|
11
|
+
PatientFindingClassification,
|
|
12
|
+
LabelVideoSegment,
|
|
13
|
+
)
|
|
14
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
15
|
+
|
|
16
|
+
class PatientFinding(models.Model):
|
|
17
|
+
patient_examination = models.ForeignKey('PatientExamination', on_delete=models.CASCADE, related_name='patient_findings') # type: ignore[assignment]
|
|
18
|
+
finding = models.ForeignKey('Finding', on_delete=models.CASCADE, related_name='finding_patient_findings') # type: ignore[assignment]
|
|
19
|
+
|
|
20
|
+
# Audit-Felder für medizinische Nachverfolgung
|
|
21
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
22
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
23
|
+
created_by = models.ForeignKey('auth.User', on_delete=models.PROTECT, related_name='created_findings', null=True, blank=True)
|
|
24
|
+
updated_by = models.ForeignKey('auth.User', on_delete=models.PROTECT, related_name='updated_findings', null=True, blank=True)
|
|
25
|
+
|
|
26
|
+
# Soft Delete für historische Daten
|
|
27
|
+
is_active = models.BooleanField(default=True, help_text="Deaktiviert statt gelöscht für Audit-Trail")
|
|
28
|
+
deactivated_at = models.DateTimeField(null=True, blank=True)
|
|
29
|
+
deactivated_by = models.ForeignKey('auth.User', on_delete=models.PROTECT, related_name='deactivated_findings', null=True, blank=True)
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
patient_examination: "PatientExamination"
|
|
33
|
+
finding: "Finding"
|
|
34
|
+
classifications: models.QuerySet["PatientFindingClassification"]
|
|
35
|
+
interventions: models.QuerySet["PatientFindingIntervention"]
|
|
36
|
+
video_segments: models.QuerySet["LabelVideoSegment"]
|
|
37
|
+
|
|
38
|
+
class Meta:
|
|
39
|
+
verbose_name = 'Patient Finding'
|
|
40
|
+
verbose_name_plural = 'Patient Findings'
|
|
41
|
+
ordering = ['patient_examination', 'finding']
|
|
42
|
+
|
|
43
|
+
# Wichtige Constraints für Datenintegrität
|
|
44
|
+
constraints = [
|
|
45
|
+
models.UniqueConstraint(
|
|
46
|
+
fields=['patient_examination', 'finding'],
|
|
47
|
+
condition=models.Q(is_active=True),
|
|
48
|
+
name='unique_active_finding_per_examination'
|
|
49
|
+
),
|
|
50
|
+
models.CheckConstraint(
|
|
51
|
+
check=models.Q(
|
|
52
|
+
deactivated_at__isnull=True,
|
|
53
|
+
deactivated_by__isnull=True
|
|
54
|
+
) | models.Q(
|
|
55
|
+
deactivated_at__isnull=False,
|
|
56
|
+
deactivated_by__isnull=False,
|
|
57
|
+
is_active=False
|
|
58
|
+
),
|
|
59
|
+
name='deactivation_fields_consistency'
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
# Performance-optimierte Indizes
|
|
64
|
+
indexes = [
|
|
65
|
+
models.Index(fields=['patient_examination', 'finding']),
|
|
66
|
+
models.Index(fields=['patient_examination', 'is_active']),
|
|
67
|
+
models.Index(fields=['created_at']),
|
|
68
|
+
models.Index(fields=['finding', 'is_active']),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def patient(self):
|
|
73
|
+
"""Returns the patient associated with this patient finding."""
|
|
74
|
+
return self.patient_examination.patient
|
|
75
|
+
|
|
76
|
+
def __str__(self):
|
|
77
|
+
status = " (deaktiviert)" if not self.is_active else ""
|
|
78
|
+
return f"{self.patient_examination} - {self.finding}{status}"
|
|
79
|
+
|
|
80
|
+
def clean(self):
|
|
81
|
+
"""
|
|
82
|
+
Validates the patient finding against business rules before saving.
|
|
83
|
+
|
|
84
|
+
Ensures that the selected finding is allowed for the associated examination and that all required findings are present. Raises a ValidationError if the finding is not permitted or required findings are missing.
|
|
85
|
+
"""
|
|
86
|
+
super().clean()
|
|
87
|
+
|
|
88
|
+
# Prüfe ob Finding für diese Examination erlaubt ist
|
|
89
|
+
if self.finding and self.patient_examination:
|
|
90
|
+
available_findings = self.patient_examination.examination.get_available_findings()
|
|
91
|
+
if self.finding not in available_findings:
|
|
92
|
+
raise ValidationError({
|
|
93
|
+
'finding': f'Finding "{self.finding.name}" ist nicht für Examination "{self.patient_examination.examination.name}" erlaubt.'
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
# Prüfe Required Findings Logic
|
|
97
|
+
if self.finding and self.patient_examination:
|
|
98
|
+
self._validate_required_findings()
|
|
99
|
+
|
|
100
|
+
# This avoids validation errors on partial updates
|
|
101
|
+
def save(self, *args, **kwargs):
|
|
102
|
+
"""
|
|
103
|
+
Validates the model instance before saving, unless performing a partial update.
|
|
104
|
+
|
|
105
|
+
Performs full model validation with `full_clean()` before saving, except when `update_fields` is specified for a partial update.
|
|
106
|
+
"""
|
|
107
|
+
if not kwargs.get('update_fields'):
|
|
108
|
+
self.full_clean()
|
|
109
|
+
super().save(*args, **kwargs)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _validate_required_findings(self):
|
|
113
|
+
"""Validiert Required vs Optional Finding Constraints"""
|
|
114
|
+
examination = self.patient_examination.examination
|
|
115
|
+
|
|
116
|
+
# Hole Required Findings für diese Examination
|
|
117
|
+
required_findings = getattr(examination, 'required_findings', None)
|
|
118
|
+
if required_findings and required_findings.exists():
|
|
119
|
+
# Prüfe ob alle Required Findings vorhanden sind
|
|
120
|
+
existing_findings = self.patient_examination.patient_findings.filter(
|
|
121
|
+
is_active=True
|
|
122
|
+
).values_list('finding', flat=True)
|
|
123
|
+
|
|
124
|
+
missing_required = required_findings.exclude(id__in=existing_findings)
|
|
125
|
+
if missing_required.exists() and self.finding not in required_findings.all():
|
|
126
|
+
missing_names = ', '.join([f.name for f in missing_required])
|
|
127
|
+
raise ValidationError(
|
|
128
|
+
f'Erforderliche Findings fehlen: {missing_names}'
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def deactivate(self, user=None, reason=None):
|
|
132
|
+
"""Soft Delete mit Audit-Trail"""
|
|
133
|
+
self.is_active = False
|
|
134
|
+
self.deactivated_at = timezone.now()
|
|
135
|
+
self.deactivated_by = user
|
|
136
|
+
self.save(update_fields=['is_active', 'deactivated_at', 'deactivated_by'])
|
|
137
|
+
|
|
138
|
+
# Deaktiviere auch abhängige Objekte
|
|
139
|
+
self.locations.update(is_active=False, deactivated_at=timezone.now())
|
|
140
|
+
self.morphologies.update(is_active=False, deactivated_at=timezone.now())
|
|
141
|
+
self.interventions.update(is_active=False, deactivated_at=timezone.now())
|
|
142
|
+
|
|
143
|
+
def reactivate(self, user=None):
|
|
144
|
+
"""
|
|
145
|
+
Reactivates a previously deactivated patient finding after validating its state.
|
|
146
|
+
|
|
147
|
+
If validation passes, sets the finding as active, clears deactivation fields, updates the user, and saves changes. Raises a ValidationError if reactivation is not allowed.
|
|
148
|
+
"""
|
|
149
|
+
if not self.is_active:
|
|
150
|
+
# Prüfe ob Reaktivierung erlaubt ist
|
|
151
|
+
try:
|
|
152
|
+
self.clean()
|
|
153
|
+
self.is_active = True
|
|
154
|
+
self.deactivated_at = None
|
|
155
|
+
self.deactivated_by = None
|
|
156
|
+
self.updated_by = user
|
|
157
|
+
self.save(update_fields=['is_active', 'deactivated_at', 'deactivated_by', 'updated_by'])
|
|
158
|
+
except ValidationError as e:
|
|
159
|
+
raise ValidationError(f'Reaktivierung nicht möglich: {e}')
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_interventions(self):
|
|
163
|
+
"""
|
|
164
|
+
Retrieve all active interventions associated with this patient finding.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
QuerySet: Active related interventions with intervention details prefetched.
|
|
168
|
+
"""
|
|
169
|
+
return self.interventions.filter(is_active=True).select_related('intervention')
|
|
170
|
+
|
|
171
|
+
def add_classification(
|
|
172
|
+
self,
|
|
173
|
+
classification_id,
|
|
174
|
+
classification_choice_id,
|
|
175
|
+
user=None,
|
|
176
|
+
) -> "PatientFindingClassification":
|
|
177
|
+
"""
|
|
178
|
+
Add a classification choice to this patient finding after validating its association.
|
|
179
|
+
|
|
180
|
+
Parameters:
|
|
181
|
+
classification_id: The ID of the classification to add.
|
|
182
|
+
classification_choice_id: The ID of the classification choice to associate.
|
|
183
|
+
user: Optional user performing the action.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
PatientFindingClassification: The created or existing active classification association.
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
ValidationError: If the classification does not exist or the choice is not valid for the classification.
|
|
190
|
+
"""
|
|
191
|
+
from .patient_finding_classification import PatientFindingClassification
|
|
192
|
+
from ..finding import FindingClassification, FindingClassificationChoice
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
classification = FindingClassification.objects.get(id=classification_id)
|
|
196
|
+
classification_choice = FindingClassificationChoice.objects.filter(id=classification_choice_id).first()
|
|
197
|
+
|
|
198
|
+
if not classification.choices.filter(id=classification_choice_id).exists():
|
|
199
|
+
raise ValidationError(
|
|
200
|
+
f'Classification Choice {classification_choice_id} gehört nicht zu Classification {classification_id}'
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
existing = self.classifications.filter(
|
|
204
|
+
classification=classification,
|
|
205
|
+
classification_choice=classification_choice,
|
|
206
|
+
is_active=True
|
|
207
|
+
).first()
|
|
208
|
+
|
|
209
|
+
if existing:
|
|
210
|
+
return existing
|
|
211
|
+
|
|
212
|
+
patient_finding_classification = PatientFindingClassification.objects.create(
|
|
213
|
+
finding=self,
|
|
214
|
+
classification_id=classification_id,
|
|
215
|
+
classification_choice_id=classification_choice_id,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return patient_finding_classification
|
|
219
|
+
|
|
220
|
+
except FindingClassification.DoesNotExist:
|
|
221
|
+
raise ValidationError(f'Classification {classification_id} nicht gefunden')
|
|
222
|
+
|
|
223
|
+
def add_intervention(self, intervention_id, state="pending", date=None, user=None):
|
|
224
|
+
"""
|
|
225
|
+
Add an intervention to the patient finding after validating its existence.
|
|
226
|
+
|
|
227
|
+
Parameters:
|
|
228
|
+
intervention_id (int): The ID of the intervention to add.
|
|
229
|
+
state (str, optional): The state of the intervention. Defaults to "pending".
|
|
230
|
+
date (datetime, optional): The date of the intervention. Defaults to the current time if not provided.
|
|
231
|
+
user (User, optional): The user creating the intervention.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
PatientFindingIntervention: The created intervention instance.
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
ValidationError: If the specified intervention does not exist.
|
|
238
|
+
"""
|
|
239
|
+
from .patient_finding_intervention import PatientFindingIntervention
|
|
240
|
+
from ..finding import FindingIntervention
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
intervention = FindingIntervention.objects.get(id=intervention_id)
|
|
244
|
+
|
|
245
|
+
patient_finding_intervention = PatientFindingIntervention.objects.create(
|
|
246
|
+
patient_finding=self,
|
|
247
|
+
intervention=intervention,
|
|
248
|
+
state=state,
|
|
249
|
+
date=date or timezone.now(),
|
|
250
|
+
created_by=user
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return patient_finding_intervention
|
|
254
|
+
|
|
255
|
+
except FindingIntervention.DoesNotExist:
|
|
256
|
+
raise ValidationError(f'Intervention {intervention_id} nicht gefunden')
|
|
257
|
+
|
|
258
|
+
def add_video_segment(self, video_segment):
|
|
259
|
+
"""
|
|
260
|
+
Associates a video segment with this patient finding.
|
|
261
|
+
|
|
262
|
+
Parameters:
|
|
263
|
+
video_segment: The video segment instance to add.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
The added video segment instance.
|
|
267
|
+
"""
|
|
268
|
+
self.video_segments.add(video_segment) #TODO
|
|
269
|
+
return video_segment
|
|
270
|
+
|
|
271
|
+
# Manager für active/inactive Objekte
|
|
272
|
+
@property
|
|
273
|
+
def active_classifications(self):
|
|
274
|
+
"""
|
|
275
|
+
Return all active classifications associated with this patient finding.
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
QuerySet: Active related classifications where `is_active` is True.
|
|
279
|
+
"""
|
|
280
|
+
return self.classifications.filter(is_active=True)
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def locations(self):
|
|
284
|
+
"""
|
|
285
|
+
Return all classifications of this patient finding that are of type "location".
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
QuerySet: Classifications related to this finding filtered by the "location" classification type.
|
|
289
|
+
"""
|
|
290
|
+
classifications = self.classifications.filter(
|
|
291
|
+
classification__classification_types__name__iexact="location"
|
|
292
|
+
)
|
|
293
|
+
return classifications
|
|
294
|
+
|
|
295
|
+
@property
|
|
296
|
+
def morphologies(self):
|
|
297
|
+
"""
|
|
298
|
+
Return all classifications of this patient finding that are of type "morphology".
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
QuerySet: Classifications related to this finding filtered by the "morphology" classification type.
|
|
302
|
+
"""
|
|
303
|
+
classifications = self.classifications.filter(
|
|
304
|
+
classification__classification_types__name__iexact="morphology"
|
|
305
|
+
)
|
|
306
|
+
return classifications
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def active_interventions(self):
|
|
310
|
+
return self.interventions.filter(is_active=True)
|
|
311
|
+
|
|
312
|
+
@property
|
|
313
|
+
def links(self) -> "RequirementLinks":
|
|
314
|
+
"""
|
|
315
|
+
Aggregates and returns all related model instances relevant for requirement evaluation
|
|
316
|
+
as a RequirementLinks object.
|
|
317
|
+
|
|
318
|
+
This property provides access to:
|
|
319
|
+
- The finding associated with this patient finding
|
|
320
|
+
- All active finding classifications and their choices
|
|
321
|
+
- All active finding interventions
|
|
322
|
+
- The patient examination and patient
|
|
323
|
+
"""
|
|
324
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
325
|
+
from typing import cast, List
|
|
326
|
+
|
|
327
|
+
# Get the base finding
|
|
328
|
+
findings_list = [self.finding] if self.finding else []
|
|
329
|
+
|
|
330
|
+
# Get all active finding classifications and their choices
|
|
331
|
+
finding_classifications_list = []
|
|
332
|
+
finding_classification_choices_list = []
|
|
333
|
+
|
|
334
|
+
for pf_classification in self.active_classifications:
|
|
335
|
+
if pf_classification.classification:
|
|
336
|
+
finding_classifications_list.append(pf_classification.classification)
|
|
337
|
+
if pf_classification.classification_choice:
|
|
338
|
+
finding_classification_choices_list.append(pf_classification.classification_choice)
|
|
339
|
+
|
|
340
|
+
# Get all active finding interventions
|
|
341
|
+
finding_interventions_list = []
|
|
342
|
+
for pf_intervention in self.active_interventions:
|
|
343
|
+
if pf_intervention.intervention:
|
|
344
|
+
finding_interventions_list.append(pf_intervention.intervention)
|
|
345
|
+
|
|
346
|
+
# Include patient examination and patient for context
|
|
347
|
+
patient_examinations_list = [self.patient_examination] if self.patient_examination else []
|
|
348
|
+
patient_findings_list = cast("List[PatientFinding]", [self]) # Include self for direct patient finding evaluations
|
|
349
|
+
|
|
350
|
+
return RequirementLinks(
|
|
351
|
+
findings=findings_list,
|
|
352
|
+
finding_classifications=finding_classifications_list,
|
|
353
|
+
finding_classification_choices=finding_classification_choices_list,
|
|
354
|
+
finding_interventions=finding_interventions_list,
|
|
355
|
+
patient_examinations=patient_examinations_list,
|
|
356
|
+
patient_findings=patient_findings_list,
|
|
357
|
+
)
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from typing import TYPE_CHECKING, Dict
|
|
3
|
+
import random
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Corrected imports for type hints
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ..finding import (
|
|
10
|
+
FindingClassification,
|
|
11
|
+
FindingClassificationChoice,
|
|
12
|
+
)
|
|
13
|
+
from .patient_finding import PatientFinding
|
|
14
|
+
|
|
15
|
+
class PatientFindingClassification(models.Model):
|
|
16
|
+
"""Represents basic classifications for specific findings in a patient context.
|
|
17
|
+
Links a PatientFinding to a specific classification and choice, with optional subcategory values.
|
|
18
|
+
"""
|
|
19
|
+
finding = models.ForeignKey( # type: ignore[assignment]
|
|
20
|
+
"PatientFinding",
|
|
21
|
+
on_delete=models.CASCADE,
|
|
22
|
+
related_name="classifications"
|
|
23
|
+
)
|
|
24
|
+
classification = models.ForeignKey( # type: ignore[assignment]
|
|
25
|
+
"FindingClassification",
|
|
26
|
+
on_delete=models.CASCADE,
|
|
27
|
+
related_name="patient_finding_classifications"
|
|
28
|
+
)
|
|
29
|
+
classification_choice = models.ForeignKey( # type: ignore[assignment]
|
|
30
|
+
"FindingClassificationChoice",
|
|
31
|
+
on_delete=models.CASCADE,
|
|
32
|
+
related_name="patient_finding_classifications"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
is_active = models.BooleanField(default=True, help_text="Indicates if the classification is currently active.")
|
|
36
|
+
subcategories = models.JSONField(blank=True, null=True)
|
|
37
|
+
numerical_descriptors = models.JSONField(blank=True, null=True)
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
finding: "PatientFinding"
|
|
41
|
+
classification: "FindingClassification"
|
|
42
|
+
classification_choice: "FindingClassificationChoice"
|
|
43
|
+
|
|
44
|
+
class Meta:
|
|
45
|
+
verbose_name = 'Patient Finding Classification'
|
|
46
|
+
verbose_name_plural = 'Patient Finding Classifications'
|
|
47
|
+
ordering = ['finding', 'classification', 'classification_choice']
|
|
48
|
+
|
|
49
|
+
def __str__(self):
|
|
50
|
+
"""
|
|
51
|
+
Return a string representation combining the finding, classification, and classification choice.
|
|
52
|
+
"""
|
|
53
|
+
return f"{self.finding} - {self.classification} - {self.classification_choice}"
|
|
54
|
+
|
|
55
|
+
def save(self, *args, **kwargs):
|
|
56
|
+
"""
|
|
57
|
+
Saves the model instance after validating and initializing classification-related fields.
|
|
58
|
+
|
|
59
|
+
Ensures that the selected classification choice is valid for the associated classification. If subcategories or numerical descriptors are unset, initializes them from the classification choice before saving.
|
|
60
|
+
"""
|
|
61
|
+
if self.classification_choice not in self.classification.choices.all():
|
|
62
|
+
raise ValueError("classification_choice must be in classification.choices")
|
|
63
|
+
|
|
64
|
+
if not self.subcategories:
|
|
65
|
+
self.subcategories = self.classification_choice.subcategories
|
|
66
|
+
|
|
67
|
+
if not self.numerical_descriptors:
|
|
68
|
+
self.numerical_descriptors = self.classification_choice.numerical_descriptors
|
|
69
|
+
|
|
70
|
+
super().save(*args, **kwargs)
|
|
71
|
+
|
|
72
|
+
def initialize_and_get_subcategories(self):
|
|
73
|
+
"""
|
|
74
|
+
Ensure the subcategories field is initialized and return its dictionary.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
dict: The subcategories associated with this classification.
|
|
78
|
+
"""
|
|
79
|
+
if not self.subcategories:
|
|
80
|
+
self.save()
|
|
81
|
+
return self.subcategories
|
|
82
|
+
|
|
83
|
+
def initialize_and_get_descriptors(self):
|
|
84
|
+
"""
|
|
85
|
+
Return the numerical descriptors dictionary, initializing it if necessary.
|
|
86
|
+
|
|
87
|
+
If the `numerical_descriptors` field is empty or uninitialized, the method triggers model initialization and returns the resulting dictionary.
|
|
88
|
+
"""
|
|
89
|
+
if not self.numerical_descriptors:
|
|
90
|
+
self.save()
|
|
91
|
+
return self.numerical_descriptors
|
|
92
|
+
|
|
93
|
+
def set_subcategory(self, subcategory_name: str, subcategory_value: Dict):
|
|
94
|
+
"""
|
|
95
|
+
Update the value of a specified subcategory and save the classification.
|
|
96
|
+
|
|
97
|
+
Parameters:
|
|
98
|
+
subcategory_name (str): The name of the subcategory to update.
|
|
99
|
+
subcategory_value (dict): The value to assign to the subcategory.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
dict: The updated subcategory dictionary.
|
|
103
|
+
"""
|
|
104
|
+
assert subcategory_name in self.subcategories, "Subcategory must be in subcategories."
|
|
105
|
+
self.subcategories[subcategory_name]["value"] = subcategory_value
|
|
106
|
+
self.save()
|
|
107
|
+
|
|
108
|
+
return self.subcategories[subcategory_name]
|
|
109
|
+
|
|
110
|
+
def set_random_subcategories(self):
|
|
111
|
+
"""
|
|
112
|
+
Assign random values to all required subcategories that do not already have a value.
|
|
113
|
+
|
|
114
|
+
For each required subcategory without a value, selects a random option from its available choices, updates the subcategory, saves the model, and returns the updated subcategories dictionary.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
dict: The updated subcategories with random values assigned where needed.
|
|
118
|
+
"""
|
|
119
|
+
if not self.subcategories or not self.numerical_descriptors:
|
|
120
|
+
self.save()
|
|
121
|
+
|
|
122
|
+
self.refresh_from_db()
|
|
123
|
+
|
|
124
|
+
for subcategory_name, subcategory_dict in self.subcategories.items():
|
|
125
|
+
if subcategory_dict["required"] and not subcategory_dict.get("value", None):
|
|
126
|
+
subcategory_choice = random.choice(subcategory_dict["choices"])
|
|
127
|
+
self.subcategories[subcategory_name]["value"] = subcategory_choice
|
|
128
|
+
|
|
129
|
+
self.save()
|
|
130
|
+
|
|
131
|
+
return self.subcategories
|
|
132
|
+
|
|
133
|
+
def get_random_value_for_numerical_descriptor(self, descriptor_name):
|
|
134
|
+
|
|
135
|
+
"""
|
|
136
|
+
Generate a random value for the specified numerical descriptor using its defined distribution parameters.
|
|
137
|
+
|
|
138
|
+
Parameters:
|
|
139
|
+
descriptor_name (str): The name of the numerical descriptor to generate a value for.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
float: A randomly generated value based on the descriptor's distribution, clipped to its min and max range.
|
|
143
|
+
|
|
144
|
+
Raises:
|
|
145
|
+
ValueError: If the descriptor's distribution type is not supported.
|
|
146
|
+
"""
|
|
147
|
+
assert descriptor_name in self.numerical_descriptors, "Descriptor must be in numerical descriptors."
|
|
148
|
+
descriptor = self.numerical_descriptors[descriptor_name]
|
|
149
|
+
min_val = descriptor.get("min", 0)
|
|
150
|
+
max_val = descriptor.get("max", 1)
|
|
151
|
+
distribution = descriptor.get("distribution", "normal")
|
|
152
|
+
if distribution == "normal":
|
|
153
|
+
mean = descriptor.get("mean", 0.5)
|
|
154
|
+
std = descriptor.get("std", 0.1)
|
|
155
|
+
value = np.random.normal(mean, std)
|
|
156
|
+
# clip value to min and max
|
|
157
|
+
value = np.clip(value, min_val, max_val)
|
|
158
|
+
elif distribution == "uniform":
|
|
159
|
+
value = np.random.uniform(min_val, max_val)
|
|
160
|
+
else:
|
|
161
|
+
raise ValueError("Distribution not supported")
|
|
162
|
+
|
|
163
|
+
return value
|
|
164
|
+
|
|
165
|
+
def set_random_numerical_descriptor(self, descriptor_name, save=True):
|
|
166
|
+
"""
|
|
167
|
+
Assigns a random value to the specified numerical descriptor and optionally saves the model.
|
|
168
|
+
|
|
169
|
+
Parameters:
|
|
170
|
+
descriptor_name (str): The name of the numerical descriptor to update.
|
|
171
|
+
save (bool): If True, saves the model after updating the descriptor. Defaults to True.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
dict: The updated numerical descriptor dictionary with the new random value.
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
ValueError: If the descriptor name is not present in the numerical descriptors.
|
|
178
|
+
"""
|
|
179
|
+
if descriptor_name not in self.numerical_descriptors:
|
|
180
|
+
raise ValueError("Descriptor name must be in numerical descriptors.")
|
|
181
|
+
|
|
182
|
+
value = self.get_random_value_for_numerical_descriptor(descriptor_name)
|
|
183
|
+
|
|
184
|
+
self.numerical_descriptors[descriptor_name]["value"] = value
|
|
185
|
+
if save:
|
|
186
|
+
self.save()
|
|
187
|
+
|
|
188
|
+
return self.numerical_descriptors[descriptor_name]
|
|
189
|
+
|
|
190
|
+
def set_random_numerical_descriptors(self):
|
|
191
|
+
"""
|
|
192
|
+
Assigns random values to all numerical descriptors and saves the model.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
dict: The updated numerical_descriptors dictionary with assigned random values.
|
|
196
|
+
"""
|
|
197
|
+
if not self.subcategories or not self.numerical_descriptors:
|
|
198
|
+
self.save()
|
|
199
|
+
|
|
200
|
+
numerical_descriptors = self.numerical_descriptors
|
|
201
|
+
|
|
202
|
+
for numerical_descriptor_name, _numerical_descriptor_dict in numerical_descriptors.items():
|
|
203
|
+
self.set_random_numerical_descriptor(numerical_descriptor_name, save=False)
|
|
204
|
+
|
|
205
|
+
self.save()
|
|
206
|
+
|
|
207
|
+
return self.numerical_descriptors
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from operator import is_
|
|
2
|
+
from django.db import models
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..finding import FindingIntervention
|
|
7
|
+
from .patient_finding import PatientFinding
|
|
8
|
+
|
|
9
|
+
class PatientFindingIntervention(models.Model):
|
|
10
|
+
finding = models.ForeignKey(
|
|
11
|
+
'PatientFinding',
|
|
12
|
+
on_delete=models.CASCADE,
|
|
13
|
+
related_name='interventions'
|
|
14
|
+
)
|
|
15
|
+
intervention = models.ForeignKey(
|
|
16
|
+
'FindingIntervention',
|
|
17
|
+
on_delete=models.CASCADE,
|
|
18
|
+
related_name='patient_finding_interventions'
|
|
19
|
+
)
|
|
20
|
+
is_active = models.BooleanField(
|
|
21
|
+
default=True,
|
|
22
|
+
help_text="Indicates if the intervention is currently active."
|
|
23
|
+
)
|
|
24
|
+
state = models.CharField(max_length=100, blank=True, null=True)
|
|
25
|
+
time_start = models.DateTimeField(blank=True, null=True)
|
|
26
|
+
time_end = models.DateTimeField(blank=True, null=True)
|
|
27
|
+
date = models.DateField(blank=True, null=True)
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
finding: "PatientFinding"
|
|
31
|
+
intervention: "FindingIntervention"
|
|
32
|
+
|
|
33
|
+
def __str__(self):
|
|
34
|
+
return self.intervention.name
|
|
35
|
+
|
|
36
|
+
def natural_key(self):
|
|
37
|
+
return (self.intervention.name,)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
objects = models.Manager()
|