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,402 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import shutil
|
|
3
|
+
import uuid
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING, Optional, Type
|
|
7
|
+
|
|
8
|
+
# Import the new exceptions from the correct path
|
|
9
|
+
from endoreg_db.exceptions import InsufficientStorageError, TranscodingError
|
|
10
|
+
from endoreg_db.utils.paths import (
|
|
11
|
+
IMPORT_VIDEO_DIR,
|
|
12
|
+
SENSITIVE_VIDEO_DIR,
|
|
13
|
+
TRANSCODING_DIR,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from endoreg_db.models import VideoFile
|
|
18
|
+
|
|
19
|
+
import endoreg_db.utils.paths as path_utils
|
|
20
|
+
|
|
21
|
+
from ....utils.video.ffmpeg_wrapper import transcode_videofile_if_required
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def check_storage_capacity(
|
|
27
|
+
src_path: Path, dst_root: Path, safety_margin: float = 1.2
|
|
28
|
+
) -> None:
|
|
29
|
+
"""
|
|
30
|
+
Check if there's enough storage space before starting operations.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
src_path: Source file path
|
|
34
|
+
dst_root: Destination root directory
|
|
35
|
+
safety_margin: Safety factor (1.2 = 20% extra space required)
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
InsufficientStorageError: If insufficient storage space
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
src_size = src_path.stat().st_size
|
|
42
|
+
required_space = int(src_size * safety_margin)
|
|
43
|
+
|
|
44
|
+
# Check free space on destination
|
|
45
|
+
free_space = shutil.disk_usage(dst_root).free
|
|
46
|
+
|
|
47
|
+
if free_space < required_space:
|
|
48
|
+
raise InsufficientStorageError(
|
|
49
|
+
f"Insufficient storage space. Required: {required_space / 1e9:.1f} GB, Available: {free_space / 1e9:.1f} GB on {dst_root}",
|
|
50
|
+
required_space=required_space,
|
|
51
|
+
available_space=free_space,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
logger.info(
|
|
55
|
+
f"Storage check passed: {free_space / 1e9:.1f} GB available, {required_space / 1e9:.1f} GB required"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
except OSError as e:
|
|
59
|
+
logger.warning(f"Could not check storage capacity: {e}")
|
|
60
|
+
# Don't fail the operation, just log the warning
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def atomic_copy_with_fallback(
|
|
64
|
+
src_path: Path = IMPORT_VIDEO_DIR, dst_path: Path = SENSITIVE_VIDEO_DIR
|
|
65
|
+
) -> bool:
|
|
66
|
+
"""
|
|
67
|
+
Atomically copy file from src to dst, preserving the source file.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
src_path: Source file path
|
|
71
|
+
dst_path: Destination file path
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
True if successful
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
InsufficientStorageError: If not enough space for the operation
|
|
78
|
+
OSError: For other file system errors
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
# Check space before copy
|
|
82
|
+
src_size = src_path.stat().st_size
|
|
83
|
+
free_space = shutil.disk_usage(dst_path.parent).free
|
|
84
|
+
|
|
85
|
+
if free_space < src_size * 1.1: # 10% safety margin
|
|
86
|
+
raise InsufficientStorageError(
|
|
87
|
+
f"Insufficient space for copy operation. Required: {src_size / 1e9:.1f} GB, Available: {free_space / 1e9:.1f} GB",
|
|
88
|
+
required_space=src_size,
|
|
89
|
+
available_space=free_space,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Use a temporary name during copy for atomicity
|
|
93
|
+
temp_dst = dst_path.with_suffix(dst_path.suffix + ".tmp")
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
shutil.copy2(str(src_path), str(temp_dst))
|
|
97
|
+
temp_dst.rename(dst_path)
|
|
98
|
+
logger.debug(f"Copy successful: {src_path} -> {dst_path}")
|
|
99
|
+
return True
|
|
100
|
+
except Exception:
|
|
101
|
+
# Clean up temp file if copy failed
|
|
102
|
+
if temp_dst.exists():
|
|
103
|
+
temp_dst.unlink(missing_ok=True)
|
|
104
|
+
raise
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"Copy operation failed: {src_path} -> {dst_path}: {e}")
|
|
108
|
+
raise
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def atomic_move_with_fallback(src_path: Path, dst_path: Path) -> bool:
|
|
112
|
+
"""
|
|
113
|
+
Atomically move file from src to dst, with fallback to copy+remove.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
src_path: Source file path
|
|
117
|
+
dst_path: Destination file path
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if successful
|
|
121
|
+
|
|
122
|
+
Raises:
|
|
123
|
+
InsufficientStorageError: If not enough space for the operation
|
|
124
|
+
OSError: For other file system errors
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
# First try atomic move (same filesystem)
|
|
128
|
+
try:
|
|
129
|
+
src_path.rename(dst_path)
|
|
130
|
+
logger.debug(f"Atomic move successful: {src_path} -> {dst_path}")
|
|
131
|
+
return True
|
|
132
|
+
except OSError as e:
|
|
133
|
+
if e.errno == 18: # Cross-device link
|
|
134
|
+
logger.debug("Cross-device move detected, falling back to copy+remove")
|
|
135
|
+
else:
|
|
136
|
+
raise
|
|
137
|
+
|
|
138
|
+
# Check space before cross-filesystem copy
|
|
139
|
+
src_size = src_path.stat().st_size
|
|
140
|
+
free_space = shutil.disk_usage(dst_path.parent).free
|
|
141
|
+
|
|
142
|
+
if free_space < src_size * 1.1: # 10% safety margin
|
|
143
|
+
raise InsufficientStorageError(
|
|
144
|
+
f"Insufficient space for copy operation. Required: {src_size / 1e9:.1f} GB, Available: {free_space / 1e9:.1f} GB",
|
|
145
|
+
required_space=src_size,
|
|
146
|
+
available_space=free_space,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Fallback to copy+remove for cross-filesystem moves
|
|
150
|
+
logger.info(f"Copying file (cross-filesystem): {src_path} -> {dst_path}")
|
|
151
|
+
|
|
152
|
+
# Use a temporary name during copy for atomicity
|
|
153
|
+
temp_dst = dst_path.with_suffix(dst_path.suffix + ".tmp")
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
shutil.copy2(str(src_path), str(temp_dst))
|
|
157
|
+
temp_dst.rename(dst_path)
|
|
158
|
+
src_path.unlink() # Remove source only after successful copy
|
|
159
|
+
logger.debug(f"Copy+remove successful: {src_path} -> {dst_path}")
|
|
160
|
+
return True
|
|
161
|
+
|
|
162
|
+
except OSError as e:
|
|
163
|
+
# Clean up temp file on failure
|
|
164
|
+
if temp_dst.exists():
|
|
165
|
+
temp_dst.unlink(missing_ok=True)
|
|
166
|
+
# Re-raise with better context
|
|
167
|
+
if e.errno == 28: # No space left on device
|
|
168
|
+
raise InsufficientStorageError(
|
|
169
|
+
f"No space left on device during copy: {e}",
|
|
170
|
+
required_space=src_path.stat().st_size,
|
|
171
|
+
available_space=shutil.disk_usage(dst_path.parent).free,
|
|
172
|
+
)
|
|
173
|
+
raise
|
|
174
|
+
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.error(f"Failed to move {src_path} -> {dst_path}: {e}")
|
|
177
|
+
raise
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _get_data_paths():
|
|
181
|
+
"""Return the current data_paths mapping (supports patched instances in tests)."""
|
|
182
|
+
utils_module = import_module("endoreg_db.utils")
|
|
183
|
+
return getattr(utils_module, "data_paths")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _get_path(mapping, key, default):
|
|
187
|
+
"""Access mapping by key using __getitem__ so MagicMocks with side effects work."""
|
|
188
|
+
if mapping is None:
|
|
189
|
+
return default
|
|
190
|
+
try:
|
|
191
|
+
return mapping[key]
|
|
192
|
+
except (KeyError, TypeError):
|
|
193
|
+
return default
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _create_from_file(
|
|
197
|
+
cls_model: Type["VideoFile"],
|
|
198
|
+
file_path: Path,
|
|
199
|
+
center_name: str,
|
|
200
|
+
processor_name: Optional[str],
|
|
201
|
+
video_hash: str,
|
|
202
|
+
video_dir: Path = IMPORT_VIDEO_DIR,
|
|
203
|
+
save: bool = True,
|
|
204
|
+
delete_source: bool = False,
|
|
205
|
+
**kwargs,
|
|
206
|
+
) -> "VideoFile":
|
|
207
|
+
"""
|
|
208
|
+
Creates a VideoFile instance from a given video file path with improved error handling.
|
|
209
|
+
|
|
210
|
+
Raises:
|
|
211
|
+
InsufficientStorageError: When not enough disk space
|
|
212
|
+
TranscodingError: When video transcoding fails
|
|
213
|
+
ValueError: When required objects (Center, Processor) not found
|
|
214
|
+
RuntimeError: For other processing errors
|
|
215
|
+
"""
|
|
216
|
+
from endoreg_db.models.administration.center.center import Center
|
|
217
|
+
from endoreg_db.models.medical.hardware import EndoscopyProcessor
|
|
218
|
+
|
|
219
|
+
original_file_name = file_path.name
|
|
220
|
+
original_suffix = file_path.suffix
|
|
221
|
+
final_storage_path = None
|
|
222
|
+
transcoded_file_path = None
|
|
223
|
+
|
|
224
|
+
try:
|
|
225
|
+
# Ensure we operate under the canonical video path root
|
|
226
|
+
data_paths = _get_data_paths()
|
|
227
|
+
resolved_video_dir = _get_path(data_paths, "sensitive_video", video_dir)
|
|
228
|
+
video_dir = Path(resolved_video_dir)
|
|
229
|
+
storage_root_default = Path(video_dir).parent
|
|
230
|
+
resolved_storage_root = _get_path(data_paths, "storage", storage_root_default)
|
|
231
|
+
storage_root = Path(resolved_storage_root)
|
|
232
|
+
storage_root.mkdir(parents=True, exist_ok=True)
|
|
233
|
+
|
|
234
|
+
# Check storage capacity before starting any work
|
|
235
|
+
check_storage_capacity(file_path, storage_root)
|
|
236
|
+
|
|
237
|
+
# 1. Transcode if necessary
|
|
238
|
+
logger.debug("Checking transcoding requirement for %s", file_path)
|
|
239
|
+
temp_transcode_dir = TRANSCODING_DIR
|
|
240
|
+
temp_transcode_dir.mkdir(parents=True, exist_ok=True)
|
|
241
|
+
|
|
242
|
+
# Use a unique name for the potential transcoded file
|
|
243
|
+
temp_transcoded_output_path = (
|
|
244
|
+
temp_transcode_dir / f"{uuid.uuid4()}{original_suffix}"
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
transcoded_file_path = transcode_videofile_if_required(
|
|
249
|
+
input_path=file_path, output_path=temp_transcoded_output_path
|
|
250
|
+
)
|
|
251
|
+
if transcoded_file_path is None:
|
|
252
|
+
raise TranscodingError(
|
|
253
|
+
f"Transcoding check/process failed for {file_path}"
|
|
254
|
+
)
|
|
255
|
+
except Exception as e:
|
|
256
|
+
raise TranscodingError(f"Video transcoding failed: {e}") from e
|
|
257
|
+
|
|
258
|
+
logger.debug("Using file for hashing: %s", transcoded_file_path)
|
|
259
|
+
|
|
260
|
+
# 3. Check if hash already exists
|
|
261
|
+
if cls_model.check_hash_exists(video_hash=video_hash):
|
|
262
|
+
existing_video = cls_model.objects.get(video_hash=video_hash)
|
|
263
|
+
logger.warning(
|
|
264
|
+
"Video with hash %s already exists (UUID: %s)",
|
|
265
|
+
video_hash,
|
|
266
|
+
existing_video.video_hash,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Check if the existing video has a valid file
|
|
270
|
+
existing_raw_path = existing_video.get_raw_file_path()
|
|
271
|
+
if (
|
|
272
|
+
existing_video.has_raw
|
|
273
|
+
and existing_raw_path
|
|
274
|
+
and existing_raw_path.exists()
|
|
275
|
+
):
|
|
276
|
+
logger.warning(
|
|
277
|
+
"Video with hash %s already exists and file is present. Returning existing instance.",
|
|
278
|
+
video_hash,
|
|
279
|
+
)
|
|
280
|
+
# Clean up transcoded file if it was created temporarily
|
|
281
|
+
if transcoded_file_path != file_path and transcoded_file_path.exists():
|
|
282
|
+
transcoded_file_path.unlink(missing_ok=True)
|
|
283
|
+
return existing_video
|
|
284
|
+
|
|
285
|
+
logger.warning(
|
|
286
|
+
"Video with hash %s exists but file is missing. Deleting orphaned record.",
|
|
287
|
+
video_hash,
|
|
288
|
+
)
|
|
289
|
+
existing_video.delete()
|
|
290
|
+
|
|
291
|
+
filename = f"{video_hash}{transcoded_file_path.suffix}"
|
|
292
|
+
final_storage_path = video_dir / filename
|
|
293
|
+
|
|
294
|
+
# Ensure the DIRECTORY exists (video_dir), not the parent of a nested file
|
|
295
|
+
final_storage_path.parent.mkdir(parents=True, exist_ok=True)
|
|
296
|
+
|
|
297
|
+
# 5. Move or Copy the file to final storage using improved method
|
|
298
|
+
try:
|
|
299
|
+
if delete_source and transcoded_file_path == file_path:
|
|
300
|
+
logger.debug(
|
|
301
|
+
"Moving original file %s to %s", file_path, final_storage_path
|
|
302
|
+
)
|
|
303
|
+
atomic_move_with_fallback(file_path, final_storage_path)
|
|
304
|
+
elif delete_source and transcoded_file_path != file_path:
|
|
305
|
+
logger.debug(
|
|
306
|
+
"Moving transcoded file %s to %s",
|
|
307
|
+
transcoded_file_path,
|
|
308
|
+
final_storage_path,
|
|
309
|
+
)
|
|
310
|
+
atomic_move_with_fallback(transcoded_file_path, final_storage_path)
|
|
311
|
+
else:
|
|
312
|
+
logger.debug(
|
|
313
|
+
"Copying file %s to %s", transcoded_file_path, final_storage_path
|
|
314
|
+
)
|
|
315
|
+
atomic_copy_with_fallback(transcoded_file_path, final_storage_path)
|
|
316
|
+
if transcoded_file_path != file_path and transcoded_file_path.exists():
|
|
317
|
+
logger.debug(
|
|
318
|
+
"Cleaning up temporary transcoded file %s", transcoded_file_path
|
|
319
|
+
)
|
|
320
|
+
transcoded_file_path.unlink(missing_ok=True)
|
|
321
|
+
except InsufficientStorageError:
|
|
322
|
+
# Re-raise storage errors as-is
|
|
323
|
+
raise
|
|
324
|
+
except Exception as e:
|
|
325
|
+
raise RuntimeError(f"Failed to move file to final storage: {e}") from e
|
|
326
|
+
|
|
327
|
+
# 7. Get related objects
|
|
328
|
+
try:
|
|
329
|
+
center = Center.objects.get(name=center_name)
|
|
330
|
+
processor = (
|
|
331
|
+
EndoscopyProcessor.objects.get(name=processor_name)
|
|
332
|
+
if processor_name
|
|
333
|
+
else None
|
|
334
|
+
)
|
|
335
|
+
logger.debug(
|
|
336
|
+
"Found Center: %s, Processor: %s",
|
|
337
|
+
center.name,
|
|
338
|
+
processor.name if processor else "None",
|
|
339
|
+
)
|
|
340
|
+
except Center.DoesNotExist as e:
|
|
341
|
+
logger.error("Center '%s' not found", center_name)
|
|
342
|
+
if final_storage_path and final_storage_path.exists():
|
|
343
|
+
final_storage_path.unlink(missing_ok=True)
|
|
344
|
+
raise ValueError(f"Center '{center_name}' not found.") from e
|
|
345
|
+
except EndoscopyProcessor.DoesNotExist as e:
|
|
346
|
+
logger.error("Processor '%s' not found", processor_name)
|
|
347
|
+
if final_storage_path and final_storage_path.exists():
|
|
348
|
+
final_storage_path.unlink(missing_ok=True)
|
|
349
|
+
raise ValueError(f"Processor '{processor_name}' not found.") from e
|
|
350
|
+
|
|
351
|
+
# 8. Create the VideoFile instance
|
|
352
|
+
logger.info("Creating new VideoFile instance with hash: %s", video_hash)
|
|
353
|
+
# Store FileField path relative to storage root including the videos prefix
|
|
354
|
+
|
|
355
|
+
relative_name = path_utils.to_storage_relative(final_storage_path)
|
|
356
|
+
video = cls_model(
|
|
357
|
+
raw_file=relative_name,
|
|
358
|
+
processed_file=None,
|
|
359
|
+
center=center,
|
|
360
|
+
processor=processor,
|
|
361
|
+
original_file_name=original_file_name,
|
|
362
|
+
video_hash=video_hash,
|
|
363
|
+
processed_video_hash=None,
|
|
364
|
+
suffix=original_suffix,
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
# 9. Save the instance if requested
|
|
368
|
+
if save:
|
|
369
|
+
logger.info("Saving new VideoFile instance (Hash:%s", video_hash)
|
|
370
|
+
video.save()
|
|
371
|
+
logger.info(
|
|
372
|
+
"Successfully created VideoFile PK %s ",
|
|
373
|
+
video.pk,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
return video
|
|
377
|
+
|
|
378
|
+
except (InsufficientStorageError, TranscodingError, ValueError):
|
|
379
|
+
# Re-raise these specific errors as-is
|
|
380
|
+
raise
|
|
381
|
+
except Exception as e:
|
|
382
|
+
logger.error(
|
|
383
|
+
"Failed to create VideoFile from %s: (%s) %s",
|
|
384
|
+
file_path,
|
|
385
|
+
type(e).__name__,
|
|
386
|
+
e,
|
|
387
|
+
exc_info=True,
|
|
388
|
+
)
|
|
389
|
+
# Clean up any created files
|
|
390
|
+
if final_storage_path and final_storage_path.exists():
|
|
391
|
+
logger.warning("Cleaning up orphaned file: %s", final_storage_path)
|
|
392
|
+
final_storage_path.unlink(missing_ok=True)
|
|
393
|
+
if (
|
|
394
|
+
transcoded_file_path
|
|
395
|
+
and transcoded_file_path != file_path
|
|
396
|
+
and transcoded_file_path.exists()
|
|
397
|
+
):
|
|
398
|
+
logger.warning(
|
|
399
|
+
"Cleaning up orphaned transcoded file: %s", transcoded_file_path
|
|
400
|
+
)
|
|
401
|
+
transcoded_file_path.unlink(missing_ok=True)
|
|
402
|
+
raise RuntimeError(f"Video processing failed: {e}") from e
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
|
|
3
|
+
|
|
4
|
+
from django.db import transaction
|
|
5
|
+
|
|
6
|
+
from endoreg_db.helpers.download_segmentation_model import download_segmentation_model
|
|
7
|
+
|
|
8
|
+
# Added imports
|
|
9
|
+
|
|
10
|
+
# Configure logging
|
|
11
|
+
logger = logging.getLogger(__name__) # Changed from "video_file"
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from endoreg_db.models import VideoFile
|
|
15
|
+
|
|
16
|
+
# --- Pipeline 1 ---
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _pipe_1(
|
|
20
|
+
video_file: "VideoFile",
|
|
21
|
+
model_name: str,
|
|
22
|
+
model_meta_version: Optional[int] = None,
|
|
23
|
+
delete_frames_after: bool = False,
|
|
24
|
+
ocr_frame_fraction: float = 0.001,
|
|
25
|
+
ocr_cap: int = 10,
|
|
26
|
+
smooth_window_size_s: int = 1,
|
|
27
|
+
binarize_threshold: float = 0.5,
|
|
28
|
+
test_run: bool = False,
|
|
29
|
+
n_test_frames: int = 10,
|
|
30
|
+
) -> bool:
|
|
31
|
+
"""
|
|
32
|
+
Pipeline 1: Extract frames, text, predict, create segments, optionally delete frames.
|
|
33
|
+
"""
|
|
34
|
+
success = False # Initialize success flag
|
|
35
|
+
from endoreg_db.models import AiModel, LabelVideoSegment
|
|
36
|
+
|
|
37
|
+
from ...metadata import ModelMeta, VideoPredictionMeta
|
|
38
|
+
from .video_file_segments import _convert_sequences_to_db_segments # Added import
|
|
39
|
+
|
|
40
|
+
video_file.refresh_from_db()
|
|
41
|
+
video_file.update_video_meta()
|
|
42
|
+
|
|
43
|
+
logger.info(f"Starting Pipe 1 for video {video_file.video_hash}")
|
|
44
|
+
try:
|
|
45
|
+
# 1. Heavy I/O operations outside the transaction block
|
|
46
|
+
logger.info("Pipe 1: Extracting frames...")
|
|
47
|
+
video_file.extract_frames(
|
|
48
|
+
overwrite=False
|
|
49
|
+
) # Avoid overwriting if already extracted
|
|
50
|
+
|
|
51
|
+
logger.info("Pipe 1: Extracting text metadata...")
|
|
52
|
+
video_file.update_text_metadata(
|
|
53
|
+
ocr_frame_fraction=ocr_frame_fraction, cap=ocr_cap, overwrite=False
|
|
54
|
+
)
|
|
55
|
+
with transaction.atomic():
|
|
56
|
+
state = video_file.get_or_create_state()
|
|
57
|
+
if not state.frames_extracted:
|
|
58
|
+
logger.error(
|
|
59
|
+
"Pipe 1 failed: Frame extraction did not complete successfully."
|
|
60
|
+
)
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
# 3. Perform Initial Prediction
|
|
64
|
+
logger.info(f"Pipe 1: Performing prediction with model '{model_name}'...")
|
|
65
|
+
try:
|
|
66
|
+
ai_model_obj = AiModel.objects.get(name=model_name)
|
|
67
|
+
if model_meta_version is not None:
|
|
68
|
+
model_meta = ai_model_obj.metadata_versions.get(
|
|
69
|
+
version=model_meta_version
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
model_meta = ai_model_obj.get_latest_version()
|
|
73
|
+
except AiModel.DoesNotExist:
|
|
74
|
+
logger.error(f"Pipe 1 failed: Model '{model_name}' not found.")
|
|
75
|
+
try:
|
|
76
|
+
model_name = download_segmentation_model()
|
|
77
|
+
ai_model_obj = AiModel.objects.get(name=model_name)
|
|
78
|
+
if model_meta_version is not None:
|
|
79
|
+
model_meta = ai_model_obj.metadata_versions.get(
|
|
80
|
+
version=model_meta_version
|
|
81
|
+
)
|
|
82
|
+
else:
|
|
83
|
+
model_meta = ai_model_obj.get_latest_version()
|
|
84
|
+
except AiModel.DoesNotExist:
|
|
85
|
+
logger.error(f"Pipe 1 failed: Model '{model_name}' not found.")
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
except ModelMeta.DoesNotExist:
|
|
89
|
+
try:
|
|
90
|
+
model_name = download_segmentation_model()
|
|
91
|
+
ai_model_obj = AiModel.objects.get(name=model_name)
|
|
92
|
+
if model_meta_version is not None:
|
|
93
|
+
model_meta = ai_model_obj.metadata_versions.get(
|
|
94
|
+
version=model_meta_version
|
|
95
|
+
)
|
|
96
|
+
else:
|
|
97
|
+
model_meta = ai_model_obj.get_latest_version()
|
|
98
|
+
except ModelMeta.DoesNotExist:
|
|
99
|
+
logger.error(
|
|
100
|
+
f"Pipe 1 failed: ModelMeta version {model_meta_version} for model '{model_name}' not found."
|
|
101
|
+
)
|
|
102
|
+
return False
|
|
103
|
+
try:
|
|
104
|
+
sequences: Optional[Dict[str, List[Tuple[int, int]]]] = (
|
|
105
|
+
video_file.predict_video(
|
|
106
|
+
model_meta=model_meta,
|
|
107
|
+
smooth_window_size_s=smooth_window_size_s,
|
|
108
|
+
binarize_threshold=binarize_threshold,
|
|
109
|
+
test_run=test_run,
|
|
110
|
+
n_test_frames=n_test_frames,
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.error(f"Pipe 1 failed during prediction: {e}", exc_info=True)
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
if sequences is None:
|
|
118
|
+
logger.error("Pipe 1 failed: Prediction pipeline returned None.")
|
|
119
|
+
return False
|
|
120
|
+
logger.info("Pipe 1: Prediction complete.")
|
|
121
|
+
|
|
122
|
+
# --- Set and Save State ---
|
|
123
|
+
state.initial_prediction_completed = True
|
|
124
|
+
state.save(update_fields=["initial_prediction_completed"])
|
|
125
|
+
logger.info("Pipe 1: Set initial_prediction_completed state to True.")
|
|
126
|
+
|
|
127
|
+
logger.info(f"Pipe 1: Sequences returned from prediction: {sequences}")
|
|
128
|
+
if not sequences:
|
|
129
|
+
logger.warning(
|
|
130
|
+
"Pipe 1: Prediction returned empty sequences dictionary. No LabelVideoSegments will be created."
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# 4. Create LabelVideoSegments
|
|
134
|
+
logger.info("Pipe 1: Creating LabelVideoSegments from predictions...")
|
|
135
|
+
try:
|
|
136
|
+
video_prediction_meta = VideoPredictionMeta.objects.get(
|
|
137
|
+
video_file=video_file, model_meta=model_meta
|
|
138
|
+
)
|
|
139
|
+
logger.info(
|
|
140
|
+
f"Pipe 1: Calling _convert_sequences_to_db_segments for video {video_file.video_hash} with prediction meta {video_prediction_meta.pk}"
|
|
141
|
+
)
|
|
142
|
+
_convert_sequences_to_db_segments(
|
|
143
|
+
video=video_file,
|
|
144
|
+
sequences=sequences,
|
|
145
|
+
video_prediction_meta=video_prediction_meta,
|
|
146
|
+
)
|
|
147
|
+
video_file.sequences = sequences
|
|
148
|
+
video_file.save(update_fields=["sequences"])
|
|
149
|
+
state.lvs_created = True
|
|
150
|
+
state.save(update_fields=["lvs_created"])
|
|
151
|
+
logger.info("Pipe 1: Set lvs_created state to True.")
|
|
152
|
+
logger.info("Pipe 1: LabelVideoSegment creation complete.")
|
|
153
|
+
lvs_count_after = LabelVideoSegment.objects.filter(
|
|
154
|
+
video_file=video_file
|
|
155
|
+
).count()
|
|
156
|
+
logger.info(
|
|
157
|
+
f"Pipe 1: Found {lvs_count_after} LabelVideoSegments after conversion attempt."
|
|
158
|
+
)
|
|
159
|
+
except VideoPredictionMeta.DoesNotExist:
|
|
160
|
+
logger.error(
|
|
161
|
+
"Pipe 1 failed: Could not find VideoPredictionMeta after prediction."
|
|
162
|
+
)
|
|
163
|
+
raise
|
|
164
|
+
|
|
165
|
+
logger.info(f"Pipe 1 completed successfully for video {video_file.video_hash}")
|
|
166
|
+
success = True # Set success flag
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(
|
|
171
|
+
f"Pipe 1 failed for video {video_file.video_hash}: {e}", exc_info=True
|
|
172
|
+
)
|
|
173
|
+
return False
|
|
174
|
+
finally:
|
|
175
|
+
# 5. Optionally delete frames
|
|
176
|
+
if delete_frames_after and success: # Check success flag
|
|
177
|
+
logger.info("Pipe 1: Deleting frames after processing...")
|
|
178
|
+
try:
|
|
179
|
+
video_file.delete_frames()
|
|
180
|
+
logger.info("Pipe 1: Frame deletion complete.")
|
|
181
|
+
except Exception as e:
|
|
182
|
+
logger.error(f"Pipe 1 failed during frame deletion: {e}", exc_info=True)
|
|
183
|
+
else:
|
|
184
|
+
logger.info("Pipe 1: Frame deletion skipped.")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# --- Test after Pipe 1 ---
|
|
188
|
+
def _test_after_pipe_1(
|
|
189
|
+
video_file: "VideoFile", start_frame: int = 0, end_frame: int = 100
|
|
190
|
+
) -> bool:
|
|
191
|
+
"""
|
|
192
|
+
Simulates human annotation validation after Pipe 1.
|
|
193
|
+
Creates 'outside' segments and marks sensitive meta as verified.
|
|
194
|
+
"""
|
|
195
|
+
from ...label import Label, LabelVideoSegment
|
|
196
|
+
|
|
197
|
+
logger.info(f"Starting _test_after_pipe_1 for video {video_file.video_hash}")
|
|
198
|
+
try:
|
|
199
|
+
# 1. Create 'outside' LabelVideoSegments
|
|
200
|
+
try:
|
|
201
|
+
outside_label = Label.objects.get(name__iexact="outside")
|
|
202
|
+
logger.info(
|
|
203
|
+
f"Creating 'outside' annotation segment [{start_frame}-{end_frame}]"
|
|
204
|
+
)
|
|
205
|
+
# Create a segment - assuming custom_create handles saving
|
|
206
|
+
outside_segment = LabelVideoSegment.objects.create( # Assign to variable
|
|
207
|
+
video_file=video_file,
|
|
208
|
+
label=outside_label,
|
|
209
|
+
start_frame_number=start_frame,
|
|
210
|
+
end_frame_number=end_frame,
|
|
211
|
+
prediction_meta=None,
|
|
212
|
+
)
|
|
213
|
+
# Ensure the segment has a state and mark it as validated
|
|
214
|
+
segment_state, created = (
|
|
215
|
+
outside_segment.get_or_create_state()
|
|
216
|
+
) # Unpack the tuple
|
|
217
|
+
segment_state.is_validated = True
|
|
218
|
+
segment_state.save()
|
|
219
|
+
logger.info(
|
|
220
|
+
f"Marked 'outside' segment {outside_segment.pk} as validated. Created: {created}"
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
except Label.DoesNotExist:
|
|
224
|
+
logger.error("_test_after_pipe_1 failed: 'outside' Label not found.")
|
|
225
|
+
return False
|
|
226
|
+
except Exception as e:
|
|
227
|
+
logger.error(
|
|
228
|
+
f"_test_after_pipe_1 failed during segment creation: {e}", exc_info=True
|
|
229
|
+
)
|
|
230
|
+
return False
|
|
231
|
+
|
|
232
|
+
# 2. Set Sensitive Metadata state to verified
|
|
233
|
+
if video_file.sensitive_meta:
|
|
234
|
+
sm = video_file.sensitive_meta
|
|
235
|
+
st_state = sm.state
|
|
236
|
+
assert st_state, "SensitiveMeta state is None. Cannot set to verified."
|
|
237
|
+
logger.info("Setting sensitive meta state to verified.")
|
|
238
|
+
|
|
239
|
+
# Example: using a boolean field
|
|
240
|
+
video_file.sensitive_meta.state.dob_verified = True
|
|
241
|
+
video_file.sensitive_meta.state.names_verified = True
|
|
242
|
+
video_file.sensitive_meta.state.save() # Save the SensitiveMeta instance
|
|
243
|
+
logger.info("Sensitive meta state updated.")
|
|
244
|
+
|
|
245
|
+
else:
|
|
246
|
+
logger.warning("_test_after_pipe_1: No sensitive meta found to verify.")
|
|
247
|
+
|
|
248
|
+
logger.info(
|
|
249
|
+
f"_test_after_pipe_1 completed successfully for video {video_file.video_hash}"
|
|
250
|
+
)
|
|
251
|
+
return True
|
|
252
|
+
|
|
253
|
+
except Exception as e:
|
|
254
|
+
logger.error(
|
|
255
|
+
f"_test_after_pipe_1 failed for video {video_file.video_hash}: {e}",
|
|
256
|
+
exc_info=True,
|
|
257
|
+
)
|
|
258
|
+
return False
|