endoreg-db 0.8.9.32__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.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/__init__.py +0 -0
- endoreg_db/_version.py +34 -0
- endoreg_db/admin.py +97 -0
- endoreg_db/api/serializers/finding_descriptions.py +0 -0
- endoreg_db/api/views/finding_descriptions.py +0 -0
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +17 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/authz/auth.py +78 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +20 -0
- endoreg_db/authz/middleware.py +84 -0
- endoreg_db/authz/permissions.py +138 -0
- endoreg_db/authz/policy.py +224 -0
- endoreg_db/authz/settings.py +64 -0
- endoreg_db/authz/views_auth.py +70 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +99 -0
- endoreg_db/config/__init__.py +0 -0
- endoreg_db/config/env.py +106 -0
- endoreg_db/config/settings/__init__.py +6 -0
- endoreg_db/config/settings/base.py +148 -0
- endoreg_db/config/settings/case_gen.py +32 -0
- endoreg_db/config/settings/dev.py +108 -0
- endoreg_db/config/settings/keycloak.py +177 -0
- endoreg_db/config/settings/prod.py +66 -0
- endoreg_db/config/settings/test.py +72 -0
- endoreg_db/data/__init__.py +135 -0
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/ai_model_label/label/data.yaml +88 -0
- 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_label/label-type/data.yaml +7 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
- endoreg_db/data/ai_model_type/data.yaml +7 -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/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
- endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
- endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
- endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
- endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
- endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
- endoreg_db/data/case_template/rule_value/.init +0 -0
- endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
- endoreg_db/data/case_template/template/base.yaml +8 -0
- endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
- endoreg_db/data/case_template/tmp/_rule_value +13 -0
- endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
- endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
- endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
- endoreg_db/data/center/data.yaml +99 -0
- endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
- endoreg_db/data/center_shift/ukw.yaml +9 -0
- endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -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/cardiovascular.yaml +37 -0
- endoreg_db/data/disease/hepatology.yaml +5 -0
- endoreg_db/data/disease/misc.yaml +5 -0
- endoreg_db/data/disease/renal.yaml +5 -0
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
- endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
- endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
- endoreg_db/data/distribution/date/patient.yaml +7 -0
- endoreg_db/data/distribution/multiple_categorical/.init +0 -0
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
- endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/endoscope_type/data.yaml +11 -0
- endoreg_db/data/endoscopy_processor/data.yaml +50 -0
- endoreg_db/data/event/cardiology.yaml +15 -0
- endoreg_db/data/event/neurology.yaml +14 -0
- endoreg_db/data/event/surgery.yaml +13 -0
- endoreg_db/data/event/thrombembolism.yaml +20 -0
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/examination/examinations/data.yaml +172 -0
- endoreg_db/data/examination/time/data.yaml +48 -0
- endoreg_db/data/examination/time-type/data.yaml +5 -0
- endoreg_db/data/examination/type/data.yaml +17 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +359 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +90 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +97 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/00_generic.yaml +15 -0
- endoreg_db/data/finding_classification_choice/00_generic_baseline.yaml +23 -0
- endoreg_db/data/finding_classification_choice/00_generic_complication.yaml +15 -0
- endoreg_db/data/finding_classification_choice/00_generic_histology.yaml +21 -0
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_bowel_preparation.yaml +49 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_generic.yaml +19 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_histology.yaml +20 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_location.yaml +248 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_morphology.yaml +75 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/00_generic.yaml +53 -0
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_type/data.yaml +39 -0
- endoreg_db/data/gender/data.yaml +42 -0
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/data.yaml +30 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
- endoreg_db/data/information_source/medication.yaml +6 -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 +37 -0
- endoreg_db/data/lab_value/coagulation.yaml +54 -0
- endoreg_db/data/lab_value/electrolytes.yaml +228 -0
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
- endoreg_db/data/lab_value/hematology.yaml +184 -0
- endoreg_db/data/lab_value/hormones.yaml +59 -0
- endoreg_db/data/lab_value/lipids.yaml +53 -0
- endoreg_db/data/lab_value/misc.yaml +76 -0
- endoreg_db/data/lab_value/renal_function.yaml +12 -0
- endoreg_db/data/log_type/data.yaml +57 -0
- 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/material/material.yaml +91 -0
- endoreg_db/data/medication/anticoagulation.yaml +65 -0
- endoreg_db/data/medication/tah.yaml +70 -0
- endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
- endoreg_db/data/medication_indication_type/data.yaml +11 -0
- endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
- endoreg_db/data/medication_intake_time/base.yaml +31 -0
- endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
- endoreg_db/data/medication_schedule/ass.yaml +12 -0
- endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
- endoreg_db/data/names_first/first_names.yaml +54 -0
- endoreg_db/data/names_last/last_names.yaml +51 -0
- endoreg_db/data/network_device/data.yaml +59 -0
- endoreg_db/data/network_device_type/data.yaml +12 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
- endoreg_db/data/pdf_type/data.yaml +46 -0
- endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
- endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
- endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
- endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
- endoreg_db/data/profession/data.yaml +70 -0
- 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/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
- endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +24 -0
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/old/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement/old/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/old/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/old/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/old/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/old/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/old/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/old/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/old/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/old/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/old/gender.yaml +0 -0
- endoreg_db/data/requirement/old/lab_value.yaml +441 -0
- endoreg_db/data/requirement/old/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/_old/age.yaml +13 -0
- endoreg_db/data/requirement_operator/_old/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/_old/model_operators.yaml +96 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +65 -0
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set_type/data.yaml +41 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
- endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -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/m2.yaml +0 -0
- endoreg_db/data/shift_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +32 -0
- endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
- endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
- endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
- endoreg_db/data/unit/concentration.yaml +115 -0
- endoreg_db/data/unit/data.yaml +17 -0
- endoreg_db/data/unit/length.yaml +31 -0
- endoreg_db/data/unit/misc.yaml +20 -0
- endoreg_db/data/unit/rate.yaml +6 -0
- endoreg_db/data/unit/time.yaml +48 -0
- endoreg_db/data/unit/volume.yaml +35 -0
- endoreg_db/data/unit/weight.yaml +38 -0
- endoreg_db/data/waste/data.yaml +12 -0
- endoreg_db/exceptions.py +24 -0
- endoreg_db/export/frames/export.py +6 -0
- endoreg_db/export/frames/export_frames_with_labels.py +616 -0
- endoreg_db/factories/__init__.py +0 -0
- endoreg_db/forms/__init__.py +4 -0
- endoreg_db/forms/examination_form.py +12 -0
- endoreg_db/forms/patient_finding_intervention_form.py +40 -0
- endoreg_db/forms/patient_form.py +23 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -0
- endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
- endoreg_db/forms/settings/__init__.py +11 -0
- endoreg_db/forms/unit.py +7 -0
- endoreg_db/helpers/__init__.py +0 -0
- endoreg_db/helpers/count_db.py +48 -0
- endoreg_db/helpers/data_loader.py +280 -0
- endoreg_db/helpers/default_objects.py +414 -0
- endoreg_db/helpers/download_segmentation_model.py +32 -0
- endoreg_db/helpers/interact.py +1 -0
- endoreg_db/helpers/test_video_helper.py +127 -0
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +83 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +42 -0
- endoreg_db/import_files/context/validate_directories.py +57 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +99 -0
- endoreg_db/import_files/file_storage/create_video_file.py +104 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +42 -0
- endoreg_db/import_files/file_storage/state_management.py +463 -0
- endoreg_db/import_files/file_storage/storage.py +42 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +99 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/pseudonymization/__init__.py +0 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +181 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +139 -0
- endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
- endoreg_db/import_files/report_import_service.py +147 -0
- endoreg_db/import_files/video_import_service.py +154 -0
- endoreg_db/logger_conf.py +156 -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 +132 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +177 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +419 -0
- endoreg_db/management/commands/export_frame_annot.py +196 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +206 -0
- endoreg_db/management/commands/fix_video_paths.py +186 -0
- endoreg_db/management/commands/import_report.py +361 -0
- endoreg_db/management/commands/list_routes.py +20 -0
- endoreg_db/management/commands/load_ai_model_data.py +83 -0
- endoreg_db/management/commands/load_ai_model_label_data.py +60 -0
- endoreg_db/management/commands/load_base_db_data.py +63 -0
- endoreg_db/management/commands/load_center_data.py +68 -0
- endoreg_db/management/commands/load_contraindication_data.py +39 -0
- endoreg_db/management/commands/load_disease_classification_choices_data.py +38 -0
- endoreg_db/management/commands/load_disease_classification_data.py +38 -0
- endoreg_db/management/commands/load_disease_data.py +59 -0
- endoreg_db/management/commands/load_distribution_data.py +63 -0
- endoreg_db/management/commands/load_endoscope_data.py +58 -0
- endoreg_db/management/commands/load_event_data.py +39 -0
- endoreg_db/management/commands/load_examination_data.py +78 -0
- endoreg_db/management/commands/load_examination_indication_data.py +85 -0
- endoreg_db/management/commands/load_finding_data.py +115 -0
- endoreg_db/management/commands/load_gender_data.py +37 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +142 -0
- endoreg_db/management/commands/load_information_source.py +46 -0
- endoreg_db/management/commands/load_lab_value_data.py +52 -0
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_medication_data.py +104 -0
- endoreg_db/management/commands/load_name_data.py +36 -0
- endoreg_db/management/commands/load_organ_data.py +39 -0
- endoreg_db/management/commands/load_pdf_type_data.py +58 -0
- endoreg_db/management/commands/load_profession_data.py +40 -0
- endoreg_db/management/commands/load_qualification_data.py +56 -0
- endoreg_db/management/commands/load_report_reader_flag_data.py +40 -0
- endoreg_db/management/commands/load_requirement_data.py +207 -0
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/load_risk_data.py +57 -0
- endoreg_db/management/commands/load_shift_data.py +57 -0
- endoreg_db/management/commands/load_tag_data.py +54 -0
- endoreg_db/management/commands/load_unit_data.py +40 -0
- endoreg_db/management/commands/load_user_groups.py +26 -0
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +70 -0
- endoreg_db/management/commands/setup_endoreg_db.py +459 -0
- endoreg_db/management/commands/start_filewatcher.py +115 -0
- endoreg_db/management/commands/storage_management.py +622 -0
- endoreg_db/management/commands/summarize_db_content.py +280 -0
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +189 -0
- endoreg_db/management/commands/video_validation.py +20 -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 +1953 -0
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +322 -0
- endoreg_db/models/administration/__init__.py +95 -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 +180 -0
- endoreg_db/models/administration/ai/model_type.py +42 -0
- endoreg_db/models/administration/case/__init__.py +5 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/administration/case/case_template/__init__.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_rule.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_type.py +3 -0
- endoreg_db/models/administration/center/__init__.py +13 -0
- endoreg_db/models/administration/center/center.py +85 -0
- endoreg_db/models/administration/center/center_product.py +67 -0
- endoreg_db/models/administration/center/center_resource.py +69 -0
- endoreg_db/models/administration/center/center_shift.py +94 -0
- endoreg_db/models/administration/center/center_waste.py +42 -0
- endoreg_db/models/administration/person/__init__.py +26 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +40 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +44 -0
- endoreg_db/models/administration/person/employee/employee_type.py +50 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +64 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/administration/person/names/first_name.py +20 -0
- endoreg_db/models/administration/person/names/last_name.py +20 -0
- endoreg_db/models/administration/person/patient/__init__.py +7 -0
- endoreg_db/models/administration/person/patient/patient.py +488 -0
- endoreg_db/models/administration/person/patient/patient_external_id.py +36 -0
- endoreg_db/models/administration/person/person.py +35 -0
- endoreg_db/models/administration/person/profession/__init__.py +28 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +41 -0
- endoreg_db/models/administration/product/__init__.py +15 -0
- endoreg_db/models/administration/product/product.py +106 -0
- endoreg_db/models/administration/product/product_group.py +41 -0
- endoreg_db/models/administration/product/product_material.py +60 -0
- endoreg_db/models/administration/product/product_weight.py +51 -0
- endoreg_db/models/administration/product/reference_product.py +147 -0
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +43 -0
- endoreg_db/models/administration/qualification/qualification_type.py +39 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +72 -0
- endoreg_db/models/administration/shift/shift.py +57 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +23 -0
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +85 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +61 -0
- endoreg_db/models/label/label.py +91 -0
- endoreg_db/models/label/label_set.py +68 -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 +42 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +611 -0
- endoreg_db/models/label/video_segmentation_label.py +35 -0
- endoreg_db/models/label/video_segmentation_labelset.py +28 -0
- endoreg_db/models/media/__init__.py +23 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +137 -0
- endoreg_db/models/media/pdf/__init__.py +12 -0
- endoreg_db/models/media/pdf/raw_pdf.py +764 -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 +85 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +46 -0
- endoreg_db/models/media/video/__init__.py +9 -0
- endoreg_db/models/media/video/create_from_file.py +402 -0
- endoreg_db/models/media/video/pipe_1.py +258 -0
- endoreg_db/models/media/video/pipe_2.py +129 -0
- endoreg_db/models/media/video/video_file.py +907 -0
- endoreg_db/models/media/video/video_file_ai.py +828 -0
- endoreg_db/models/media/video/video_file_anonymize.py +524 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +49 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +25 -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 +126 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +233 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +36 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +13 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +24 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +40 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +44 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +30 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +205 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +228 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +107 -0
- endoreg_db/models/media/video/video_file_io.py +272 -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 +58 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +62 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +183 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +198 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +178 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +105 -0
- endoreg_db/models/media/video/video_file_segments.py +317 -0
- endoreg_db/models/media/video/video_metadata.py +67 -0
- endoreg_db/models/media/video/video_processing.py +192 -0
- endoreg_db/models/medical/__init__.py +136 -0
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/contraindication/__init__.py +29 -0
- endoreg_db/models/medical/disease.py +174 -0
- endoreg_db/models/medical/event.py +154 -0
- endoreg_db/models/medical/examination/__init__.py +20 -0
- endoreg_db/models/medical/examination/examination.py +183 -0
- endoreg_db/models/medical/examination/examination_indication.py +229 -0
- endoreg_db/models/medical/examination/examination_time.py +68 -0
- endoreg_db/models/medical/examination/examination_time_type.py +44 -0
- endoreg_db/models/medical/examination/examination_type.py +47 -0
- endoreg_db/models/medical/finding/__init__.py +20 -0
- endoreg_db/models/medical/finding/finding.py +113 -0
- endoreg_db/models/medical/finding/finding_classification.py +131 -0
- endoreg_db/models/medical/finding/finding_intervention.py +68 -0
- endoreg_db/models/medical/finding/finding_type.py +38 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +77 -0
- endoreg_db/models/medical/hardware/endoscopy_processor.py +182 -0
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +490 -0
- endoreg_db/models/medical/medication/__init__.py +23 -0
- endoreg_db/models/medical/medication/medication.py +45 -0
- endoreg_db/models/medical/medication/medication_indication.py +78 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +58 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +58 -0
- endoreg_db/models/medical/medication/medication_schedule.py +58 -0
- endoreg_db/models/medical/organ/__init__.py +38 -0
- endoreg_db/models/medical/patient/__init__.py +48 -0
- endoreg_db/models/medical/patient/medication_examples.py +56 -0
- endoreg_db/models/medical/patient/patient_disease.py +72 -0
- endoreg_db/models/medical/patient/patient_event.py +80 -0
- endoreg_db/models/medical/patient/patient_examination.py +280 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +57 -0
- endoreg_db/models/medical/patient/patient_finding.py +416 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +231 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +37 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +157 -0
- endoreg_db/models/medical/patient/patient_lab_value.py +247 -0
- endoreg_db/models/medical/patient/patient_medication.py +111 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +152 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +73 -0
- endoreg_db/models/medical/risk/risk_type.py +54 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/model_meta.py +266 -0
- endoreg_db/models/metadata/model_meta_logic.py +485 -0
- endoreg_db/models/metadata/pdf_meta.py +96 -0
- endoreg_db/models/metadata/sensitive_meta.py +345 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +1161 -0
- endoreg_db/models/metadata/video_meta.py +459 -0
- endoreg_db/models/metadata/video_prediction_logic.py +232 -0
- endoreg_db/models/metadata/video_prediction_meta.py +319 -0
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +40 -0
- endoreg_db/models/other/distribution/__init__.py +46 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +22 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +163 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +50 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +211 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +23 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +110 -0
- endoreg_db/models/other/gender.py +32 -0
- endoreg_db/models/other/information_source.py +190 -0
- endoreg_db/models/other/material.py +34 -0
- endoreg_db/models/other/resource.py +24 -0
- endoreg_db/models/other/tag.py +32 -0
- endoreg_db/models/other/transport_route.py +40 -0
- endoreg_db/models/other/unit.py +40 -0
- endoreg_db/models/other/waste.py +28 -0
- endoreg_db/models/report/__init__.py +0 -0
- endoreg_db/models/report/images.py +0 -0
- endoreg_db/models/report/report.py +5 -0
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +792 -0
- endoreg_db/models/requirement/requirement_error.py +84 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +137 -0
- endoreg_db/models/requirement/requirement_operator.py +187 -0
- endoreg_db/models/requirement/requirement_set.py +327 -0
- endoreg_db/models/state/__init__.py +13 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/anonymization.py +30 -0
- endoreg_db/models/state/audit_ledger.py +155 -0
- endoreg_db/models/state/label_video_segment.py +31 -0
- endoreg_db/models/state/processing_history/__init__.py +3 -0
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +219 -0
- endoreg_db/models/state/sensitive_meta.py +50 -0
- endoreg_db/models/state/video.py +251 -0
- endoreg_db/models/upload_job.py +100 -0
- endoreg_db/models/utils.py +138 -0
- endoreg_db/queries/__init__.py +3 -0
- endoreg_db/queries/annotations/__init__.py +1 -0
- endoreg_db/queries/annotations/legacy.py +169 -0
- endoreg_db/queries/sanity/__init_.py +0 -0
- endoreg_db/root_urls.py +27 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +30 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +861 -0
- endoreg_db/serializers/__init__.py +104 -0
- endoreg_db/serializers/administration/__init__.py +13 -0
- endoreg_db/serializers/administration/ai/__init__.py +9 -0
- endoreg_db/serializers/administration/ai/active_model.py +12 -0
- endoreg_db/serializers/administration/ai/ai_model.py +20 -0
- endoreg_db/serializers/administration/ai/model_type.py +12 -0
- endoreg_db/serializers/administration/center.py +14 -0
- endoreg_db/serializers/administration/gender.py +11 -0
- endoreg_db/serializers/anonymization.py +77 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +45 -0
- endoreg_db/serializers/examination/dropdown.py +20 -0
- endoreg_db/serializers/examination_serializer.py +9 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +61 -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 +11 -0
- endoreg_db/serializers/label_video_segment/__init__.py +9 -0
- endoreg_db/serializers/label_video_segment/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/label_video_segment/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +427 -0
- endoreg_db/serializers/meta/__init__.py +13 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +122 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +153 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +62 -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 +72 -0
- endoreg_db/serializers/misc/sensitive_patient_data.py +144 -0
- endoreg_db/serializers/misc/stats.py +35 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +74 -0
- endoreg_db/serializers/patient/__init__.py +12 -0
- endoreg_db/serializers/patient/patient.py +103 -0
- endoreg_db/serializers/patient/patient_dropdown.py +35 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +168 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +32 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +47 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +62 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +28 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +40 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +135 -0
- endoreg_db/serializers/pdf/__init__.py +3 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +101 -0
- endoreg_db/serializers/requirements/requirement_schema.py +20 -0
- endoreg_db/serializers/requirements/requirement_sets.py +99 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +301 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/video_file.py +283 -0
- endoreg_db/serializers/video/video_file_brief.py +14 -0
- endoreg_db/serializers/video/video_file_detail.py +96 -0
- endoreg_db/serializers/video/video_file_list.py +100 -0
- endoreg_db/serializers/video/video_processing_history.py +172 -0
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +274 -0
- endoreg_db/services/examination_evaluation.py +172 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +424 -0
- endoreg_db/services/lookup_store.py +266 -0
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/pdf_import.py +0 -0
- endoreg_db/services/polling_coordinator.py +319 -0
- endoreg_db/services/pseudonym_service.py +94 -0
- endoreg_db/services/report_import.py +13 -0
- endoreg_db/services/segment_sync.py +171 -0
- endoreg_db/services/video_import.py +9 -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 +56 -0
- endoreg_db/urls/ai.py +14 -0
- endoreg_db/urls/anonymization.py +78 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +34 -0
- endoreg_db/urls/examination.py +63 -0
- endoreg_db/urls/media.py +251 -0
- endoreg_db/urls/patient.py +23 -0
- endoreg_db/urls/requirements.py +15 -0
- endoreg_db/urls/root_urls.py +28 -0
- endoreg_db/urls/stats.py +54 -0
- endoreg_db/urls/upload.py +12 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +97 -0
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +6 -0
- endoreg_db/utils/ai/inference_dataset.py +51 -0
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +270 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +293 -0
- endoreg_db/utils/ai/preprocess.py +76 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +32 -0
- endoreg_db/utils/check_video_files.py +175 -0
- endoreg_db/utils/cropping.py +30 -0
- endoreg_db/utils/dataloader.py +285 -0
- endoreg_db/utils/dates.py +59 -0
- endoreg_db/utils/defaults/set_default_center.py +33 -0
- endoreg_db/utils/env.py +37 -0
- endoreg_db/utils/extract_specific_frames.py +87 -0
- endoreg_db/utils/file_operations.py +70 -0
- endoreg_db/utils/fix_video_path_direct.py +157 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +138 -0
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +237 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +82 -0
- endoreg_db/utils/ocr.py +195 -0
- endoreg_db/utils/operation_log.py +87 -0
- endoreg_db/utils/parse_and_generate_yaml.py +45 -0
- endoreg_db/utils/paths.py +159 -0
- endoreg_db/utils/permissions.py +160 -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 +144 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +22 -0
- endoreg_db/utils/product/sum_weights.py +20 -0
- endoreg_db/utils/pydantic_models/__init__.py +5 -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/_old/lab_value_operators.py +678 -0
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +842 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +114 -0
- endoreg_db/utils/setup_config.py +196 -0
- endoreg_db/utils/storage.py +117 -0
- endoreg_db/utils/translation.py +31 -0
- endoreg_db/utils/uuid.py +5 -0
- endoreg_db/utils/validate_endo_roi.py +33 -0
- endoreg_db/utils/validate_subcategory_dict.py +93 -0
- endoreg_db/utils/validate_video_detailed.py +415 -0
- endoreg_db/utils/video/__init__.py +30 -0
- endoreg_db/utils/video/extract_frames.py +100 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +996 -0
- endoreg_db/utils/video/names.py +47 -0
- endoreg_db/utils/video/streaming_processor.py +386 -0
- endoreg_db/utils/video/video_splitter.py +105 -0
- endoreg_db/versioning.md +79 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +247 -0
- endoreg_db/views/__init__.py +157 -0
- endoreg_db/views/anonymization/__init__.py +31 -0
- endoreg_db/views/anonymization/media_management.py +486 -0
- endoreg_db/views/anonymization/overview.py +307 -0
- endoreg_db/views/anonymization/validate.py +310 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +146 -0
- endoreg_db/views/examination/__init__.py +30 -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 +62 -0
- endoreg_db/views/examination/get_finding_classifications.py +38 -0
- endoreg_db/views/examination/get_findings.py +39 -0
- endoreg_db/views/examination/get_instruments.py +19 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +116 -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 +41 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +54 -0
- endoreg_db/views/media/__init__.py +32 -0
- endoreg_db/views/media/pdf_media.py +411 -0
- endoreg_db/views/media/sensitive_metadata.py +372 -0
- endoreg_db/views/media/video_media.py +275 -0
- endoreg_db/views/meta/__init__.py +7 -0
- endoreg_db/views/meta/sensitive_meta_list.py +102 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +74 -0
- endoreg_db/views/misc/__init__.py +29 -0
- endoreg_db/views/misc/center.py +14 -0
- endoreg_db/views/misc/csrf.py +8 -0
- endoreg_db/views/misc/gender.py +15 -0
- endoreg_db/views/misc/stats.py +255 -0
- endoreg_db/views/misc/upload_views.py +241 -0
- endoreg_db/views/patient/__init__.py +3 -0
- endoreg_db/views/patient/patient.py +253 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +141 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +58 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +72 -0
- endoreg_db/views/patient_examination/video.py +228 -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 +71 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +291 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +75 -0
- endoreg_db/views/report/__init__.py +7 -0
- endoreg_db/views/report/reimport.py +177 -0
- endoreg_db/views/report/report_stream.py +191 -0
- endoreg_db/views/requirement/__init__.py +11 -0
- endoreg_db/views/requirement/evaluate.py +278 -0
- endoreg_db/views/requirement/lookup.py +380 -0
- endoreg_db/views/requirement/lookup_store.py +183 -0
- endoreg_db/views/requirement/requirement_utils.py +87 -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 +266 -0
- endoreg_db/views/video/__init__.py +49 -0
- endoreg_db/views/video/ai/__init__.py +8 -0
- endoreg_db/views/video/ai/label.py +159 -0
- endoreg_db/views/video/correction.py +529 -0
- endoreg_db/views/video/reimport.py +230 -0
- endoreg_db/views/video/segments_crud.py +709 -0
- endoreg_db/views/video/video_apply_mask.py +49 -0
- endoreg_db/views/video/video_correction.py +22 -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_metadata.py +101 -0
- endoreg_db/views/video/video_processing_history.py +25 -0
- endoreg_db/views/video/video_remove_frames.py +49 -0
- endoreg_db/views/video/video_stream.py +334 -0
- endoreg_db-0.8.9.32.dist-info/METADATA +404 -0
- endoreg_db-0.8.9.32.dist-info/RECORD +787 -0
- endoreg_db-0.8.9.32.dist-info/WHEEL +4 -0
- endoreg_db-0.8.9.32.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,792 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from subprocess import run
|
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Tuple, Union, cast
|
|
4
|
+
|
|
5
|
+
from django.db import models
|
|
6
|
+
|
|
7
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
QuerySet = models.QuerySet
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from endoreg_db.models import ( # RequirementSet,
|
|
16
|
+
Disease,
|
|
17
|
+
DiseaseClassificationChoice,
|
|
18
|
+
Event,
|
|
19
|
+
EventClassification,
|
|
20
|
+
EventClassificationChoice,
|
|
21
|
+
Examination,
|
|
22
|
+
ExaminationIndication,
|
|
23
|
+
Finding,
|
|
24
|
+
FindingClassification,
|
|
25
|
+
FindingClassificationChoice,
|
|
26
|
+
FindingClassificationType,
|
|
27
|
+
FindingIntervention,
|
|
28
|
+
Gender,
|
|
29
|
+
LabValue,
|
|
30
|
+
Medication,
|
|
31
|
+
MedicationIndication,
|
|
32
|
+
MedicationIntakeTime, # Added MedicationIntakeTime
|
|
33
|
+
MedicationSchedule,
|
|
34
|
+
PatientDisease,
|
|
35
|
+
PatientEvent,
|
|
36
|
+
PatientExamination,
|
|
37
|
+
PatientFinding,
|
|
38
|
+
PatientFindingClassification,
|
|
39
|
+
PatientFindingIntervention,
|
|
40
|
+
PatientLabValue,
|
|
41
|
+
PatientMedicationSchedule, # Added PatientMedicationSchedule
|
|
42
|
+
RequirementOperator,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# from endoreg_db.utils.links.requirement_link import RequirementLinks # Already imported above
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class RequirementTypeManager(models.Manager):
|
|
49
|
+
def get_by_natural_key(self, name):
|
|
50
|
+
"""
|
|
51
|
+
Retrieve a model instance using its natural key.
|
|
52
|
+
|
|
53
|
+
Queries the database for an instance with a matching name, serving as the natural key.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
name: The natural key identifying the model instance.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The model instance matching the provided natural key.
|
|
60
|
+
"""
|
|
61
|
+
return self.get(name=name)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RequirementType(models.Model):
|
|
65
|
+
"""
|
|
66
|
+
A class representing a type of requirement.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
name (str): The name of the requirement type.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
name = models.CharField(max_length=100, unique=True)
|
|
73
|
+
description = models.TextField(blank=True, null=True)
|
|
74
|
+
|
|
75
|
+
objects = RequirementTypeManager()
|
|
76
|
+
|
|
77
|
+
def natural_key(self):
|
|
78
|
+
"""
|
|
79
|
+
Return the natural key for the instance as a tuple containing its name.
|
|
80
|
+
|
|
81
|
+
This tuple enables the use of natural key lookups for serialization and deserialization.
|
|
82
|
+
"""
|
|
83
|
+
return (self.name,)
|
|
84
|
+
|
|
85
|
+
def __str__(self):
|
|
86
|
+
"""Return the string representation of the requirement type's name.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
str: The name of the requirement type.
|
|
90
|
+
"""
|
|
91
|
+
return str(self.name)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class RequirementManager(models.Manager):
|
|
95
|
+
def get_by_natural_key(self, name):
|
|
96
|
+
"""
|
|
97
|
+
Retrieve an instance using its natural key.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
name: The natural key used to look up the instance.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
The object whose 'name' field matches the given key.
|
|
104
|
+
"""
|
|
105
|
+
return self.get(name=name)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class Requirement(models.Model):
|
|
109
|
+
"""
|
|
110
|
+
A class representing a requirement.
|
|
111
|
+
|
|
112
|
+
Attributes:
|
|
113
|
+
name (str): The name of the requirement.
|
|
114
|
+
description (str): A description of the requirement.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
name = models.CharField(max_length=100, unique=True)
|
|
118
|
+
description = models.TextField(blank=True, null=True)
|
|
119
|
+
|
|
120
|
+
operator_instructions = models.TextField(
|
|
121
|
+
help_text="semicolon-separated list of target attributes for the requirement",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def operator_instructions_parsed(self):
|
|
126
|
+
from endoreg_db.models.requirement.requirement_operator import (
|
|
127
|
+
RequirementOperator,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
instructions = RequirementOperator.parse_instructions(
|
|
131
|
+
self.operator_instructions
|
|
132
|
+
)
|
|
133
|
+
return instructions
|
|
134
|
+
|
|
135
|
+
numeric_value = models.FloatField(
|
|
136
|
+
blank=True,
|
|
137
|
+
null=True,
|
|
138
|
+
help_text="Numeric value for the requirement. ons.",
|
|
139
|
+
)
|
|
140
|
+
numeric_value_min = models.FloatField(
|
|
141
|
+
blank=True,
|
|
142
|
+
null=True,
|
|
143
|
+
help_text="Minimum numeric value for the requirement. ons.",
|
|
144
|
+
)
|
|
145
|
+
numeric_value_max = models.FloatField(
|
|
146
|
+
blank=True,
|
|
147
|
+
null=True,
|
|
148
|
+
help_text="Maximum numeric value for the requirement. ons.",
|
|
149
|
+
)
|
|
150
|
+
string_value = models.CharField(
|
|
151
|
+
max_length=100,
|
|
152
|
+
blank=True,
|
|
153
|
+
null=True,
|
|
154
|
+
help_text="String value for the requirement. ons.",
|
|
155
|
+
)
|
|
156
|
+
string_values = models.TextField(
|
|
157
|
+
blank=True,
|
|
158
|
+
null=True,
|
|
159
|
+
help_text=" ','-separated list of string values for the requirement.ons.",
|
|
160
|
+
)
|
|
161
|
+
objects = RequirementManager()
|
|
162
|
+
|
|
163
|
+
requirement_types = models.ManyToManyField(
|
|
164
|
+
"RequirementType",
|
|
165
|
+
blank=True,
|
|
166
|
+
related_name="linked_requirements",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
operator = models.ForeignKey(
|
|
170
|
+
"RequirementOperator",
|
|
171
|
+
on_delete=models.CASCADE,
|
|
172
|
+
related_name="required_in",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
unit = models.ForeignKey(
|
|
176
|
+
"Unit",
|
|
177
|
+
on_delete=models.CASCADE,
|
|
178
|
+
related_name="required_in",
|
|
179
|
+
blank=True,
|
|
180
|
+
null=True,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
examinations = models.ManyToManyField(
|
|
184
|
+
"Examination",
|
|
185
|
+
blank=True,
|
|
186
|
+
related_name="required_in",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
examination_indications = models.ManyToManyField(
|
|
190
|
+
"ExaminationIndication",
|
|
191
|
+
blank=True,
|
|
192
|
+
related_name="required_in",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
diseases = models.ManyToManyField(
|
|
196
|
+
"Disease",
|
|
197
|
+
blank=True,
|
|
198
|
+
related_name="required_in",
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
disease_classification_choices = models.ManyToManyField(
|
|
202
|
+
"DiseaseClassificationChoice",
|
|
203
|
+
blank=True,
|
|
204
|
+
related_name="required_in",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
events = models.ManyToManyField(
|
|
208
|
+
"Event",
|
|
209
|
+
blank=True,
|
|
210
|
+
related_name="required_in",
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
lab_values = models.ManyToManyField(
|
|
214
|
+
"LabValue",
|
|
215
|
+
blank=True,
|
|
216
|
+
related_name="required_in",
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
findings = models.ManyToManyField(
|
|
220
|
+
"Finding",
|
|
221
|
+
blank=True,
|
|
222
|
+
related_name="required_in",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
finding_classifications = models.ManyToManyField(
|
|
226
|
+
"FindingClassification",
|
|
227
|
+
blank=True,
|
|
228
|
+
related_name="required_in",
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
finding_classification_choices = models.ManyToManyField(
|
|
232
|
+
"FindingClassificationChoice",
|
|
233
|
+
blank=True,
|
|
234
|
+
related_name="required_in",
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
finding_interventions = models.ManyToManyField(
|
|
238
|
+
"FindingIntervention",
|
|
239
|
+
blank=True,
|
|
240
|
+
related_name="required_in",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
medications = models.ManyToManyField(
|
|
244
|
+
"Medication",
|
|
245
|
+
blank=True,
|
|
246
|
+
related_name="required_in",
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
medication_indications = models.ManyToManyField(
|
|
250
|
+
"MedicationIndication",
|
|
251
|
+
blank=True,
|
|
252
|
+
related_name="required_in",
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
medication_intake_times = models.ManyToManyField(
|
|
256
|
+
"MedicationIntakeTime",
|
|
257
|
+
blank=True,
|
|
258
|
+
related_name="required_in",
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
medication_schedules = models.ManyToManyField(
|
|
262
|
+
"MedicationSchedule",
|
|
263
|
+
blank=True,
|
|
264
|
+
related_name="required_in",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
genders = models.ManyToManyField(
|
|
268
|
+
"Gender",
|
|
269
|
+
blank=True,
|
|
270
|
+
related_name="required_in",
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
if TYPE_CHECKING:
|
|
274
|
+
requirement_types = cast(
|
|
275
|
+
models.manager.RelatedManager["RequirementType"], requirement_types
|
|
276
|
+
)
|
|
277
|
+
operator = models.ForeignKey["RequirementOperator"]
|
|
278
|
+
# requirement_sets = cast(models.manager.RelatedManager["RequirementSet"], requirement_sets)
|
|
279
|
+
examinations = cast(models.manager.RelatedManager["Examination"], examinations)
|
|
280
|
+
examination_indications = cast(
|
|
281
|
+
models.manager.RelatedManager["ExaminationIndication"],
|
|
282
|
+
examination_indications,
|
|
283
|
+
)
|
|
284
|
+
lab_values = cast(models.manager.RelatedManager["LabValue"], lab_values)
|
|
285
|
+
diseases = cast(models.manager.RelatedManager["Disease"], diseases)
|
|
286
|
+
disease_classification_choices = cast(
|
|
287
|
+
models.manager.RelatedManager["DiseaseClassificationChoice"],
|
|
288
|
+
disease_classification_choices,
|
|
289
|
+
)
|
|
290
|
+
events = cast(models.manager.RelatedManager["Event"], events)
|
|
291
|
+
findings = cast(models.manager.RelatedManager["Finding"], findings)
|
|
292
|
+
finding_classifications = cast(
|
|
293
|
+
models.manager.RelatedManager["FindingClassification"],
|
|
294
|
+
finding_classifications,
|
|
295
|
+
)
|
|
296
|
+
finding_classification_choices = cast(
|
|
297
|
+
models.manager.RelatedManager["FindingClassificationChoice"],
|
|
298
|
+
finding_classification_choices,
|
|
299
|
+
)
|
|
300
|
+
finding_interventions = cast(
|
|
301
|
+
models.manager.RelatedManager["FindingIntervention"], finding_interventions
|
|
302
|
+
)
|
|
303
|
+
medications = cast(models.manager.RelatedManager["Medication"], medications)
|
|
304
|
+
medication_indications = cast(
|
|
305
|
+
models.manager.RelatedManager["MedicationIndication"],
|
|
306
|
+
medication_indications,
|
|
307
|
+
)
|
|
308
|
+
medication_intake_times = cast(
|
|
309
|
+
models.manager.RelatedManager["MedicationIntakeTime"],
|
|
310
|
+
medication_intake_times,
|
|
311
|
+
)
|
|
312
|
+
medication_schedules = cast(
|
|
313
|
+
models.manager.RelatedManager["MedicationSchedule"], medication_schedules
|
|
314
|
+
)
|
|
315
|
+
genders = cast(models.manager.RelatedManager["Gender"], genders)
|
|
316
|
+
|
|
317
|
+
def natural_key(self):
|
|
318
|
+
"""
|
|
319
|
+
Returns a tuple containing the instance's name as its natural key.
|
|
320
|
+
|
|
321
|
+
This tuple provides a unique identifier for serialization purposes.
|
|
322
|
+
"""
|
|
323
|
+
return (self.name,)
|
|
324
|
+
|
|
325
|
+
def __str__(self):
|
|
326
|
+
"""Returns the name of the requirement as its string representation."""
|
|
327
|
+
return str(self.name)
|
|
328
|
+
|
|
329
|
+
@property
|
|
330
|
+
def expected_models(
|
|
331
|
+
self,
|
|
332
|
+
) -> List[
|
|
333
|
+
Union[
|
|
334
|
+
"Disease",
|
|
335
|
+
"DiseaseClassificationChoice",
|
|
336
|
+
"Event",
|
|
337
|
+
"EventClassification",
|
|
338
|
+
"EventClassificationChoice",
|
|
339
|
+
"Examination",
|
|
340
|
+
"ExaminationIndication",
|
|
341
|
+
"Finding",
|
|
342
|
+
"FindingIntervention",
|
|
343
|
+
"FindingClassification",
|
|
344
|
+
"FindingClassificationChoice",
|
|
345
|
+
"FindingClassificationType",
|
|
346
|
+
"LabValue",
|
|
347
|
+
"Medication",
|
|
348
|
+
"MedicationIndication",
|
|
349
|
+
"MedicationIntakeTime", # Added MedicationIntakeTime
|
|
350
|
+
"PatientDisease",
|
|
351
|
+
"PatientEvent",
|
|
352
|
+
"PatientExamination",
|
|
353
|
+
"PatientFinding",
|
|
354
|
+
"PatientFindingIntervention",
|
|
355
|
+
"PatientFindingClassification",
|
|
356
|
+
"PatientLabValue",
|
|
357
|
+
"PatientMedicationSchedule", # Added PatientMedicationSchedule
|
|
358
|
+
]
|
|
359
|
+
]:
|
|
360
|
+
"""
|
|
361
|
+
Return the list of model classes that are expected as input for evaluating this requirement.
|
|
362
|
+
|
|
363
|
+
The returned models correspond to the requirement types linked to this requirement, mapped via the internal data model dictionary.
|
|
364
|
+
"""
|
|
365
|
+
req_types = self.requirement_types.all()
|
|
366
|
+
req_type_names = [_.name for _ in req_types]
|
|
367
|
+
|
|
368
|
+
expected_models = [self.data_model_dict[_] for _ in req_type_names]
|
|
369
|
+
# e.g. [PatientExamination, PatientFinding]
|
|
370
|
+
return expected_models
|
|
371
|
+
|
|
372
|
+
@property
|
|
373
|
+
def links(self) -> "RequirementLinks":
|
|
374
|
+
"""
|
|
375
|
+
Return a RequirementLinks object containing all non-null related model instances for this requirement.
|
|
376
|
+
|
|
377
|
+
The returned object provides structured access to all associated entities, such as examinations, diseases, findings, classifications, interventions, medications, and related choices, aggregated from the requirement's many-to-many fields.
|
|
378
|
+
"""
|
|
379
|
+
# requirement_sets is not part of RequirementLinks (avoids circular import); collect other related models
|
|
380
|
+
models_dict = RequirementLinks(
|
|
381
|
+
examinations=[_ for _ in self.examinations.all() if _ is not None],
|
|
382
|
+
examination_indications=[
|
|
383
|
+
_ for _ in self.examination_indications.all() if _ is not None
|
|
384
|
+
],
|
|
385
|
+
lab_values=[_ for _ in self.lab_values.all() if _ is not None],
|
|
386
|
+
diseases=[_ for _ in self.diseases.all() if _ is not None],
|
|
387
|
+
disease_classification_choices=[
|
|
388
|
+
_ for _ in self.disease_classification_choices.all() if _ is not None
|
|
389
|
+
],
|
|
390
|
+
events=[_ for _ in self.events.all() if _ is not None],
|
|
391
|
+
findings=[_ for _ in self.findings.all() if _ is not None],
|
|
392
|
+
finding_classifications=[
|
|
393
|
+
_ for _ in self.finding_classifications.all() if _ is not None
|
|
394
|
+
],
|
|
395
|
+
finding_classification_choices=[
|
|
396
|
+
_ for _ in self.finding_classification_choices.all() if _ is not None
|
|
397
|
+
],
|
|
398
|
+
finding_interventions=[
|
|
399
|
+
_ for _ in self.finding_interventions.all() if _ is not None
|
|
400
|
+
],
|
|
401
|
+
medications=[_ for _ in self.medications.all() if _ is not None],
|
|
402
|
+
medication_indications=[
|
|
403
|
+
_ for _ in self.medication_indications.all() if _ is not None
|
|
404
|
+
],
|
|
405
|
+
medication_intake_times=[
|
|
406
|
+
_ for _ in self.medication_intake_times.all() if _ is not None
|
|
407
|
+
],
|
|
408
|
+
)
|
|
409
|
+
return models_dict
|
|
410
|
+
|
|
411
|
+
@property
|
|
412
|
+
def data_model_dict(self) -> dict:
|
|
413
|
+
"""
|
|
414
|
+
Provides a mapping from requirement type names to their corresponding model classes.
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
A dictionary where keys are requirement type names and values are model classes used for requirement evaluation.
|
|
418
|
+
"""
|
|
419
|
+
from .requirement_evaluation.requirement_type_parser import data_model_dict
|
|
420
|
+
|
|
421
|
+
return data_model_dict
|
|
422
|
+
|
|
423
|
+
@property
|
|
424
|
+
def active_links(self) -> Dict[str, List]:
|
|
425
|
+
"""Returns a dictionary of linked models containing only non-empty entries.
|
|
426
|
+
|
|
427
|
+
The returned dictionary includes only those related model lists that have at least one linked instance.
|
|
428
|
+
"""
|
|
429
|
+
return self.links.active()
|
|
430
|
+
|
|
431
|
+
def evaluate(self, input_obj):
|
|
432
|
+
"""
|
|
433
|
+
Evaluates whether the requirement is satisfied for the given input models using linked operators and gender constraints.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
*args: Instances or QuerySets of expected model classes to be evaluated. Each must have a `.links` property returning a `RequirementLinks` object.
|
|
437
|
+
mode: Evaluation mode; "strict" requires all operators to pass, "loose" requires any operator to pass.
|
|
438
|
+
**kwargs: Additional keyword arguments passed to operator evaluations.
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
True if the requirement is satisfied according to the specified mode, linked operators, and gender restrictions; otherwise, False.
|
|
442
|
+
|
|
443
|
+
Raises:
|
|
444
|
+
ValueError: If an invalid mode is provided.
|
|
445
|
+
TypeError: If an input is not an instance or QuerySet of expected models, or lacks a valid `.links` attribute.
|
|
446
|
+
|
|
447
|
+
If the requirement specifies genders, only input containing a patient with a matching gender will be considered valid for evaluation.
|
|
448
|
+
"""
|
|
449
|
+
is_valid: bool = False
|
|
450
|
+
|
|
451
|
+
requirement_req_links = self.active_links
|
|
452
|
+
|
|
453
|
+
# expected_models = self.expected_models
|
|
454
|
+
|
|
455
|
+
operator = self.operator
|
|
456
|
+
assert isinstance(operator, RequirementOperator)
|
|
457
|
+
|
|
458
|
+
operator_instructions = self.operator_instructions_parsed
|
|
459
|
+
|
|
460
|
+
is_valid = operator.evaluate(input_links)
|
|
461
|
+
|
|
462
|
+
return is_valid
|
|
463
|
+
|
|
464
|
+
def evaluate_with_details(self, *args, mode: str, **kwargs) -> Tuple[bool, str]:
|
|
465
|
+
"""
|
|
466
|
+
Evaluates whether the requirement is satisfied for the given input models using linked operators and gender constraints.
|
|
467
|
+
|
|
468
|
+
Args:
|
|
469
|
+
*args: Instances or QuerySets of expected model classes to be evaluated. Each must have a `.links` property returning a `RequirementLinks` object.
|
|
470
|
+
mode: Evaluation mode; "strict" requires all operators to pass, "loose" requires any operator to pass.
|
|
471
|
+
**kwargs: Additional keyword arguments passed to operator evaluations.
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
(met, details):
|
|
475
|
+
met: True/False, ob die Voraussetzung erfüllt ist
|
|
476
|
+
details: menschenlesbare Erklärung (für UI geeignet)
|
|
477
|
+
|
|
478
|
+
Raises:
|
|
479
|
+
RequirementEvaluationError:
|
|
480
|
+
- bei ungültigem Modus
|
|
481
|
+
- bei komplett falschen Input-Typen / fehlender .links-Struktur
|
|
482
|
+
"""
|
|
483
|
+
from endoreg_db.models.requirement.requirement_error import (
|
|
484
|
+
RequirementEvaluationError,
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
# --- Mode validieren -------------------------------------------------
|
|
488
|
+
if mode not in ["strict", "loose"]:
|
|
489
|
+
raise RequirementEvaluationError(
|
|
490
|
+
requirement=self,
|
|
491
|
+
code="INVALID_MODE",
|
|
492
|
+
technical_message=f"Invalid mode: {mode}. Use 'strict' or 'loose'.",
|
|
493
|
+
user_message=(
|
|
494
|
+
"Diese Voraussetzung ist intern mit einem ungültigen Bewertungsmodus konfiguriert und kann aktuell nicht korrekt geprüft werden."
|
|
495
|
+
),
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
evaluate_result_list_func = all if mode == "strict" else any
|
|
499
|
+
|
|
500
|
+
requirement_req_links = self.links
|
|
501
|
+
expected_models = self.expected_models
|
|
502
|
+
|
|
503
|
+
operators = list(self.operators.all())
|
|
504
|
+
has_operators = bool(operators)
|
|
505
|
+
requirement_has_conditions = bool(requirement_req_links.active())
|
|
506
|
+
queryset_mode, queryset_min_count = self._resolve_queryset_config(kwargs)
|
|
507
|
+
|
|
508
|
+
# --- Helper für Typprüfung ------------------------------------------
|
|
509
|
+
def _is_expected_instance(obj) -> bool:
|
|
510
|
+
for cls in expected_models:
|
|
511
|
+
if isinstance(cls, type):
|
|
512
|
+
try:
|
|
513
|
+
if isinstance(obj, cls):
|
|
514
|
+
return True
|
|
515
|
+
except Exception:
|
|
516
|
+
# cls might nicht runtime-kompatibel sein
|
|
517
|
+
continue
|
|
518
|
+
return False
|
|
519
|
+
|
|
520
|
+
def _is_queryset_of_expected(qs) -> bool:
|
|
521
|
+
if not isinstance(qs, models.QuerySet) or not hasattr(qs, "model"):
|
|
522
|
+
return False
|
|
523
|
+
for cls in expected_models:
|
|
524
|
+
if isinstance(cls, type):
|
|
525
|
+
try:
|
|
526
|
+
if issubclass(qs.model, cls):
|
|
527
|
+
return True
|
|
528
|
+
except Exception:
|
|
529
|
+
continue
|
|
530
|
+
return False
|
|
531
|
+
|
|
532
|
+
# --- RequirementLinks aus allen Inputs aggregieren -------------------
|
|
533
|
+
aggregated_input_links_data: dict = {}
|
|
534
|
+
processed_inputs_count = 0
|
|
535
|
+
|
|
536
|
+
for _input in args:
|
|
537
|
+
if not _is_expected_instance(_input):
|
|
538
|
+
# QuerySet von erwarteten Typen erlauben
|
|
539
|
+
if _is_queryset_of_expected(_input):
|
|
540
|
+
if not _input.exists():
|
|
541
|
+
# leeres QS -> je nach QS-Mode sofort nicht erfüllt
|
|
542
|
+
if queryset_mode == "all":
|
|
543
|
+
return (
|
|
544
|
+
False,
|
|
545
|
+
"Für diese Voraussetzung müssen alle passenden Einträge vorliegen, aber es wurden keine entsprechenden Datensätze gefunden.",
|
|
546
|
+
)
|
|
547
|
+
if queryset_mode == "min_count":
|
|
548
|
+
required = (
|
|
549
|
+
queryset_min_count
|
|
550
|
+
if queryset_min_count is not None
|
|
551
|
+
else 1
|
|
552
|
+
)
|
|
553
|
+
if required > 0:
|
|
554
|
+
return (
|
|
555
|
+
False,
|
|
556
|
+
f"Für diese Voraussetzung werden mindestens {required} passende Einträge benötigt, es wurden jedoch keine gefunden.",
|
|
557
|
+
)
|
|
558
|
+
# queryset_mode == "any" bei leerem QS -> neutral (keine zusätzliche Einschränkung)
|
|
559
|
+
continue
|
|
560
|
+
|
|
561
|
+
queryset_results: List[bool] = []
|
|
562
|
+
queryset_true_count = 0
|
|
563
|
+
queryset_item_count = 0
|
|
564
|
+
|
|
565
|
+
for item in _input:
|
|
566
|
+
if not hasattr(item, "links") or not isinstance(
|
|
567
|
+
item.links, RequirementLinks
|
|
568
|
+
):
|
|
569
|
+
raise RequirementEvaluationError(
|
|
570
|
+
requirement=self,
|
|
571
|
+
code="MISSING_LINKS_ATTR",
|
|
572
|
+
technical_message=(
|
|
573
|
+
f"Item {item} of type {type(item)} in QuerySet does not have a valid .links attribute of type RequirementLinks."
|
|
574
|
+
),
|
|
575
|
+
user_message=(
|
|
576
|
+
"Für einen Datensatz fehlen die intern benötigten Verknüpfungen, "
|
|
577
|
+
"sodass diese Voraussetzung nicht korrekt geprüft werden kann."
|
|
578
|
+
),
|
|
579
|
+
meta={"item_type": str(type(item))},
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
item_active_links = item.links.active()
|
|
583
|
+
item_input_links = RequirementLinks(**item_active_links)
|
|
584
|
+
|
|
585
|
+
# Links sammeln
|
|
586
|
+
for link_key, link_list in item_active_links.items():
|
|
587
|
+
if link_key not in aggregated_input_links_data:
|
|
588
|
+
aggregated_input_links_data[link_key] = []
|
|
589
|
+
aggregated_input_links_data[link_key].extend(link_list)
|
|
590
|
+
|
|
591
|
+
per_item_args = tuple(
|
|
592
|
+
item if arg is _input else arg for arg in args
|
|
593
|
+
)
|
|
594
|
+
op_kwargs = kwargs.copy()
|
|
595
|
+
op_kwargs["requirement"] = self
|
|
596
|
+
op_kwargs["original_input_args"] = per_item_args
|
|
597
|
+
|
|
598
|
+
if has_operators:
|
|
599
|
+
item_operator_results: List[bool] = []
|
|
600
|
+
for operator in operators:
|
|
601
|
+
try:
|
|
602
|
+
operator_result = operator.evaluate(
|
|
603
|
+
requirement_links=requirement_req_links,
|
|
604
|
+
input_links=item_input_links,
|
|
605
|
+
**op_kwargs,
|
|
606
|
+
)
|
|
607
|
+
item_operator_results.append(operator_result)
|
|
608
|
+
except Exception as exc:
|
|
609
|
+
logger.debug(
|
|
610
|
+
"Operator %s evaluation failed for item %s: %s",
|
|
611
|
+
getattr(operator, "name", "unknown"),
|
|
612
|
+
item,
|
|
613
|
+
exc,
|
|
614
|
+
)
|
|
615
|
+
item_operator_results.append(False)
|
|
616
|
+
item_result = (
|
|
617
|
+
evaluate_result_list_func(item_operator_results)
|
|
618
|
+
if item_operator_results
|
|
619
|
+
else True
|
|
620
|
+
)
|
|
621
|
+
else:
|
|
622
|
+
# keine Operatoren -> Bedingung erfüllt, wenn Requirement selbst keine Bedingungen hat
|
|
623
|
+
item_result = not requirement_has_conditions
|
|
624
|
+
|
|
625
|
+
queryset_results.append(item_result)
|
|
626
|
+
if item_result:
|
|
627
|
+
queryset_true_count += 1
|
|
628
|
+
queryset_item_count += 1
|
|
629
|
+
processed_inputs_count += 1
|
|
630
|
+
|
|
631
|
+
# QS-Modus nach Auswertung anwenden
|
|
632
|
+
if queryset_mode == "all":
|
|
633
|
+
if queryset_item_count == 0 or not all(queryset_results):
|
|
634
|
+
return (
|
|
635
|
+
False,
|
|
636
|
+
"Für diese Voraussetzung müssen alle relevanten Einträge die Bedingung erfüllen.",
|
|
637
|
+
)
|
|
638
|
+
elif queryset_mode == "min_count":
|
|
639
|
+
required = (
|
|
640
|
+
queryset_min_count if queryset_min_count is not None else 1
|
|
641
|
+
)
|
|
642
|
+
if queryset_true_count < max(required, 0):
|
|
643
|
+
return (
|
|
644
|
+
False,
|
|
645
|
+
f"Für diese Voraussetzung werden mindestens {max(required, 0)} passende Einträge benötigt (gefunden: {queryset_true_count}).",
|
|
646
|
+
)
|
|
647
|
+
# queryset_mode == "any": keine zusätzliche Einschränkung
|
|
648
|
+
continue
|
|
649
|
+
|
|
650
|
+
# Weder Instanz noch QS eines erwarteten Modells -> Konfig-/Aufruf-Fehler
|
|
651
|
+
raise RequirementEvaluationError(
|
|
652
|
+
requirement=self,
|
|
653
|
+
code="INVALID_INPUT_TYPE",
|
|
654
|
+
technical_message=(
|
|
655
|
+
f"Input type {type(_input)} is not among expected models: {self.expected_models} nor a QuerySet of expected models."
|
|
656
|
+
),
|
|
657
|
+
user_message=(
|
|
658
|
+
"Diese Voraussetzung wurde mit einem nicht passenden Datentyp aufgerufen und kann aktuell nicht korrekt geprüft werden."
|
|
659
|
+
),
|
|
660
|
+
meta={"input_type": str(type(_input))},
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
# Einzelinstanz erwarteten Typs
|
|
664
|
+
if not hasattr(_input, "links") or not isinstance(
|
|
665
|
+
_input.links, RequirementLinks
|
|
666
|
+
):
|
|
667
|
+
raise RequirementEvaluationError(
|
|
668
|
+
requirement=self,
|
|
669
|
+
code="MISSING_LINKS_ATTR",
|
|
670
|
+
technical_message=(
|
|
671
|
+
f"Input {_input} of type {type(_input)} does not have a valid .links attribute of type RequirementLinks."
|
|
672
|
+
),
|
|
673
|
+
user_message=(
|
|
674
|
+
"Für die Auswertung dieser Voraussetzung fehlen die intern benötigten Verknüpfungsinformationen."
|
|
675
|
+
),
|
|
676
|
+
meta={"input_type": str(type(_input))},
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
active_input_links = _input.links.active()
|
|
680
|
+
for link_key, link_list in active_input_links.items():
|
|
681
|
+
if link_key not in aggregated_input_links_data:
|
|
682
|
+
aggregated_input_links_data[link_key] = []
|
|
683
|
+
aggregated_input_links_data[link_key].extend(link_list)
|
|
684
|
+
processed_inputs_count += 1
|
|
685
|
+
|
|
686
|
+
# Wenn es zwar *args gibt, aber alles leer/irrelevant war, lassen wir das weiterlaufen.
|
|
687
|
+
# Operatoren sehen dann ggf. ein leeres final_input_links.
|
|
688
|
+
|
|
689
|
+
# Deduplizieren der aggregierten Links
|
|
690
|
+
for key in aggregated_input_links_data:
|
|
691
|
+
try:
|
|
692
|
+
aggregated_input_links_data[key] = list(
|
|
693
|
+
dict.fromkeys(aggregated_input_links_data[key])
|
|
694
|
+
)
|
|
695
|
+
except TypeError:
|
|
696
|
+
# Fallback für nicht-hashbare Items
|
|
697
|
+
tmp: list = []
|
|
698
|
+
for item in aggregated_input_links_data[key]:
|
|
699
|
+
if item not in tmp:
|
|
700
|
+
tmp.append(item)
|
|
701
|
+
aggregated_input_links_data[key] = tmp
|
|
702
|
+
|
|
703
|
+
final_input_links = RequirementLinks(**aggregated_input_links_data)
|
|
704
|
+
|
|
705
|
+
# --- Gender-Check ----------------------------------------------------
|
|
706
|
+
genders_exist = self.genders.exists()
|
|
707
|
+
if genders_exist:
|
|
708
|
+
from endoreg_db.models.administration.person.patient import Patient
|
|
709
|
+
|
|
710
|
+
patient = None
|
|
711
|
+
for arg in args:
|
|
712
|
+
if isinstance(arg, Patient):
|
|
713
|
+
patient = arg
|
|
714
|
+
break
|
|
715
|
+
|
|
716
|
+
if patient is None or patient.gender is None:
|
|
717
|
+
return (
|
|
718
|
+
False,
|
|
719
|
+
"Für diese Voraussetzung ist ein hinterlegtes Geschlecht des Patienten erforderlich.",
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
if not self.genders.filter(pk=patient.gender.pk).exists():
|
|
723
|
+
return (
|
|
724
|
+
False,
|
|
725
|
+
"Diese Voraussetzung gilt nur für bestimmte Geschlechter und ist für diesen Patienten nicht erfüllt.",
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
# --- Fall: keine Operatoren -----------------------------------------
|
|
729
|
+
if not has_operators:
|
|
730
|
+
if not requirement_has_conditions:
|
|
731
|
+
return True, "Keine Operatoren für die Bewertung erforderlich."
|
|
732
|
+
return (
|
|
733
|
+
False,
|
|
734
|
+
"Die Voraussetzung besitzt Bedingungen, aber keinen Operator zur Auswertung.",
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
# --- Operatoren anwenden --------------------------------------------
|
|
738
|
+
operator_results: List[bool] = []
|
|
739
|
+
operator_details: List[str] = []
|
|
740
|
+
|
|
741
|
+
for operator in operators:
|
|
742
|
+
op_kwargs = kwargs.copy()
|
|
743
|
+
op_kwargs["requirement"] = self
|
|
744
|
+
op_kwargs["original_input_args"] = args
|
|
745
|
+
|
|
746
|
+
try:
|
|
747
|
+
operator_result = operator.evaluate(
|
|
748
|
+
requirement_links=requirement_req_links,
|
|
749
|
+
input_links=final_input_links,
|
|
750
|
+
**op_kwargs,
|
|
751
|
+
)
|
|
752
|
+
operator_results.append(operator_result)
|
|
753
|
+
operator_details.append(
|
|
754
|
+
f"{operator.name}: {'erfüllt' if operator_result else 'nicht erfüllt'}"
|
|
755
|
+
)
|
|
756
|
+
except Exception as e:
|
|
757
|
+
operator_results.append(False)
|
|
758
|
+
operator_details.append(f"{operator.name}: technischer Fehler ({e})")
|
|
759
|
+
logger.debug(
|
|
760
|
+
"Operator %s evaluation failed for requirement %s: %s",
|
|
761
|
+
getattr(operator, "name", "unknown"),
|
|
762
|
+
getattr(self, "name", "unknown"),
|
|
763
|
+
e,
|
|
764
|
+
)
|
|
765
|
+
|
|
766
|
+
is_valid = evaluate_result_list_func(operator_results)
|
|
767
|
+
|
|
768
|
+
# --- Detailtext bauen -----------------------------------------------
|
|
769
|
+
if not operator_results:
|
|
770
|
+
details = "Keine Operatoren für die Bewertung verfügbar."
|
|
771
|
+
elif len(operator_results) == 1:
|
|
772
|
+
details = operator_details[0]
|
|
773
|
+
else:
|
|
774
|
+
failed_details = [
|
|
775
|
+
detail
|
|
776
|
+
for detail, result in zip(operator_details, operator_results)
|
|
777
|
+
if not result
|
|
778
|
+
]
|
|
779
|
+
if failed_details:
|
|
780
|
+
details = "; ".join(failed_details)
|
|
781
|
+
else:
|
|
782
|
+
details = "Alle verknüpften Bedingungen sind erfüllt."
|
|
783
|
+
|
|
784
|
+
# Arbeitsverzeichnis als Debug-Helfer anhängen (optional)
|
|
785
|
+
try:
|
|
786
|
+
cwd = run("pwd", capture_output=True, text=True).stdout.strip()
|
|
787
|
+
details = f"{details}\ncwd: {cwd}"
|
|
788
|
+
except Exception:
|
|
789
|
+
# nicht kritisch
|
|
790
|
+
pass
|
|
791
|
+
|
|
792
|
+
return bool(is_valid), details
|