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,380 @@
|
|
|
1
|
+
# api/viewsets/lookup.py
|
|
2
|
+
import logging
|
|
3
|
+
from ast import literal_eval
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
|
|
6
|
+
from django.core.cache import cache
|
|
7
|
+
from rest_framework import status, viewsets
|
|
8
|
+
from rest_framework.decorators import action
|
|
9
|
+
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
|
|
10
|
+
from rest_framework.response import Response
|
|
11
|
+
|
|
12
|
+
# Use module import so tests can monkeypatch functions on the module
|
|
13
|
+
from endoreg_db.services import lookup_service as ls
|
|
14
|
+
from endoreg_db.services.lookup_store import DEFAULT_TTL_SECONDS, LookupStore
|
|
15
|
+
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
16
|
+
from endoreg_db.models.other.tag import Tag
|
|
17
|
+
|
|
18
|
+
ORIGIN_MAP_PREFIX = "lookup:origin:"
|
|
19
|
+
ISSUED_MAP_PREFIX = "lookup:issued_for_internal:"
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LookupViewSet(viewsets.ViewSet):
|
|
25
|
+
"""
|
|
26
|
+
Django REST Framework ViewSet for managing lookup sessions.
|
|
27
|
+
|
|
28
|
+
This ViewSet provides REST API endpoints for the lookup system, which
|
|
29
|
+
evaluates medical examination requirements against patient data. It uses
|
|
30
|
+
token-based sessions stored in Django cache to maintain state across
|
|
31
|
+
multiple client requests.
|
|
32
|
+
|
|
33
|
+
Key features:
|
|
34
|
+
- Session initialization with patient examination data
|
|
35
|
+
- Retrieval of lookup data by token
|
|
36
|
+
- Partial updates to session data with automatic recomputation
|
|
37
|
+
- Manual recomputation of derived data
|
|
38
|
+
- Automatic session recovery for expired tokens
|
|
39
|
+
|
|
40
|
+
The API supports both internal service tokens and public client tokens,
|
|
41
|
+
with origin mapping to enable session restart functionality.
|
|
42
|
+
|
|
43
|
+
Endpoints:
|
|
44
|
+
- POST /init: Initialize new lookup session
|
|
45
|
+
- GET /{token}/all: Retrieve complete session data
|
|
46
|
+
- GET/PATCH /{token}/parts: Get/update partial session data
|
|
47
|
+
- POST /{token}/recompute: Manually trigger recomputation
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
permission_classes = [EnvironmentAwarePermission]
|
|
51
|
+
parser_classes = (JSONParser, FormParser, MultiPartParser)
|
|
52
|
+
INPUT_KEYS = {
|
|
53
|
+
"patient_examination_id",
|
|
54
|
+
"selectedRequirementSetIds",
|
|
55
|
+
"selectedChoices",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
user_tags = Tag
|
|
59
|
+
|
|
60
|
+
@action(detail=False, methods=["post"])
|
|
61
|
+
def init(self, request):
|
|
62
|
+
"""
|
|
63
|
+
Initialize a new lookup session for a patient examination.
|
|
64
|
+
|
|
65
|
+
Creates a new token-based session containing initial lookup data
|
|
66
|
+
for the specified patient examination. Handles malformed payloads
|
|
67
|
+
and supports multiple initialization requests for the same examination
|
|
68
|
+
by issuing fresh public tokens while maintaining internal state.
|
|
69
|
+
|
|
70
|
+
Request body:
|
|
71
|
+
patient_examination_id: Integer ID of the patient examination
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
JSON response with session token
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
400: Invalid patient_examination_id or creation failure
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
debug_data = getattr(request, "data", None)
|
|
81
|
+
raw_post = getattr(getattr(request, "_request", None), "POST", None)
|
|
82
|
+
body_preview = None
|
|
83
|
+
try:
|
|
84
|
+
body = getattr(getattr(request, "_request", None), "body", b"")
|
|
85
|
+
body_preview = body[:200]
|
|
86
|
+
|
|
87
|
+
except Exception:
|
|
88
|
+
body_preview = None
|
|
89
|
+
logger.debug(
|
|
90
|
+
"lookup.init incoming: data=%r POST=%r body[:200]=%r",
|
|
91
|
+
debug_data,
|
|
92
|
+
raw_post,
|
|
93
|
+
body_preview,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
except Exception:
|
|
97
|
+
pass
|
|
98
|
+
# Prefer DRF data
|
|
99
|
+
raw_pe = (
|
|
100
|
+
request.data.get("patient_examination_id")
|
|
101
|
+
if hasattr(request, "data")
|
|
102
|
+
else None
|
|
103
|
+
)
|
|
104
|
+
# Fallback: parse malformed form payload where the entire dict was sent as a single key string
|
|
105
|
+
|
|
106
|
+
if raw_pe is None:
|
|
107
|
+
for candidate in (
|
|
108
|
+
getattr(getattr(request, "_request", None), "POST", None),
|
|
109
|
+
request.data if hasattr(request, "data") else None,
|
|
110
|
+
):
|
|
111
|
+
try:
|
|
112
|
+
if isinstance(candidate, Mapping) and len(candidate.keys()) == 1:
|
|
113
|
+
only_key = next(iter(candidate.keys()))
|
|
114
|
+
if (
|
|
115
|
+
isinstance(only_key, str)
|
|
116
|
+
and only_key.startswith("{")
|
|
117
|
+
and only_key.endswith("}")
|
|
118
|
+
):
|
|
119
|
+
try:
|
|
120
|
+
parsed = literal_eval(only_key)
|
|
121
|
+
if (
|
|
122
|
+
isinstance(parsed, dict)
|
|
123
|
+
and "patient_examination_id" in parsed
|
|
124
|
+
):
|
|
125
|
+
raw_pe = parsed.get("patient_examination_id")
|
|
126
|
+
logger.debug(
|
|
127
|
+
"lookup.init recovered pe_id from malformed payload: %r",
|
|
128
|
+
raw_pe,
|
|
129
|
+
)
|
|
130
|
+
break
|
|
131
|
+
|
|
132
|
+
except Exception:
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
except Exception:
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
user_tags = request.data.get("user_tags", None)
|
|
139
|
+
if user_tags and not isinstance(user_tags, list):
|
|
140
|
+
user_tags = [user_tags]
|
|
141
|
+
# Fallback to query params
|
|
142
|
+
if raw_pe is None:
|
|
143
|
+
raw_pe = request.query_params.get("patient_examination_id")
|
|
144
|
+
|
|
145
|
+
logger.debug("lookup.init raw_pe=%r type=%s", raw_pe, type(raw_pe))
|
|
146
|
+
|
|
147
|
+
# Normalize potential list/tuple inputs (e.g., from form submissions)
|
|
148
|
+
if isinstance(raw_pe, (list, tuple)):
|
|
149
|
+
raw_pe = raw_pe[0] if raw_pe else None
|
|
150
|
+
|
|
151
|
+
if raw_pe in (None, ""):
|
|
152
|
+
return Response(
|
|
153
|
+
{"detail": "patient_examination_id must be an integer"},
|
|
154
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Coerce to int robustly
|
|
158
|
+
try:
|
|
159
|
+
pe_id = int(str(raw_pe))
|
|
160
|
+
|
|
161
|
+
except (TypeError, ValueError):
|
|
162
|
+
logger.warning("lookup.init failed to int() raw_pe=%r", raw_pe)
|
|
163
|
+
return Response(
|
|
164
|
+
{"detail": "patient_examination_id must be an integer"},
|
|
165
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
if pe_id <= 0:
|
|
169
|
+
return Response(
|
|
170
|
+
{"detail": "patient_examination_id must be positive"},
|
|
171
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
# Create internal session via service (may seed its own token/cache)
|
|
176
|
+
service_kwargs = {}
|
|
177
|
+
if user_tags:
|
|
178
|
+
service_kwargs["user_tags"] = user_tags
|
|
179
|
+
|
|
180
|
+
internal_token = ls.create_lookup_token_for_pe(pe_id, **service_kwargs)
|
|
181
|
+
internal_data = LookupStore(token=internal_token).get_all()
|
|
182
|
+
|
|
183
|
+
issued_key = f"{ISSUED_MAP_PREFIX}{internal_token}"
|
|
184
|
+
|
|
185
|
+
issued_count = cache.get(issued_key, 0)
|
|
186
|
+
|
|
187
|
+
if issued_count == 0:
|
|
188
|
+
# First issuance: return the service token directly
|
|
189
|
+
|
|
190
|
+
token_to_return = internal_token
|
|
191
|
+
|
|
192
|
+
cache.set(issued_key, 1, DEFAULT_TTL_SECONDS)
|
|
193
|
+
|
|
194
|
+
else:
|
|
195
|
+
# Subsequent inits for same internal token: issue a fresh public token seeded with internal data
|
|
196
|
+
|
|
197
|
+
public_store = LookupStore()
|
|
198
|
+
|
|
199
|
+
token_to_return = public_store.init(
|
|
200
|
+
initial=internal_data, ttl=DEFAULT_TTL_SECONDS
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
cache.set(issued_key, issued_count + 1, DEFAULT_TTL_SECONDS)
|
|
204
|
+
|
|
205
|
+
# Persist origin mapping so we can restart expired sessions
|
|
206
|
+
|
|
207
|
+
cache.set(
|
|
208
|
+
f"{ORIGIN_MAP_PREFIX}{token_to_return}", pe_id, DEFAULT_TTL_SECONDS
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
213
|
+
|
|
214
|
+
return Response({"token": token_to_return}, status=status.HTTP_201_CREATED)
|
|
215
|
+
|
|
216
|
+
@action(detail=True, methods=["get"], url_path="all")
|
|
217
|
+
def get_all(self, request, pk=None):
|
|
218
|
+
"""
|
|
219
|
+
Retrieve complete lookup data for a session token.
|
|
220
|
+
|
|
221
|
+
Returns all stored data for the given token. If data is not found,
|
|
222
|
+
attempts automatic session recovery using persisted origin mapping.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
pk: Session token
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Complete lookup data dictionary
|
|
229
|
+
|
|
230
|
+
Raises:
|
|
231
|
+
404: Token not found and recovery failed
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
if not pk:
|
|
235
|
+
return Response(
|
|
236
|
+
{"detail": "Token required"}, status=status.HTTP_404_NOT_FOUND
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
store = LookupStore(token=pk)
|
|
240
|
+
|
|
241
|
+
try:
|
|
242
|
+
validated_data = store.validate_and_recover_data(pk)
|
|
243
|
+
|
|
244
|
+
except Exception:
|
|
245
|
+
validated_data = None
|
|
246
|
+
|
|
247
|
+
if validated_data is None:
|
|
248
|
+
# Try automatic restart once using persisted origin mapping
|
|
249
|
+
|
|
250
|
+
pe_id = cache.get(f"{ORIGIN_MAP_PREFIX}{pk}")
|
|
251
|
+
|
|
252
|
+
if pe_id:
|
|
253
|
+
try:
|
|
254
|
+
internal_token = ls.create_lookup_token_for_pe(int(pe_id))
|
|
255
|
+
|
|
256
|
+
new_data = LookupStore(token=internal_token).get_all()
|
|
257
|
+
|
|
258
|
+
if not new_data:
|
|
259
|
+
return Response(
|
|
260
|
+
{
|
|
261
|
+
"error": "Lookup data not available after restart",
|
|
262
|
+
"token": pk,
|
|
263
|
+
},
|
|
264
|
+
status=status.HTTP_404_NOT_FOUND,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# Hydrate the original token with recovered data and refresh origin TTL
|
|
268
|
+
store.set_many(new_data)
|
|
269
|
+
cache.set(f"{ORIGIN_MAP_PREFIX}{pk}", pe_id, DEFAULT_TTL_SECONDS)
|
|
270
|
+
return Response(store.get_all(), status=status.HTTP_200_OK)
|
|
271
|
+
|
|
272
|
+
except Exception:
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
return Response(
|
|
276
|
+
{"error": "Lookup data not found or expired", "token": pk},
|
|
277
|
+
status=status.HTTP_404_NOT_FOUND,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
return Response(store.get_all())
|
|
281
|
+
|
|
282
|
+
@action(detail=True, methods=["get", "patch"], url_path="parts")
|
|
283
|
+
def parts(self, request, pk=None):
|
|
284
|
+
"""
|
|
285
|
+
Get or update partial lookup data for a session.
|
|
286
|
+
|
|
287
|
+
GET: Retrieve specific keys from the session data.
|
|
288
|
+
PATCH: Update session data and trigger recomputation if input keys changed.
|
|
289
|
+
|
|
290
|
+
GET query params:
|
|
291
|
+
keys: Comma-separated list of keys to retrieve
|
|
292
|
+
|
|
293
|
+
PATCH body:
|
|
294
|
+
updates: Dictionary of key-value pairs to update
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
pk: Session token
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
GET: Dictionary with requested keys
|
|
301
|
+
PATCH: Success confirmation
|
|
302
|
+
|
|
303
|
+
Raises:
|
|
304
|
+
404: Token not found
|
|
305
|
+
400: Invalid request parameters
|
|
306
|
+
"""
|
|
307
|
+
|
|
308
|
+
if not pk:
|
|
309
|
+
return Response(
|
|
310
|
+
{"detail": "Token required"}, status=status.HTTP_404_NOT_FOUND
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
store = LookupStore(token=pk)
|
|
314
|
+
|
|
315
|
+
if request.method == "GET":
|
|
316
|
+
keys_param = request.query_params.get("keys", "")
|
|
317
|
+
|
|
318
|
+
keys = [k.strip() for k in keys_param.split(",") if k.strip()]
|
|
319
|
+
|
|
320
|
+
if not keys:
|
|
321
|
+
return Response(
|
|
322
|
+
{"detail": "Provide ?keys=key1,key2"},
|
|
323
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
return Response(store.get_many(keys))
|
|
328
|
+
|
|
329
|
+
except Exception:
|
|
330
|
+
return Response(
|
|
331
|
+
{"detail": "Lookup data not found or expired"},
|
|
332
|
+
status=status.HTTP_404_NOT_FOUND,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# PATCH
|
|
336
|
+
|
|
337
|
+
updates = request.data.get("updates", {})
|
|
338
|
+
|
|
339
|
+
if not isinstance(updates, dict) or not updates:
|
|
340
|
+
return Response(
|
|
341
|
+
{"detail": "updates must be a non-empty object"},
|
|
342
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
store.set_many(updates)
|
|
346
|
+
|
|
347
|
+
if any(key in self.INPUT_KEYS for key in updates.keys()):
|
|
348
|
+
try:
|
|
349
|
+
ls.recompute_lookup(pk)
|
|
350
|
+
|
|
351
|
+
except Exception as e:
|
|
352
|
+
import logging
|
|
353
|
+
|
|
354
|
+
logging.getLogger(__name__).error(
|
|
355
|
+
"Failed to recompute after patch for token %s: %s", pk, e
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
return Response({"ok": True, "token": pk}, status=status.HTTP_200_OK)
|
|
359
|
+
|
|
360
|
+
@action(detail=True, methods=["post"], url_path="recompute")
|
|
361
|
+
def recompute(self, request, pk=None):
|
|
362
|
+
"""Recompute lookup data based on current PatientExamination and user selections"""
|
|
363
|
+
|
|
364
|
+
if not pk:
|
|
365
|
+
return Response(
|
|
366
|
+
{"detail": "Token required"}, status=status.HTTP_404_NOT_FOUND
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
try:
|
|
370
|
+
updates = ls.recompute_lookup(pk)
|
|
371
|
+
|
|
372
|
+
return Response(
|
|
373
|
+
{"ok": True, "token": pk, "updates": updates}, status=status.HTTP_200_OK
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
except ValueError as e:
|
|
377
|
+
return Response({"detail": str(e)}, status=status.HTTP_404_NOT_FOUND)
|
|
378
|
+
|
|
379
|
+
except Exception as e:
|
|
380
|
+
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# services/lookup_store.py
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import uuid
|
|
6
|
+
from typing import Any, Dict, Iterable, Optional
|
|
7
|
+
|
|
8
|
+
from django.conf import settings
|
|
9
|
+
from django.core.cache import cache
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Align TTL with Django cache TIMEOUT for consistency in tests and runtime
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
DEFAULT_TTL_SECONDS = int(
|
|
17
|
+
settings.CACHES.get("default", {}).get("TIMEOUT", 60 * 30)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
except Exception:
|
|
22
|
+
DEFAULT_TTL_SECONDS = 60 * 30 # 30 minutes fallback
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class LookupStore:
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
Server-side lookup dictionary stored in Django cache.
|
|
29
|
+
|
|
30
|
+
Return a token to the client; later requests use that token to get/update parts.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, token: Optional[str] = None):
|
|
35
|
+
self.token = token or uuid.uuid4().hex
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def cache_key(self) -> str:
|
|
39
|
+
return f"lookup:{self.token}"
|
|
40
|
+
|
|
41
|
+
def init(
|
|
42
|
+
self, initial: Optional[Dict[str, Any]] = None, ttl: int = DEFAULT_TTL_SECONDS
|
|
43
|
+
) -> str:
|
|
44
|
+
cache.set(self.cache_key, initial or {}, ttl)
|
|
45
|
+
|
|
46
|
+
return self.token
|
|
47
|
+
|
|
48
|
+
def get_all(self) -> Dict[str, Any]:
|
|
49
|
+
return cache.get(self.cache_key, {})
|
|
50
|
+
|
|
51
|
+
def get_many(self, keys: Iterable[str]) -> Dict[str, Any]:
|
|
52
|
+
data = self.get_all()
|
|
53
|
+
|
|
54
|
+
return {k: data.get(k) for k in keys}
|
|
55
|
+
|
|
56
|
+
def set_many(self, updates: Dict[str, Any], ttl: int = DEFAULT_TTL_SECONDS) -> None:
|
|
57
|
+
data = self.get_all()
|
|
58
|
+
|
|
59
|
+
data.update(updates)
|
|
60
|
+
|
|
61
|
+
cache.set(self.cache_key, data, ttl)
|
|
62
|
+
|
|
63
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
64
|
+
return self.get_all().get(key, default)
|
|
65
|
+
|
|
66
|
+
def set(self, key: str, value: Any, ttl: int = DEFAULT_TTL_SECONDS) -> None:
|
|
67
|
+
data = self.get_all()
|
|
68
|
+
|
|
69
|
+
data[key] = value
|
|
70
|
+
|
|
71
|
+
cache.set(self.cache_key, data, ttl)
|
|
72
|
+
|
|
73
|
+
def delete(self) -> None:
|
|
74
|
+
cache.delete(self.cache_key)
|
|
75
|
+
|
|
76
|
+
def patch(self, updates: Dict[str, Any], ttl: int = DEFAULT_TTL_SECONDS) -> None:
|
|
77
|
+
"""Patch existing data with updates."""
|
|
78
|
+
|
|
79
|
+
data = self.get_all()
|
|
80
|
+
|
|
81
|
+
data.update(updates)
|
|
82
|
+
|
|
83
|
+
cache.set(self.cache_key, data, ttl)
|
|
84
|
+
|
|
85
|
+
def validate_and_recover_data(self, token):
|
|
86
|
+
"""Validate stored data and attempt recovery if corrupted"""
|
|
87
|
+
|
|
88
|
+
data = self.get_all()
|
|
89
|
+
|
|
90
|
+
if not data:
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
# Check if required fields are present
|
|
94
|
+
|
|
95
|
+
required_fields = [
|
|
96
|
+
"patient_examination_id",
|
|
97
|
+
"requirements_by_set",
|
|
98
|
+
"requirement_status",
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
missing_fields = [field for field in required_fields if field not in data]
|
|
102
|
+
|
|
103
|
+
if missing_fields:
|
|
104
|
+
import logging
|
|
105
|
+
|
|
106
|
+
logger = logging.getLogger(__name__)
|
|
107
|
+
|
|
108
|
+
logger.warning(
|
|
109
|
+
f"Missing fields in lookup data for token {token}: {missing_fields}"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Try to recover patient_examination_id from token or related data
|
|
113
|
+
|
|
114
|
+
if "patient_examination_id" in missing_fields:
|
|
115
|
+
# Attempt to extract from token or find related examination
|
|
116
|
+
|
|
117
|
+
recovered_id = self._recover_patient_examination_id(token)
|
|
118
|
+
|
|
119
|
+
if recovered_id:
|
|
120
|
+
data["patient_examination_id"] = recovered_id
|
|
121
|
+
|
|
122
|
+
logger.info(
|
|
123
|
+
f"Recovered patient_examination_id {recovered_id} for token {token}"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Do not automatically recompute here to avoid loops
|
|
127
|
+
|
|
128
|
+
# Recompute is only triggered by PATCH or explicit POST /recompute/
|
|
129
|
+
|
|
130
|
+
# For now, just return the data as is
|
|
131
|
+
|
|
132
|
+
return data
|
|
133
|
+
|
|
134
|
+
def _recover_patient_examination_id(self, token: str) -> Optional[str]:
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
Placeholder for recovering patient_examination_id.
|
|
138
|
+
|
|
139
|
+
This should be implemented with logic to find the ID based on the token or other data.
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
# In a real implementation, you might query a database or another service.
|
|
144
|
+
|
|
145
|
+
# For now, we return None as recovery logic is not defined.
|
|
146
|
+
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
def should_recompute(self, token):
|
|
150
|
+
"""Check if recomputation is needed based on data freshness"""
|
|
151
|
+
|
|
152
|
+
data = self.get_all()
|
|
153
|
+
|
|
154
|
+
if not data:
|
|
155
|
+
return True
|
|
156
|
+
|
|
157
|
+
# Check if we have a last_recompute timestamp
|
|
158
|
+
|
|
159
|
+
last_recompute = data.get("_last_recompute")
|
|
160
|
+
|
|
161
|
+
if not last_recompute:
|
|
162
|
+
return True
|
|
163
|
+
|
|
164
|
+
# Only recompute if it's been more than 30 seconds since last recompute
|
|
165
|
+
|
|
166
|
+
# This prevents excessive recomputation while allowing for updates
|
|
167
|
+
|
|
168
|
+
from datetime import datetime, timedelta
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
last_recompute_time = datetime.fromisoformat(last_recompute)
|
|
172
|
+
|
|
173
|
+
return datetime.now() - last_recompute_time > timedelta(seconds=30)
|
|
174
|
+
|
|
175
|
+
except (ValueError, TypeError):
|
|
176
|
+
return True
|
|
177
|
+
|
|
178
|
+
def mark_recompute_done(self):
|
|
179
|
+
"""Mark that recomputation has been completed"""
|
|
180
|
+
|
|
181
|
+
from datetime import datetime
|
|
182
|
+
|
|
183
|
+
self.set("_last_recompute", datetime.now().isoformat())
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Tuple, TYPE_CHECKING
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from endoreg_db.models.requirement.requirement_error import (
|
|
6
|
+
RequirementEvaluationError,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from endoreg_db.models.requirement.requirement import Requirement
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def safe_evaluate_requirement(
|
|
16
|
+
requirement: "Requirement",
|
|
17
|
+
*args: Any,
|
|
18
|
+
mode: str = "strict",
|
|
19
|
+
**kwargs: Any,
|
|
20
|
+
) -> Tuple[bool, str, str | None]:
|
|
21
|
+
"""
|
|
22
|
+
Wrapper für Requirement.evaluate / evaluate_with_details, der NIE Exceptions durchlässt.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
met: bool
|
|
26
|
+
details: human-readable explanation (für UI)
|
|
27
|
+
error: technischer Fehlerstring oder None
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
if hasattr(requirement, "evaluate_with_details"):
|
|
32
|
+
met, details = requirement.evaluate_with_details(*args, mode=mode, **kwargs)
|
|
33
|
+
else:
|
|
34
|
+
met = requirement.evaluate(*args, **kwargs)
|
|
35
|
+
details = "Voraussetzung erfüllt" if met else "Voraussetzung nicht erfüllt"
|
|
36
|
+
error = None
|
|
37
|
+
|
|
38
|
+
except RequirementEvaluationError as e:
|
|
39
|
+
ctx = e.context
|
|
40
|
+
req_obj = ctx.requirement or requirement
|
|
41
|
+
|
|
42
|
+
# sprechbarer Name aus DB (Beschreibung bevorzugen, sonst name)
|
|
43
|
+
display_name = (
|
|
44
|
+
getattr(req_obj, "description", None)
|
|
45
|
+
or getattr(req_obj, "name", None)
|
|
46
|
+
or "unbekannte Voraussetzung"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# falls Exception schon eine user_message mitbringt: die nehmen
|
|
50
|
+
if ctx.user_message:
|
|
51
|
+
details = ctx.user_message
|
|
52
|
+
else:
|
|
53
|
+
details = (
|
|
54
|
+
f"Die Voraussetzung „{display_name}“ konnte nicht ausgewertet werden."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# technischer Fehlerstring für Logs/Debug
|
|
58
|
+
error = f"{ctx.code}: {ctx.technical_message}"
|
|
59
|
+
logger.warning(
|
|
60
|
+
"Requirement '%s' (code=%s) validation error: %s",
|
|
61
|
+
getattr(req_obj, "name", "unknown"),
|
|
62
|
+
ctx.code,
|
|
63
|
+
ctx.technical_message,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
met = False
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
met = False
|
|
70
|
+
display_name = getattr(requirement, "description", None) or getattr(
|
|
71
|
+
requirement, "name", "unbekannte Voraussetzung"
|
|
72
|
+
)
|
|
73
|
+
details = f"Bei der Auswertung der Voraussetzung „{display_name}“ ist ein interner Fehler aufgetreten."
|
|
74
|
+
error = f"{e.__class__.__name__}: {e}"
|
|
75
|
+
logger.exception(
|
|
76
|
+
"Requirement '%s' unexpected error",
|
|
77
|
+
getattr(requirement, "name", "unknown"),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# normalize details to string
|
|
81
|
+
if not isinstance(details, str):
|
|
82
|
+
try:
|
|
83
|
+
details = json.dumps(details, ensure_ascii=False, default=str)
|
|
84
|
+
except Exception:
|
|
85
|
+
details = str(details)
|
|
86
|
+
|
|
87
|
+
return bool(met), details, error
|
|
File without changes
|
|
File without changes
|