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,272 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import TYPE_CHECKING, Iterator, Optional
|
|
5
|
+
|
|
6
|
+
from django.db import transaction
|
|
7
|
+
|
|
8
|
+
from endoreg_db.utils.paths import ANONYM_VIDEO_DIR, data_paths
|
|
9
|
+
|
|
10
|
+
from ....utils import delete_field_file, ensure_local_file, storage_file_exists
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .video_file import VideoFile
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger("video_file")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _get_raw_file_path(video: "VideoFile") -> Optional[Path]:
|
|
19
|
+
"""Return the best-effort absolute path to the raw video on disk."""
|
|
20
|
+
if not (video.has_raw and video.raw_file.name):
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
# 1) Canonical: use Django's storage path
|
|
24
|
+
try:
|
|
25
|
+
direct_path = Path(video.raw_file.path)
|
|
26
|
+
if direct_path.is_file():
|
|
27
|
+
return direct_path.resolve()
|
|
28
|
+
else:
|
|
29
|
+
logger.debug(
|
|
30
|
+
"raw_file.path for video %s is not a regular file: %s",
|
|
31
|
+
video.video_hash,
|
|
32
|
+
direct_path,
|
|
33
|
+
)
|
|
34
|
+
except Exception as exc:
|
|
35
|
+
logger.debug(
|
|
36
|
+
"Could not access raw_file.path for video %s: %s",
|
|
37
|
+
video.video_hash,
|
|
38
|
+
exc,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# 2) Fallback: use just the filename and search in known dirs
|
|
42
|
+
raw_rel = Path(video.raw_file.name)
|
|
43
|
+
filename = raw_rel.name # strip any (possibly wrong) prefix
|
|
44
|
+
|
|
45
|
+
candidates = [
|
|
46
|
+
data_paths["import_video"] / filename,
|
|
47
|
+
data_paths["sensitive_video"] / filename,
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
for candidate in candidates:
|
|
51
|
+
if candidate.is_file():
|
|
52
|
+
return candidate
|
|
53
|
+
|
|
54
|
+
logger.warning(
|
|
55
|
+
"Raw video file '%s' not found in import/sensitive paths or via stored FileField path for video %s.",
|
|
56
|
+
video.raw_file.name,
|
|
57
|
+
video.video_hash,
|
|
58
|
+
)
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@contextmanager
|
|
63
|
+
def _ensure_local_raw_file(video: "VideoFile") -> Iterator[Path]:
|
|
64
|
+
"""Yield a local filesystem path for the raw file, downloading if required."""
|
|
65
|
+
if not video.has_raw:
|
|
66
|
+
raise ValueError(f"Video {video.video_hash} has no raw file")
|
|
67
|
+
|
|
68
|
+
with ensure_local_file(video.raw_file) as local_path:
|
|
69
|
+
yield local_path
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _get_processed_file_path(video: "VideoFile") -> Optional[Path]:
|
|
73
|
+
"""Returns the absolute Path object for the processed file, if it exists."""
|
|
74
|
+
processed_field = getattr(video, "processed_file", None)
|
|
75
|
+
if not (video.is_processed and processed_field and processed_field.name):
|
|
76
|
+
return None
|
|
77
|
+
try:
|
|
78
|
+
direct_path = Path(processed_field.path)
|
|
79
|
+
if direct_path.exists():
|
|
80
|
+
return direct_path.resolve()
|
|
81
|
+
except Exception as exc:
|
|
82
|
+
logger.debug(
|
|
83
|
+
"Could not access direct processed_file.path for video %s: %s",
|
|
84
|
+
video.video_hash,
|
|
85
|
+
exc,
|
|
86
|
+
)
|
|
87
|
+
direct_path = None
|
|
88
|
+
|
|
89
|
+
if processed_field and storage_file_exists(processed_field):
|
|
90
|
+
logger.debug(
|
|
91
|
+
"Processed file for %s available only via storage backend", video.video_hash
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
logger.warning(
|
|
95
|
+
"Could not get path for processed file of VideoFile %s: %s",
|
|
96
|
+
video.video_hash,
|
|
97
|
+
"path unavailable",
|
|
98
|
+
)
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@contextmanager
|
|
103
|
+
def _ensure_local_processed_file(video: "VideoFile") -> Iterator[Path]:
|
|
104
|
+
"""Yield a local path to the processed file, downloading if necessary."""
|
|
105
|
+
if not video.is_processed:
|
|
106
|
+
raise ValueError(f"Video {video.video_hash} has no processed file")
|
|
107
|
+
|
|
108
|
+
with ensure_local_file(video.processed_file) as local_path:
|
|
109
|
+
yield local_path
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@transaction.atomic
|
|
113
|
+
def _delete_with_file(video: "VideoFile", *args, **kwargs):
|
|
114
|
+
"""Deletes the VideoFile record and its associated physical files (raw, processed, frames)."""
|
|
115
|
+
# 1. Delete Frames (using the frame helper function via instance method)
|
|
116
|
+
try:
|
|
117
|
+
# delete_frames raises RuntimeError on state update failure
|
|
118
|
+
frame_delete_msg = video.delete_frames()
|
|
119
|
+
logger.info(
|
|
120
|
+
"Frame deletion result for video %s: %s", video.video_hash, frame_delete_msg
|
|
121
|
+
)
|
|
122
|
+
except Exception as frame_del_e:
|
|
123
|
+
# Log error but continue, as file deletion might still be possible
|
|
124
|
+
logger.error(
|
|
125
|
+
"Error during frame file/state deletion for video %s: %s",
|
|
126
|
+
video.video_hash,
|
|
127
|
+
frame_del_e,
|
|
128
|
+
exc_info=True,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# 2. Delete Raw File
|
|
132
|
+
raw_file_path = _get_raw_file_path(video)
|
|
133
|
+
if raw_file_path:
|
|
134
|
+
try:
|
|
135
|
+
if raw_file_path.exists():
|
|
136
|
+
raw_file_path.unlink()
|
|
137
|
+
logger.info(
|
|
138
|
+
"Deleted raw video file for %s: %s", video.video_hash, raw_file_path
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
logger.warning(
|
|
142
|
+
"Raw video file not found at %s for video %s, skipping deletion.",
|
|
143
|
+
raw_file_path,
|
|
144
|
+
video.video_hash,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
except Exception as e:
|
|
148
|
+
# Log error but continue
|
|
149
|
+
logger.error(
|
|
150
|
+
"Error deleting raw video file %s for video %s: %s",
|
|
151
|
+
raw_file_path,
|
|
152
|
+
video.video_hash,
|
|
153
|
+
e,
|
|
154
|
+
exc_info=True,
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
if delete_field_file(getattr(video, "raw_file", None), save=False):
|
|
158
|
+
logger.info("Deleted raw file from storage for video %s", video.video_hash)
|
|
159
|
+
else:
|
|
160
|
+
logger.warning(
|
|
161
|
+
"Raw video file not found during deletion for video %s.",
|
|
162
|
+
video.video_hash,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# 3. Delete Processed File
|
|
166
|
+
processed_file_path = _get_processed_file_path(video)
|
|
167
|
+
if processed_file_path:
|
|
168
|
+
try:
|
|
169
|
+
if processed_file_path.exists():
|
|
170
|
+
processed_file_path.unlink()
|
|
171
|
+
logger.info(
|
|
172
|
+
"Deleted processed video file for %s: %s",
|
|
173
|
+
video.video_hash,
|
|
174
|
+
processed_file_path,
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
logger.warning(
|
|
178
|
+
"Processed video file not found at %s for video %s, skipping deletion.",
|
|
179
|
+
processed_file_path,
|
|
180
|
+
video.video_hash,
|
|
181
|
+
)
|
|
182
|
+
except Exception as e:
|
|
183
|
+
# Log error but continue
|
|
184
|
+
logger.error(
|
|
185
|
+
"Error deleting processed video file %s for video %s: %s",
|
|
186
|
+
processed_file_path,
|
|
187
|
+
video.video_hash,
|
|
188
|
+
e,
|
|
189
|
+
exc_info=True,
|
|
190
|
+
)
|
|
191
|
+
else:
|
|
192
|
+
if delete_field_file(getattr(video, "processed_file", None), save=False):
|
|
193
|
+
logger.info(
|
|
194
|
+
"Deleted processed file from storage for video %s", video.video_hash
|
|
195
|
+
)
|
|
196
|
+
else:
|
|
197
|
+
logger.warning(
|
|
198
|
+
"Processed file missing in storage for video %s", video.video_hash
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# 4. Delete Database Record
|
|
202
|
+
try:
|
|
203
|
+
# Use 'super(type(video), video)' to call the parent's delete method
|
|
204
|
+
super(type(video), video).delete(*args, **kwargs)
|
|
205
|
+
logger.info(
|
|
206
|
+
"Deleted VideoFile database record PK %s (UUID: %s).",
|
|
207
|
+
video.pk,
|
|
208
|
+
video.video_hash,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return f"Successfully deleted VideoFile {video.video_hash} and attempted file cleanup."
|
|
212
|
+
except Exception as e:
|
|
213
|
+
logger.error(
|
|
214
|
+
"Error deleting VideoFile database record PK %s (UUID: %s): %s",
|
|
215
|
+
video.pk,
|
|
216
|
+
video.video_hash,
|
|
217
|
+
e,
|
|
218
|
+
exc_info=True,
|
|
219
|
+
)
|
|
220
|
+
raise # Re-raise the exception for DB deletion failure
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _get_base_frame_dir(video: "VideoFile") -> Path:
|
|
224
|
+
"""Gets the base directory path for storing extracted frames."""
|
|
225
|
+
# Assuming data_paths['frame'] is the root directory for all frame storage
|
|
226
|
+
return data_paths["frame"] / str(video.video_hash)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _set_frame_dir(video: "VideoFile", force_update: bool = False):
|
|
230
|
+
"""Sets the frame_dir field based on the video's UUID."""
|
|
231
|
+
target_dir = _get_base_frame_dir(video)
|
|
232
|
+
target_path_str = target_dir.as_posix() # Store as POSIX path string
|
|
233
|
+
|
|
234
|
+
if not video.frame_dir or video.frame_dir != target_path_str or force_update:
|
|
235
|
+
video.frame_dir = target_path_str
|
|
236
|
+
logger.info(
|
|
237
|
+
"Set frame_dir for video %s to %s", video.video_hash, video.frame_dir
|
|
238
|
+
)
|
|
239
|
+
# Avoid saving if called from within the save method itself
|
|
240
|
+
if not getattr(video, "_saving", False):
|
|
241
|
+
video.save(update_fields=["frame_dir"])
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _get_frame_dir_path(video: "VideoFile") -> Optional[Path]:
|
|
245
|
+
"""Returns the Path object for the frame directory, if set."""
|
|
246
|
+
if not video.frame_dir:
|
|
247
|
+
_set_frame_dir(video)
|
|
248
|
+
|
|
249
|
+
return Path(video.frame_dir)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _get_temp_anonymized_frame_dir(video: "VideoFile") -> Path:
|
|
253
|
+
"""Gets the path for the temporary directory used during anonymization frame creation."""
|
|
254
|
+
base_frame_dir = _get_base_frame_dir(video)
|
|
255
|
+
# Place temp dir alongside the final frame dir but with a prefix/suffix
|
|
256
|
+
anon_dir = base_frame_dir.parent / f"anonymizing_{base_frame_dir.name}"
|
|
257
|
+
return anon_dir
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _get_target_anonymized_video_path(video: "VideoFile") -> Path:
|
|
261
|
+
"""Determines the target path for the anonymized/processed video file."""
|
|
262
|
+
if not video.has_raw or not video.raw_file.name:
|
|
263
|
+
# If raw is gone, maybe base it on UUID? Requires careful thought.
|
|
264
|
+
# For now, assume raw is needed to determine the original filename base.
|
|
265
|
+
raise ValueError(
|
|
266
|
+
"Cannot determine target anonymized path without a raw file reference."
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Use the filename part of the raw file's relative path
|
|
270
|
+
raw_path_relative = Path(video.raw_file.name)
|
|
271
|
+
# Place it in the ANONYM_VIDEO_DIR using the same filename
|
|
272
|
+
return ANONYM_VIDEO_DIR / raw_path_relative.name
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
# Import functions from submodule files to make them available directly
|
|
4
|
+
from .text_meta import _update_text_metadata
|
|
5
|
+
from .video_meta import _update_video_meta
|
|
6
|
+
from .initialize_video_specs import _initialize_video_specs
|
|
7
|
+
from .get_fps import _get_fps
|
|
8
|
+
from .get_endo_roi import _get_endo_roi
|
|
9
|
+
from .get_crop_template import _get_crop_template
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
# Define __all__ if you want to control what `from .video_file_meta import *` imports
|
|
15
|
+
__all__ = [
|
|
16
|
+
"_update_text_metadata",
|
|
17
|
+
"_update_video_meta",
|
|
18
|
+
"_initialize_video_specs",
|
|
19
|
+
"_get_fps",
|
|
20
|
+
"_get_endo_roi",
|
|
21
|
+
"_get_crop_template",
|
|
22
|
+
]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
3
|
+
|
|
4
|
+
from .get_endo_roi import _get_endo_roi
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from ..video_file import VideoFile
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_crop_template(video: "VideoFile") -> Optional[List[int]]:
|
|
13
|
+
"""Generates a crop template [y1, y2, x1, x2] from the endo ROI."""
|
|
14
|
+
endo_roi = _get_endo_roi(video) # Use the helper function
|
|
15
|
+
if not endo_roi:
|
|
16
|
+
logger.warning(
|
|
17
|
+
"Cannot generate crop template for video %s: Endo ROI not available.",
|
|
18
|
+
video.video_hash,
|
|
19
|
+
)
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
x = endo_roi["x"]
|
|
23
|
+
y = endo_roi["y"]
|
|
24
|
+
width = endo_roi["width"]
|
|
25
|
+
height = endo_roi["height"]
|
|
26
|
+
|
|
27
|
+
# Validate dimensions
|
|
28
|
+
if None in [x, y, width, height] or width <= 0 or height <= 0:
|
|
29
|
+
logger.warning(
|
|
30
|
+
"Invalid ROI dimensions for video %s: %s", video.video_hash, endo_roi
|
|
31
|
+
)
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
# Ensure crop boundaries are within image dimensions if available
|
|
35
|
+
img_h, img_w = video.height, video.width
|
|
36
|
+
if img_h and img_w:
|
|
37
|
+
y1 = max(0, y)
|
|
38
|
+
y2 = min(img_h, y + height)
|
|
39
|
+
x1 = max(0, x)
|
|
40
|
+
x2 = min(img_w, x + width)
|
|
41
|
+
if y1 >= y2 or x1 >= x2:
|
|
42
|
+
logger.warning(
|
|
43
|
+
"Calculated crop template has zero or negative size for video %s. ROI: %s, Img: %dx%d",
|
|
44
|
+
video.video_hash,
|
|
45
|
+
endo_roi,
|
|
46
|
+
img_w,
|
|
47
|
+
img_h,
|
|
48
|
+
)
|
|
49
|
+
return None
|
|
50
|
+
crop_template = [y1, y2, x1, x2]
|
|
51
|
+
else:
|
|
52
|
+
# Proceed without boundary check if image dimensions unknown
|
|
53
|
+
crop_template = [y, y + height, x, x + width]
|
|
54
|
+
|
|
55
|
+
logger.debug(
|
|
56
|
+
"Generated crop template for video %s: %s", video.video_hash, crop_template
|
|
57
|
+
)
|
|
58
|
+
return crop_template
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Dict, Optional
|
|
3
|
+
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from ..video_file import VideoFile
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _get_endo_roi(video: "VideoFile") -> Optional[Dict[str, int]]:
|
|
11
|
+
"""
|
|
12
|
+
Gets the endoscope region of interest (ROI) dictionary from the linked VideoMeta.
|
|
13
|
+
|
|
14
|
+
The ROI dictionary typically contains 'x', 'y', 'width', 'height'.
|
|
15
|
+
Returns None if VideoMeta is not linked or ROI is not properly defined.
|
|
16
|
+
"""
|
|
17
|
+
if not video.video_meta:
|
|
18
|
+
logger.warning(
|
|
19
|
+
"VideoMeta not linked for video %s. Cannot get endo ROI.", video.video_hash
|
|
20
|
+
)
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
# Assuming VideoMeta has a method get_endo_roi()
|
|
25
|
+
endo_roi = video.video_meta.get_endo_roi()
|
|
26
|
+
# Basic validation
|
|
27
|
+
if (
|
|
28
|
+
isinstance(endo_roi, dict)
|
|
29
|
+
and all(k in endo_roi for k in ("x", "y", "width", "height"))
|
|
30
|
+
and all(
|
|
31
|
+
isinstance(v, int) and not isinstance(v, bool)
|
|
32
|
+
for v in endo_roi.values()
|
|
33
|
+
)
|
|
34
|
+
):
|
|
35
|
+
cleaned_roi = {
|
|
36
|
+
k: int(endo_roi[k] or 0) for k in ("x", "y", "width", "height")
|
|
37
|
+
}
|
|
38
|
+
logger.debug(
|
|
39
|
+
"Retrieved endo ROI for video %s: %s", video.video_hash, cleaned_roi
|
|
40
|
+
)
|
|
41
|
+
return cleaned_roi
|
|
42
|
+
else:
|
|
43
|
+
logger.warning(
|
|
44
|
+
"Endo ROI not fully defined or invalid in VideoMeta for video %s. ROI: %s",
|
|
45
|
+
video.video_hash,
|
|
46
|
+
endo_roi,
|
|
47
|
+
)
|
|
48
|
+
return None
|
|
49
|
+
except AttributeError:
|
|
50
|
+
logger.error(
|
|
51
|
+
"VideoMeta object for video %s does not have a 'get_endo_roi' method.",
|
|
52
|
+
video.video_hash,
|
|
53
|
+
)
|
|
54
|
+
return None
|
|
55
|
+
except Exception as e:
|
|
56
|
+
logger.error(
|
|
57
|
+
"Error getting endo ROI from VideoMeta for video %s: %s",
|
|
58
|
+
video.video_hash,
|
|
59
|
+
e,
|
|
60
|
+
exc_info=True,
|
|
61
|
+
)
|
|
62
|
+
return None
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import cv2
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ..video_file import VideoFile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _validate_video_path(video_path: Path):
|
|
12
|
+
"""
|
|
13
|
+
Validates that the provided path is an existing video file.
|
|
14
|
+
|
|
15
|
+
Raises:
|
|
16
|
+
TypeError: If `video_path` is not a Path object.
|
|
17
|
+
FileNotFoundError: If the file does not exist at the specified path.
|
|
18
|
+
IsADirectoryError: If the path points to a directory instead of a file.
|
|
19
|
+
"""
|
|
20
|
+
if not isinstance(video_path, Path):
|
|
21
|
+
raise TypeError("video_path must be a Path object")
|
|
22
|
+
if not video_path.exists():
|
|
23
|
+
raise FileNotFoundError(f"Video file not found at {video_path}")
|
|
24
|
+
if not video_path.is_file():
|
|
25
|
+
raise IsADirectoryError(f"Path is a directory, not a file: {video_path}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _get_fps(video: "VideoFile") -> float:
|
|
32
|
+
"""
|
|
33
|
+
Determine and return the frames per second (FPS) of a video associated with a VideoFile instance.
|
|
34
|
+
|
|
35
|
+
Attempts to retrieve FPS from the instance itself, its linked VideoMeta, or by direct analysis of the raw video file using OpenCV. Updates and saves the FPS value to the instance if successfully determined. Raises a ValueError if FPS cannot be determined by any method.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
float: The frames per second (FPS) of the video.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ValueError: If the FPS cannot be determined from any available source.
|
|
42
|
+
"""
|
|
43
|
+
from .video_meta import _update_video_meta
|
|
44
|
+
|
|
45
|
+
if video.fps is not None:
|
|
46
|
+
return video.fps
|
|
47
|
+
|
|
48
|
+
logger.debug("FPS not set on instance %s, checking VideoMeta.", video.video_hash)
|
|
49
|
+
|
|
50
|
+
if not video.video_meta:
|
|
51
|
+
logger.info("VideoMeta not linked for %s, attempting update.", video.video_hash)
|
|
52
|
+
|
|
53
|
+
_update_video_meta(video, save_instance=True) # Call the helper function
|
|
54
|
+
|
|
55
|
+
# Check again after potential update
|
|
56
|
+
if video.fps is not None:
|
|
57
|
+
return video.fps
|
|
58
|
+
elif video.video_meta and video.video_meta.fps is not None:
|
|
59
|
+
logger.info(
|
|
60
|
+
"Retrieved FPS %.2f from VideoMeta for %s.",
|
|
61
|
+
video.video_meta.fps,
|
|
62
|
+
video.video_hash,
|
|
63
|
+
)
|
|
64
|
+
_fps = video.video_meta.fps
|
|
65
|
+
try:
|
|
66
|
+
_fps = float(_fps)
|
|
67
|
+
except (TypeError, ValueError):
|
|
68
|
+
logger.warning(
|
|
69
|
+
"Invalid FPS value %.2f in VideoMeta for video %s.",
|
|
70
|
+
video.video_meta.fps,
|
|
71
|
+
video.video_hash,
|
|
72
|
+
)
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"Could not determine FPS for video {video.video_hash} due to invalid VideoMeta FPS value."
|
|
75
|
+
)
|
|
76
|
+
video.fps = _fps
|
|
77
|
+
# Avoid saving if called from within the save method itself
|
|
78
|
+
if not getattr(video, "_saving", False):
|
|
79
|
+
video.save(update_fields=["fps"])
|
|
80
|
+
return _fps
|
|
81
|
+
else:
|
|
82
|
+
logger.warning(
|
|
83
|
+
"Could not determine FPS from VideoMeta for video %s. Trying direct raw file access.",
|
|
84
|
+
video.video_hash,
|
|
85
|
+
)
|
|
86
|
+
try:
|
|
87
|
+
if video.has_raw:
|
|
88
|
+
video_path = video.get_raw_file_path() # Use helper
|
|
89
|
+
if video_path and video_path.exists():
|
|
90
|
+
cap = cv2.VideoCapture(video_path.as_posix())
|
|
91
|
+
if not cap.isOpened():
|
|
92
|
+
raise IOError(f"Cannot open video file: {video_path}")
|
|
93
|
+
try:
|
|
94
|
+
fps = _get_fps_from_property(cap)
|
|
95
|
+
|
|
96
|
+
if fps is None or fps <= 0:
|
|
97
|
+
# Reset video capture to the beginning for manual calculation
|
|
98
|
+
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
|
|
99
|
+
fps = _calculate_fps_manually(cap, video_path)
|
|
100
|
+
finally:
|
|
101
|
+
cap.release()
|
|
102
|
+
if fps and fps > 0:
|
|
103
|
+
video.fps = fps
|
|
104
|
+
logger.info(
|
|
105
|
+
"Determined FPS %.2f directly from file for %s.",
|
|
106
|
+
video.fps,
|
|
107
|
+
video.video_hash,
|
|
108
|
+
)
|
|
109
|
+
if not getattr(video, "_saving", False):
|
|
110
|
+
video.save(update_fields=["fps"])
|
|
111
|
+
return fps
|
|
112
|
+
else:
|
|
113
|
+
logger.warning(
|
|
114
|
+
"Could not determine a valid FPS for video file %s.",
|
|
115
|
+
video_path,
|
|
116
|
+
)
|
|
117
|
+
elif video_path:
|
|
118
|
+
logger.warning(
|
|
119
|
+
"Raw file path %s does not exist for direct FPS check.",
|
|
120
|
+
video_path,
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
logger.warning("Raw file path is None for direct FPS check.")
|
|
124
|
+
else:
|
|
125
|
+
logger.warning("Raw file not available for direct FPS check.")
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error(
|
|
129
|
+
"Error getting FPS directly from file %s: %s",
|
|
130
|
+
video.raw_file.name if video.has_raw else "N/A",
|
|
131
|
+
e,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Could not determine FPS for video {video.video_hash}. Ensure the video file is valid and accessible."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# TODO Refactor to utils / check if similar function exists in utils
|
|
140
|
+
def _get_fps_from_property(cap: cv2.VideoCapture) -> float:
|
|
141
|
+
"""
|
|
142
|
+
Retrieve the frames per second (FPS) from an OpenCV video capture object using the appropriate property for the OpenCV version.
|
|
143
|
+
|
|
144
|
+
Parameters:
|
|
145
|
+
cap: An OpenCV video capture object.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
float: The FPS value obtained from the video capture properties, or 0.0 if unavailable.
|
|
149
|
+
"""
|
|
150
|
+
return cap.get(cv2.CAP_PROP_FPS)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _calculate_fps_manually(cap, video_path: Path) -> float:
|
|
154
|
+
"""
|
|
155
|
+
Estimate the frames per second (FPS) of a video by reading all frames and dividing the total frame count by the elapsed time.
|
|
156
|
+
|
|
157
|
+
Parameters:
|
|
158
|
+
cap: An OpenCV video capture object positioned at the start of the video.
|
|
159
|
+
video_path (Path): Path to the video file, used for logging.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
float: The estimated FPS, or 0.0 if the duration is zero or calculation fails.
|
|
163
|
+
"""
|
|
164
|
+
logger.warning(
|
|
165
|
+
f"Could not get a valid FPS for {video_path}. Trying to calculate manually."
|
|
166
|
+
)
|
|
167
|
+
# This is less accurate and slower
|
|
168
|
+
num_frames = 0
|
|
169
|
+
start_time = cv2.getTickCount()
|
|
170
|
+
while True:
|
|
171
|
+
ret, _ = cap.read()
|
|
172
|
+
if not ret:
|
|
173
|
+
break
|
|
174
|
+
num_frames += 1
|
|
175
|
+
end_time = cv2.getTickCount()
|
|
176
|
+
seconds = (end_time - start_time) / cv2.getTickFrequency()
|
|
177
|
+
if seconds > 0:
|
|
178
|
+
return num_frames / seconds
|
|
179
|
+
|
|
180
|
+
logger.error(
|
|
181
|
+
f"Manual FPS calculation failed for {video_path} due to zero duration."
|
|
182
|
+
)
|
|
183
|
+
return 0.0
|