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,76 @@
|
|
|
1
|
+
# endoreg_db/services/model_meta_from_hf.py
|
|
2
|
+
|
|
3
|
+
from django.core.files.base import ContentFile
|
|
4
|
+
from huggingface_hub import hf_hub_download
|
|
5
|
+
|
|
6
|
+
from endoreg_db.models import AiModel, LabelSet, ModelMeta
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def ensure_model_meta_from_hf(
|
|
10
|
+
*,
|
|
11
|
+
model_id: str,
|
|
12
|
+
model_name: str,
|
|
13
|
+
labelset_name: str,
|
|
14
|
+
meta_version: str = "1",
|
|
15
|
+
labelset_version: int | None = None,
|
|
16
|
+
) -> ModelMeta:
|
|
17
|
+
"""
|
|
18
|
+
Download weights from Hugging Face (if needed) and ensure a ModelMeta
|
|
19
|
+
exists for the given configuration. Returns the ModelMeta.
|
|
20
|
+
"""
|
|
21
|
+
# Download the model weights
|
|
22
|
+
weights_path = hf_hub_download(
|
|
23
|
+
repo_id=model_id,
|
|
24
|
+
filename="colo_segmentation_RegNetX800MF_base.safetensors",
|
|
25
|
+
local_dir="/tmp",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Get or create AI model
|
|
29
|
+
ai_model, _ = AiModel.objects.get_or_create(
|
|
30
|
+
name=model_name, defaults={"description": f"Model from {model_id}"}
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Get labelset
|
|
34
|
+
labelset_qs = LabelSet.objects.filter(name=labelset_name)
|
|
35
|
+
if labelset_version is not None:
|
|
36
|
+
labelset_qs = labelset_qs.filter(version=labelset_version)
|
|
37
|
+
labelset = labelset_qs.order_by("-version").first()
|
|
38
|
+
if labelset is None:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
f"LabelSet '{labelset_name}'"
|
|
41
|
+
+ (f" v{labelset_version}" if labelset_version is not None else "")
|
|
42
|
+
+ " not found"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Create or get ModelMeta
|
|
46
|
+
model_meta, _ = ModelMeta.objects.get_or_create(
|
|
47
|
+
name=model_name,
|
|
48
|
+
model=ai_model,
|
|
49
|
+
version=meta_version,
|
|
50
|
+
defaults={
|
|
51
|
+
"labelset": labelset,
|
|
52
|
+
"activation": "sigmoid",
|
|
53
|
+
"mean": "0.45211223,0.27139644,0.19264949",
|
|
54
|
+
"std": "0.31418097,0.21088019,0.16059452",
|
|
55
|
+
"size_x": 716,
|
|
56
|
+
"size_y": 716,
|
|
57
|
+
"axes": "2,0,1",
|
|
58
|
+
"batchsize": 16,
|
|
59
|
+
"num_workers": 0,
|
|
60
|
+
"description": f"Downloaded from {model_id}",
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# If weights file not yet saved, save it
|
|
65
|
+
if not model_meta.weights:
|
|
66
|
+
with open(weights_path, "rb") as f:
|
|
67
|
+
model_meta.weights.save(
|
|
68
|
+
f"{model_name}_v{meta_version}.safetensors",
|
|
69
|
+
ContentFile(f.read()),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Set as active meta
|
|
73
|
+
ai_model.active_meta = model_meta
|
|
74
|
+
ai_model.save(update_fields=["active_meta"])
|
|
75
|
+
|
|
76
|
+
return model_meta
|
|
File without changes
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# endoreg_db/services/polling_coordinator.py
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
from typing import Dict, Optional
|
|
6
|
+
from django.core.cache import cache
|
|
7
|
+
from django.utils import timezone
|
|
8
|
+
from datetime import timedelta
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PollingCoordinator:
|
|
14
|
+
"""
|
|
15
|
+
Service to prevent duplicate polling operations on the same media items.
|
|
16
|
+
Uses Django cache and thread-safe operations to coordinate polling requests.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
# Class-level lock for thread safety
|
|
20
|
+
_lock = threading.Lock()
|
|
21
|
+
|
|
22
|
+
# Cache key prefixes
|
|
23
|
+
PROCESSING_PREFIX = "polling_processing:"
|
|
24
|
+
LAST_CHECK_PREFIX = "polling_last_check:"
|
|
25
|
+
|
|
26
|
+
# Default timeouts
|
|
27
|
+
PROCESSING_TIMEOUT = 300 # 5 minutes
|
|
28
|
+
CHECK_COOLDOWN = 10 # 10 seconds minimum between checks
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def acquire_processing_lock(
|
|
32
|
+
cls, file_id: int, file_type: str = "video", timeout: Optional[int] = None
|
|
33
|
+
) -> bool:
|
|
34
|
+
"""
|
|
35
|
+
Acquire a processing lock for a media file to prevent duplicate processing.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
file_id: ID of the media file
|
|
39
|
+
file_type: Type of media (video, pdf)
|
|
40
|
+
timeout: Lock timeout in seconds (default: 5 minutes)
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
True if lock acquired, False if already locked
|
|
44
|
+
"""
|
|
45
|
+
if timeout is None:
|
|
46
|
+
timeout = cls.PROCESSING_TIMEOUT
|
|
47
|
+
|
|
48
|
+
cache_key = f"{cls.PROCESSING_PREFIX}{file_type}:{file_id}"
|
|
49
|
+
|
|
50
|
+
with cls._lock:
|
|
51
|
+
# Try to acquire lock atomically
|
|
52
|
+
lock_acquired = cache.add(
|
|
53
|
+
cache_key,
|
|
54
|
+
{
|
|
55
|
+
"locked_at": timezone.now().isoformat(),
|
|
56
|
+
"file_id": file_id,
|
|
57
|
+
"file_type": file_type,
|
|
58
|
+
"thread_id": threading.get_ident(),
|
|
59
|
+
},
|
|
60
|
+
timeout,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if lock_acquired:
|
|
64
|
+
logger.info(f"Processing lock acquired for {file_type}:{file_id}")
|
|
65
|
+
return True
|
|
66
|
+
else:
|
|
67
|
+
# Check if existing lock is stale
|
|
68
|
+
existing_lock = cache.get(cache_key)
|
|
69
|
+
if existing_lock:
|
|
70
|
+
logger.warning(
|
|
71
|
+
f"Processing lock already exists for {file_type}:{file_id}: {existing_lock}"
|
|
72
|
+
)
|
|
73
|
+
else:
|
|
74
|
+
logger.warning(
|
|
75
|
+
f"Failed to acquire processing lock for {file_type}:{file_id}"
|
|
76
|
+
)
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def release_processing_lock(cls, file_id: int, file_type: str = "video") -> bool:
|
|
81
|
+
"""
|
|
82
|
+
Release a processing lock for a media file.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
file_id: ID of the media file
|
|
86
|
+
file_type: Type of media (video, pdf)
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
True if lock released, False if lock didn't exist
|
|
90
|
+
"""
|
|
91
|
+
cache_key = f"{cls.PROCESSING_PREFIX}{file_type}:{file_id}"
|
|
92
|
+
|
|
93
|
+
with cls._lock:
|
|
94
|
+
if cache.delete(cache_key):
|
|
95
|
+
logger.info(f"Processing lock released for {file_type}:{file_id}")
|
|
96
|
+
return True
|
|
97
|
+
else:
|
|
98
|
+
logger.warning(
|
|
99
|
+
f"No processing lock found to release for {file_type}:{file_id}"
|
|
100
|
+
)
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
@classmethod
|
|
104
|
+
def is_processing_locked(cls, file_id: int, file_type: str = "video") -> bool:
|
|
105
|
+
"""
|
|
106
|
+
Check if a media file is currently processing locked.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
file_id: ID of the media file
|
|
110
|
+
file_type: Type of media (video, pdf)
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
True if locked, False otherwise
|
|
114
|
+
"""
|
|
115
|
+
cache_key = f"{cls.PROCESSING_PREFIX}{file_type}:{file_id}"
|
|
116
|
+
return cache.get(cache_key) is not None
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def can_check_status(cls, file_id: int, file_type: str = "video") -> bool:
|
|
120
|
+
"""
|
|
121
|
+
Check if enough time has passed since last status check to prevent spam.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
file_id: ID of the media file
|
|
125
|
+
file_type: Type of media (video, pdf)
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
True if status check is allowed, False if still in cooldown
|
|
129
|
+
"""
|
|
130
|
+
cache_key = f"{cls.LAST_CHECK_PREFIX}{file_type}:{file_id}"
|
|
131
|
+
last_check = cache.get(cache_key)
|
|
132
|
+
|
|
133
|
+
if last_check is None:
|
|
134
|
+
# First check or cooldown expired - allowed
|
|
135
|
+
cls._record_status_check(file_id, file_type)
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
# Check if cooldown period has passed
|
|
139
|
+
last_check_time = timezone.datetime.fromisoformat(
|
|
140
|
+
last_check.replace("Z", "+00:00")
|
|
141
|
+
)
|
|
142
|
+
cooldown_end = last_check_time + timedelta(seconds=cls.CHECK_COOLDOWN)
|
|
143
|
+
|
|
144
|
+
if timezone.now() > cooldown_end:
|
|
145
|
+
cls._record_status_check(file_id, file_type)
|
|
146
|
+
return True
|
|
147
|
+
else:
|
|
148
|
+
remaining_cooldown = (cooldown_end - timezone.now()).total_seconds()
|
|
149
|
+
logger.debug(
|
|
150
|
+
f"Status check cooldown active for {file_type}:{file_id}, {remaining_cooldown:.1f}s remaining"
|
|
151
|
+
)
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def get_remaining_cooldown_seconds(
|
|
156
|
+
cls, file_id: int, file_type: str = "video"
|
|
157
|
+
) -> int:
|
|
158
|
+
"""
|
|
159
|
+
Get the remaining cooldown seconds for a status check.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
file_id: ID of the media file
|
|
163
|
+
file_type: Type of media (video, pdf)
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Remaining cooldown in seconds (0 if no cooldown active)
|
|
167
|
+
"""
|
|
168
|
+
cache_key = f"{cls.LAST_CHECK_PREFIX}{file_type}:{file_id}"
|
|
169
|
+
last_check = cache.get(cache_key)
|
|
170
|
+
|
|
171
|
+
if last_check is None:
|
|
172
|
+
return 0
|
|
173
|
+
|
|
174
|
+
# Check if cooldown period has passed
|
|
175
|
+
last_check_time = timezone.datetime.fromisoformat(
|
|
176
|
+
last_check.replace("Z", "+00:00")
|
|
177
|
+
)
|
|
178
|
+
cooldown_end = last_check_time + timedelta(seconds=cls.CHECK_COOLDOWN)
|
|
179
|
+
|
|
180
|
+
if timezone.now() > cooldown_end:
|
|
181
|
+
return 0
|
|
182
|
+
else:
|
|
183
|
+
remaining_cooldown = (cooldown_end - timezone.now()).total_seconds()
|
|
184
|
+
# Round up to at least 1 second
|
|
185
|
+
return max(1, int(remaining_cooldown) + 1)
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def _record_status_check(cls, file_id: int, file_type: str = "video") -> None:
|
|
189
|
+
"""Record the time of a status check"""
|
|
190
|
+
cache_key = f"{cls.LAST_CHECK_PREFIX}{file_type}:{file_id}"
|
|
191
|
+
cache.set(cache_key, timezone.now().isoformat(), cls.CHECK_COOLDOWN + 5)
|
|
192
|
+
|
|
193
|
+
@classmethod
|
|
194
|
+
def get_processing_locks_info(cls) -> Dict[str, any]:
|
|
195
|
+
"""
|
|
196
|
+
Get information about all currently active processing locks.
|
|
197
|
+
Useful for debugging and monitoring.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Dictionary with lock information
|
|
201
|
+
"""
|
|
202
|
+
# Note: This is a simplified version since Django cache doesn't support pattern scanning
|
|
203
|
+
# In production, consider using Redis with SCAN command for better performance
|
|
204
|
+
|
|
205
|
+
info = {
|
|
206
|
+
"coordinator_status": "active",
|
|
207
|
+
"config": {
|
|
208
|
+
"processing_timeout": cls.PROCESSING_TIMEOUT,
|
|
209
|
+
"check_cooldown": cls.CHECK_COOLDOWN,
|
|
210
|
+
},
|
|
211
|
+
"note": "Active locks info requires Redis backend for pattern scanning",
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return info
|
|
215
|
+
|
|
216
|
+
@classmethod
|
|
217
|
+
def clear_all_locks(cls, file_type: Optional[str] = None) -> int:
|
|
218
|
+
"""
|
|
219
|
+
Emergency function to clear all processing locks.
|
|
220
|
+
Use with caution - only for debugging/recovery scenarios.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
file_type: Optionally clear locks only for specific file type
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Number of locks cleared (approximation)
|
|
227
|
+
"""
|
|
228
|
+
logger.warning(
|
|
229
|
+
"clear_all_locks called - this should only be used for debugging/recovery"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# This is a simplified implementation
|
|
233
|
+
# In production with Redis, you'd use SCAN to find and delete matching keys
|
|
234
|
+
if hasattr(cache, "clear"):
|
|
235
|
+
cache.clear()
|
|
236
|
+
return -1 # Unknown count
|
|
237
|
+
else:
|
|
238
|
+
logger.warning("Cache backend doesn't support pattern deletion")
|
|
239
|
+
return 0
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Decorator for views that need processing coordination
|
|
243
|
+
def processing_coordination(file_id_param: str = "file_id", file_type: str = "video"):
|
|
244
|
+
"""
|
|
245
|
+
Decorator to add automatic processing coordination to views.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
file_id_param: Name of the parameter containing file ID
|
|
249
|
+
file_type: Type of media file
|
|
250
|
+
"""
|
|
251
|
+
|
|
252
|
+
def decorator(view_func):
|
|
253
|
+
def wrapper(request, *args, **kwargs):
|
|
254
|
+
# Extract file_id from kwargs or request
|
|
255
|
+
file_id = kwargs.get(file_id_param) or request.data.get(file_id_param)
|
|
256
|
+
|
|
257
|
+
if file_id is None:
|
|
258
|
+
logger.error(
|
|
259
|
+
f"No {file_id_param} found in request for processing coordination"
|
|
260
|
+
)
|
|
261
|
+
from rest_framework.response import Response
|
|
262
|
+
from rest_framework import status
|
|
263
|
+
|
|
264
|
+
return Response(
|
|
265
|
+
{"error": f"Missing {file_id_param} parameter"},
|
|
266
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Check if processing is already locked
|
|
270
|
+
if PollingCoordinator.is_processing_locked(file_id, file_type):
|
|
271
|
+
from rest_framework.response import Response
|
|
272
|
+
from rest_framework import status
|
|
273
|
+
|
|
274
|
+
return Response(
|
|
275
|
+
{"detail": "File is currently being processed by another request"},
|
|
276
|
+
status=status.HTTP_409_CONFLICT,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Proceed with the view
|
|
280
|
+
return view_func(request, *args, **kwargs)
|
|
281
|
+
|
|
282
|
+
return wrapper
|
|
283
|
+
|
|
284
|
+
return decorator
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# Context manager for automatic lock management
|
|
288
|
+
class ProcessingLockContext:
|
|
289
|
+
"""
|
|
290
|
+
Context manager for automatic processing lock acquisition and release.
|
|
291
|
+
|
|
292
|
+
Usage:
|
|
293
|
+
with ProcessingLockContext(file_id, "video") as lock:
|
|
294
|
+
if lock.acquired:
|
|
295
|
+
# Perform processing
|
|
296
|
+
pass
|
|
297
|
+
else:
|
|
298
|
+
# Handle lock acquisition failure
|
|
299
|
+
pass
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
def __init__(
|
|
303
|
+
self, file_id: int, file_type: str = "video", timeout: Optional[int] = None
|
|
304
|
+
):
|
|
305
|
+
self.file_id = file_id
|
|
306
|
+
self.file_type = file_type
|
|
307
|
+
self.timeout = timeout
|
|
308
|
+
self.acquired = False
|
|
309
|
+
|
|
310
|
+
def __enter__(self):
|
|
311
|
+
self.acquired = PollingCoordinator.acquire_processing_lock(
|
|
312
|
+
self.file_id, self.file_type, self.timeout
|
|
313
|
+
)
|
|
314
|
+
return self
|
|
315
|
+
|
|
316
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
317
|
+
if self.acquired:
|
|
318
|
+
PollingCoordinator.release_processing_lock(self.file_id, self.file_type)
|
|
319
|
+
return False # Don't suppress exceptions
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Service for generating patient pseudonyms using SensitiveMeta logic.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Tuple
|
|
7
|
+
from django.db import transaction
|
|
8
|
+
|
|
9
|
+
from endoreg_db.models.administration.person.patient.patient import Patient
|
|
10
|
+
from endoreg_db.models.metadata.sensitive_meta import SensitiveMeta
|
|
11
|
+
from endoreg_db.models.metadata import sensitive_meta_logic as logic
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def generate_patient_pseudonym(patient: Patient) -> Tuple[str, bool]:
|
|
17
|
+
"""
|
|
18
|
+
Generate a pseudonym hash for an existing Patient using SensitiveMeta logic.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
patient: The Patient instance to generate a pseudonym for
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Tuple of (patient_hash, persisted_flag)
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
ValueError: If required fields are missing for hash calculation
|
|
28
|
+
"""
|
|
29
|
+
# Validate required fields for hash calculation
|
|
30
|
+
if not patient.dob:
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"Patient date of birth (dob) is required for pseudonym generation"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if not patient.center:
|
|
36
|
+
raise ValueError("Patient center is required for pseudonym generation")
|
|
37
|
+
|
|
38
|
+
# Use existing patient_hash if it exists and is valid
|
|
39
|
+
if patient.patient_hash and len(patient.patient_hash.strip()) > 0:
|
|
40
|
+
logger.info(f"Patient {patient.id} already has a hash: {patient.patient_hash}")
|
|
41
|
+
return patient.patient_hash, True
|
|
42
|
+
|
|
43
|
+
# Create a transient SensitiveMeta instance to calculate the hash
|
|
44
|
+
# We don't save this instance, just use it for hash calculation
|
|
45
|
+
sensitive_meta = SensitiveMeta(
|
|
46
|
+
patient_first_name=patient.first_name or "",
|
|
47
|
+
patient_last_name=patient.last_name or "",
|
|
48
|
+
patient_dob=patient.dob,
|
|
49
|
+
center=patient.center,
|
|
50
|
+
patient_gender=patient.gender, # Optional, but include if available
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
# Calculate the hash using the existing logic
|
|
55
|
+
patient_hash = logic.calculate_patient_hash(
|
|
56
|
+
sensitive_meta, salt=logic.SECRET_SALT
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Persist the hash to the Patient model
|
|
60
|
+
with transaction.atomic():
|
|
61
|
+
patient.patient_hash = patient_hash
|
|
62
|
+
patient.save(update_fields=["patient_hash"])
|
|
63
|
+
|
|
64
|
+
logger.info(f"Generated and persisted pseudonym for patient {patient.id}")
|
|
65
|
+
|
|
66
|
+
return patient_hash, True
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error(f"Error generating pseudonym for patient {patient.id}: {str(e)}")
|
|
70
|
+
raise ValueError(f"Failed to generate pseudonym: {str(e)}")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def validate_patient_for_pseudonym(patient: Patient) -> list[str]:
|
|
74
|
+
"""
|
|
75
|
+
Validate that a patient has all required fields for pseudonym generation.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
patient: The Patient instance to validate
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List of missing required fields (empty if all fields present)
|
|
82
|
+
"""
|
|
83
|
+
missing_fields = []
|
|
84
|
+
|
|
85
|
+
if not patient.dob:
|
|
86
|
+
missing_fields.append("dob")
|
|
87
|
+
|
|
88
|
+
if not patient.center:
|
|
89
|
+
missing_fields.append("center")
|
|
90
|
+
|
|
91
|
+
# Note: first_name and last_name can be empty strings according to the logic,
|
|
92
|
+
# so we don't require them to be non-empty
|
|
93
|
+
|
|
94
|
+
return missing_fields
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from endoreg_db.import_files.report_import_service import ReportImportService as ris
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ReportImportService(ris):
|
|
5
|
+
__doc__ = (
|
|
6
|
+
(ris.__doc__ or "")
|
|
7
|
+
+ """
|
|
8
|
+
Wrapper for known import of concurrency safe ReportImportService,
|
|
9
|
+
here celery will be implemented in the future.
|
|
10
|
+
12.02.2025
|
|
11
|
+
"""
|
|
12
|
+
)
|
|
13
|
+
pass
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Service for synchronizing annotation updates with LabelVideoSegment creation.
|
|
3
|
+
|
|
4
|
+
This module provides functionality to create user-source LabelVideoSegments
|
|
5
|
+
when segment annotations are created or updated.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Optional, Dict, Any
|
|
10
|
+
from django.contrib.auth.models import User
|
|
11
|
+
from django.db import transaction
|
|
12
|
+
|
|
13
|
+
from ..models import VideoFile, Label, LabelVideoSegment, InformationSource
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_user_segment_from_annotation(
|
|
19
|
+
annotation: Dict[str, Any], request_user: User
|
|
20
|
+
) -> Optional[LabelVideoSegment]:
|
|
21
|
+
"""
|
|
22
|
+
Create a user-source LabelVideoSegment from a segment annotation.
|
|
23
|
+
|
|
24
|
+
This function:
|
|
25
|
+
1. Locates the original LabelVideoSegment (if segmentId is present)
|
|
26
|
+
2. Clones all its DB fields
|
|
27
|
+
3. Overwrites with new data from annotation
|
|
28
|
+
4. Sets information_source = user
|
|
29
|
+
5. Saves via model manager
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
annotation: Annotation data containing segment information
|
|
33
|
+
request_user: The authenticated user making the request
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
New LabelVideoSegment instance or None if creation failed/skipped
|
|
37
|
+
"""
|
|
38
|
+
# Validate this is a segment annotation
|
|
39
|
+
if annotation.get("type") != "segment":
|
|
40
|
+
logger.debug("Annotation is not a segment type, skipping user segment creation")
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
# Get required data from annotation
|
|
44
|
+
video_id = annotation.get("videoId")
|
|
45
|
+
start_time = annotation.get("startTime")
|
|
46
|
+
end_time = annotation.get("endTime")
|
|
47
|
+
label_text = annotation.get("text", "").strip()
|
|
48
|
+
metadata = annotation.get("metadata", {})
|
|
49
|
+
original_segment_id = metadata.get("segmentId")
|
|
50
|
+
|
|
51
|
+
if not all([video_id, start_time is not None, end_time is not None]):
|
|
52
|
+
logger.warning(
|
|
53
|
+
"Missing required segment data in annotation, skipping user segment creation"
|
|
54
|
+
)
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
# Get the video file
|
|
59
|
+
video_file = VideoFile.objects.get(id=video_id)
|
|
60
|
+
|
|
61
|
+
# Get video FPS for frame calculation
|
|
62
|
+
fps = video_file.get_fps()
|
|
63
|
+
if not fps or fps <= 0:
|
|
64
|
+
logger.warning(
|
|
65
|
+
f"Invalid FPS ({fps}) for video {video_id}, using default 25"
|
|
66
|
+
)
|
|
67
|
+
fps = 25.0
|
|
68
|
+
|
|
69
|
+
# Calculate frame numbers
|
|
70
|
+
start_frame_number = int(start_time * fps)
|
|
71
|
+
end_frame_number = int(end_time * fps)
|
|
72
|
+
|
|
73
|
+
# Get or create user information source
|
|
74
|
+
user_source, _ = InformationSource.objects.get_or_create(
|
|
75
|
+
name="user", defaults={"description": "User-generated annotations"}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Try to find label by name from annotation text
|
|
79
|
+
label = None
|
|
80
|
+
if label_text:
|
|
81
|
+
try:
|
|
82
|
+
label = Label.objects.filter(name__iexact=label_text).first()
|
|
83
|
+
if not label:
|
|
84
|
+
# Try to extract label from tags
|
|
85
|
+
tags = annotation.get("tags", [])
|
|
86
|
+
for tag in tags:
|
|
87
|
+
label = Label.objects.filter(name__iexact=tag).first()
|
|
88
|
+
if label:
|
|
89
|
+
break
|
|
90
|
+
except Exception as e:
|
|
91
|
+
logger.warning(f"Error finding label '{label_text}': {e}")
|
|
92
|
+
|
|
93
|
+
# Start with default segment data
|
|
94
|
+
segment_data = {
|
|
95
|
+
"video_file": video_file,
|
|
96
|
+
"start_frame_number": start_frame_number,
|
|
97
|
+
"end_frame_number": end_frame_number,
|
|
98
|
+
"source": user_source,
|
|
99
|
+
"label": label,
|
|
100
|
+
"prediction_meta": None, # User segments don't have prediction meta
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# If original segment ID is provided, try to clone from original
|
|
104
|
+
if original_segment_id:
|
|
105
|
+
try:
|
|
106
|
+
original_segment = LabelVideoSegment.objects.get(id=original_segment_id)
|
|
107
|
+
|
|
108
|
+
# Check if timing or label actually changed
|
|
109
|
+
original_start_time = original_segment.start_frame_number / fps
|
|
110
|
+
original_end_time = original_segment.end_frame_number / fps
|
|
111
|
+
|
|
112
|
+
timing_changed = (
|
|
113
|
+
abs(original_start_time - start_time)
|
|
114
|
+
> 0.1 # Allow small floating point differences
|
|
115
|
+
or abs(original_end_time - end_time) > 0.1
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
label_changed = (label and original_segment.label != label) or (
|
|
119
|
+
not label and original_segment.label is not None
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Only create new segment if something actually changed
|
|
123
|
+
if not timing_changed and not label_changed:
|
|
124
|
+
logger.debug(
|
|
125
|
+
f"No changes detected in segment {original_segment_id}, skipping user segment creation"
|
|
126
|
+
)
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
# Clone relevant fields from original segment
|
|
130
|
+
segment_data.update(
|
|
131
|
+
{
|
|
132
|
+
"prediction_meta": original_segment.prediction_meta,
|
|
133
|
+
"label": label
|
|
134
|
+
or original_segment.label, # Use new label if provided, otherwise keep original
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
logger.info(
|
|
139
|
+
f"Cloning segment {original_segment_id} with user modifications"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
except LabelVideoSegment.DoesNotExist:
|
|
143
|
+
logger.warning(
|
|
144
|
+
f"Original segment {original_segment_id} not found, creating new user segment"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Create the new user segment using the manager
|
|
148
|
+
with transaction.atomic():
|
|
149
|
+
new_segment = LabelVideoSegment.create_from_video(
|
|
150
|
+
source=video_file,
|
|
151
|
+
prediction_meta=segment_data.get("prediction_meta"),
|
|
152
|
+
label=segment_data["label"],
|
|
153
|
+
start_frame_number=start_frame_number,
|
|
154
|
+
end_frame_number=end_frame_number,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Set the user information source
|
|
158
|
+
new_segment.source = user_source
|
|
159
|
+
new_segment.save()
|
|
160
|
+
|
|
161
|
+
logger.info(
|
|
162
|
+
f"Created user segment {new_segment.id} for video {video_id} by user {request_user.username}"
|
|
163
|
+
)
|
|
164
|
+
return new_segment
|
|
165
|
+
|
|
166
|
+
except VideoFile.DoesNotExist:
|
|
167
|
+
logger.error(f"Video {video_id} not found, cannot create user segment")
|
|
168
|
+
return None
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"Error creating user segment from annotation: {e}")
|
|
171
|
+
return None
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from endoreg_db.import_files.video_import_service import VideoImportService as vis
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class VideoImportService(vis):
|
|
5
|
+
__doc__ = (vis.__doc__ or "") + (
|
|
6
|
+
"Wrapper for service import of concurrency safe VideoImportService.\n"
|
|
7
|
+
"Implemented for future Celery integration (12.02.2025).\n\n"
|
|
8
|
+
)
|
|
9
|
+
pass
|