endoreg-db 0.4.5__py3-none-any.whl → 0.8.6.3__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.
- endoreg_db/admin.py +90 -1
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +12 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +92 -0
- endoreg_db/config/env.py +101 -0
- endoreg_db/data/__init__.py +76 -4
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
- 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_meta/default_multilabel_classification.yaml +27 -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/center/data.yaml +40 -9
- endoreg_db/data/center_shift/ukw.yaml +9 -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/misc.yaml +1 -2
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +2 -2
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +6 -6
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/endoscopy_processor/data.yaml +3 -0
- endoreg_db/data/event/cardiology.yaml +0 -13
- endoreg_db/data/examination/examinations/data.yaml +34 -28
- endoreg_db/data/examination/type/data.yaml +12 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +424 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +160 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/finding/complication.yaml +16 -0
- endoreg_db/data/finding/data.yaml +105 -0
- endoreg_db/data/finding/examination_setting.yaml +16 -0
- endoreg_db/data/finding/medication_related.yaml +18 -0
- endoreg_db/data/finding/outcome.yaml +12 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +43 -0
- endoreg_db/data/gender/data.yaml +24 -0
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -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 +7 -1
- endoreg_db/data/lab_value/coagulation.yaml +6 -1
- endoreg_db/data/lab_value/electrolytes.yaml +39 -1
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
- endoreg_db/data/lab_value/hematology.yaml +17 -2
- endoreg_db/data/lab_value/hormones.yaml +6 -0
- endoreg_db/data/lab_value/lipids.yaml +12 -3
- endoreg_db/data/lab_value/misc.yaml +48 -2
- endoreg_db/data/lab_value/renal_function.yaml +2 -1
- 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/medication/anticoagulation.yaml +5 -5
- endoreg_db/data/medication/tah.yaml +5 -5
- endoreg_db/data/medication_indication/anticoagulation.yaml +48 -53
- endoreg_db/data/medication_intake_time/base.yaml +4 -4
- 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 +30 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/pdf_type/data.yaml +27 -9
- 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/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +5 -0
- endoreg_db/data/requirement/age.yaml +26 -0
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/gender.yaml +25 -0
- endoreg_db/data/requirement/lab_value.yaml +441 -0
- endoreg_db/data/requirement/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/age.yaml +13 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +52 -0
- endoreg_db/data/requirement_set_type/data.yaml +20 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +165 -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_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
- endoreg_db/data/unit/concentration.yaml +23 -0
- endoreg_db/data/unit/time.yaml +36 -1
- endoreg_db/exceptions.py +19 -0
- endoreg_db/forms/__init__.py +3 -1
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +18 -0
- endoreg_db/forms/patient_form.py +27 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/questionnaires/tto_questionnaire.py +19 -19
- endoreg_db/helpers/count_db.py +45 -0
- endoreg_db/helpers/data_loader.py +208 -0
- endoreg_db/helpers/default_objects.py +378 -0
- endoreg_db/helpers/download_segmentation_model.py +31 -0
- endoreg_db/helpers/interact.py +6 -0
- endoreg_db/helpers/test_video_helper.py +119 -0
- endoreg_db/logger_conf.py +140 -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 +125 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +115 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
- endoreg_db/management/commands/fix_video_paths.py +165 -0
- endoreg_db/management/commands/import_fallback_video.py +203 -0
- endoreg_db/management/commands/import_report.py +298 -0
- endoreg_db/management/commands/import_video.py +423 -0
- endoreg_db/management/commands/import_video_with_classification.py +367 -0
- endoreg_db/management/commands/init_default_ai_model.py +112 -0
- endoreg_db/management/commands/load_ai_model_data.py +58 -26
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +174 -118
- endoreg_db/management/commands/load_center_data.py +46 -21
- endoreg_db/management/commands/{load_logging_data.py → load_contraindication_data.py} +4 -2
- endoreg_db/management/commands/load_disease_data.py +29 -7
- endoreg_db/management/commands/{load_endoscope_type_data.py → load_endoscope_data.py} +30 -7
- endoreg_db/management/commands/load_examination_indication_data.py +86 -0
- endoreg_db/management/commands/load_finding_data.py +128 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +0 -1
- endoreg_db/management/commands/load_information_source.py +13 -7
- endoreg_db/management/commands/load_lab_value_data.py +3 -3
- endoreg_db/management/commands/load_medication_data.py +83 -21
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/{load_medication_intake_time_data.py → load_organ_data.py} +7 -5
- endoreg_db/management/commands/load_qualification_data.py +59 -0
- endoreg_db/management/commands/load_requirement_data.py +180 -0
- endoreg_db/management/commands/load_risk_data.py +56 -0
- endoreg_db/management/commands/load_shift_data.py +60 -0
- endoreg_db/management/commands/load_tag_data.py +57 -0
- endoreg_db/management/commands/register_ai_model.py +1 -1
- endoreg_db/management/commands/setup_endoreg_db.py +381 -0
- endoreg_db/management/commands/start_filewatcher.py +106 -0
- endoreg_db/management/commands/storage_management.py +548 -0
- endoreg_db/management/commands/summarize_db_content.py +189 -0
- endoreg_db/management/commands/validate_video.py +204 -0
- endoreg_db/management/commands/validate_video_files.py +161 -0
- endoreg_db/management/commands/video_validation.py +22 -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 +1234 -944
- endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
- endoreg_db/migrations/0003_add_center_display_name.py +30 -0
- endoreg_db/models/__init__.py +339 -53
- endoreg_db/models/administration/__init__.py +116 -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 +156 -0
- endoreg_db/models/{ai_model → administration/ai}/model_type.py +19 -4
- endoreg_db/models/administration/case/__init__.py +19 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/{case_template → administration/case/case_template}/__init__.py +10 -1
- endoreg_db/models/{case_template → administration/case/case_template}/case_template.py +60 -16
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule.py +6 -13
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule_value.py +21 -8
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_type.py +1 -3
- endoreg_db/models/{center → administration/center}/__init__.py +9 -0
- endoreg_db/models/administration/center/center.py +67 -0
- endoreg_db/models/administration/center/center_product.py +64 -0
- endoreg_db/models/administration/center/center_resource.py +49 -0
- endoreg_db/models/administration/center/center_shift.py +88 -0
- endoreg_db/models/administration/center/center_waste.py +30 -0
- endoreg_db/models/administration/permissions/__init__.py +44 -0
- endoreg_db/models/administration/person/__init__.py +24 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +35 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
- endoreg_db/models/administration/person/employee/employee_type.py +42 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +54 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/{persons → administration/person/names}/first_name.py +1 -1
- endoreg_db/models/{persons → administration/person/names}/last_name.py +2 -3
- endoreg_db/models/administration/person/patient/__init__.py +5 -0
- endoreg_db/models/administration/person/patient/patient.py +460 -0
- endoreg_db/models/administration/person/profession/__init__.py +24 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
- endoreg_db/models/administration/product/__init__.py +14 -0
- endoreg_db/models/administration/product/product.py +97 -0
- endoreg_db/models/administration/product/product_group.py +39 -0
- endoreg_db/models/administration/product/product_material.py +54 -0
- endoreg_db/models/{product → administration/product}/product_weight.py +21 -0
- endoreg_db/models/{product → administration/product}/reference_product.py +44 -13
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +37 -0
- endoreg_db/models/administration/qualification/qualification_type.py +35 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +69 -0
- endoreg_db/models/administration/shift/shift.py +51 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/label/__init__.py +24 -1
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +84 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
- endoreg_db/models/label/label.py +53 -54
- endoreg_db/models/label/label_set.py +53 -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 +41 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
- endoreg_db/models/label/video_segmentation_label.py +31 -0
- endoreg_db/models/label/video_segmentation_labelset.py +27 -0
- endoreg_db/models/media/__init__.py +16 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +111 -0
- endoreg_db/models/media/pdf/__init__.py +11 -0
- endoreg_db/models/media/pdf/raw_pdf.py +757 -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 +77 -0
- endoreg_db/models/media/video/__init__.py +8 -0
- endoreg_db/models/media/video/create_from_file.py +358 -0
- endoreg_db/models/media/video/pipe_1.py +213 -0
- endoreg_db/models/media/video/pipe_2.py +105 -0
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file.py +825 -0
- endoreg_db/models/media/video/video_file_ai.py +443 -0
- endoreg_db/models/media/video/video_file_anonymize.py +349 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -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 +104 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +141 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/media/video/video_file_io.py +168 -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 +45 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
- endoreg_db/models/media/video/video_file_segments.py +209 -0
- endoreg_db/models/media/video/video_metadata.py +65 -0
- endoreg_db/models/media/video/video_processing.py +152 -0
- endoreg_db/models/medical/__init__.py +146 -0
- endoreg_db/models/medical/contraindication/__init__.py +17 -0
- endoreg_db/models/medical/disease.py +156 -0
- endoreg_db/models/medical/event.py +137 -0
- endoreg_db/models/medical/examination/__init__.py +9 -0
- endoreg_db/models/medical/examination/examination.py +148 -0
- endoreg_db/models/medical/examination/examination_indication.py +278 -0
- endoreg_db/models/medical/examination/examination_time.py +49 -0
- endoreg_db/models/medical/examination/examination_time_type.py +41 -0
- endoreg_db/models/medical/examination/examination_type.py +48 -0
- endoreg_db/models/medical/finding/__init__.py +18 -0
- endoreg_db/models/medical/finding/finding.py +96 -0
- endoreg_db/models/medical/finding/finding_classification.py +142 -0
- endoreg_db/models/medical/finding/finding_intervention.py +52 -0
- endoreg_db/models/medical/finding/finding_type.py +35 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +65 -0
- endoreg_db/models/{hardware → medical/hardware}/endoscopy_processor.py +68 -29
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +419 -0
- endoreg_db/models/medical/medication/__init__.py +19 -0
- endoreg_db/models/medical/medication/medication.py +31 -0
- endoreg_db/models/medical/medication/medication_indication.py +50 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +39 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +44 -0
- endoreg_db/models/medical/medication/medication_schedule.py +45 -0
- endoreg_db/models/medical/organ/__init__.py +35 -0
- endoreg_db/models/medical/patient/__init__.py +56 -0
- endoreg_db/models/medical/patient/medication_examples.py +38 -0
- endoreg_db/models/medical/patient/patient_disease.py +63 -0
- endoreg_db/models/medical/patient/patient_event.py +75 -0
- endoreg_db/models/medical/patient/patient_examination.py +249 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +44 -0
- endoreg_db/models/medical/patient/patient_finding.py +357 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +40 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
- endoreg_db/models/{persons → medical}/patient/patient_lab_value.py +68 -22
- endoreg_db/models/medical/patient/patient_medication.py +104 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +72 -0
- endoreg_db/models/medical/risk/risk_type.py +51 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/metadata/model_meta.py +206 -0
- endoreg_db/models/metadata/model_meta_logic.py +343 -0
- endoreg_db/models/{data_file/metadata → metadata}/pdf_meta.py +32 -13
- endoreg_db/models/metadata/sensitive_meta.py +288 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +1048 -0
- endoreg_db/models/metadata/video_meta.py +332 -0
- endoreg_db/models/metadata/video_prediction_logic.py +190 -0
- endoreg_db/models/metadata/video_prediction_meta.py +270 -0
- endoreg_db/models/other/__init__.py +36 -1
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +125 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +94 -0
- endoreg_db/models/{persons → other}/gender.py +8 -3
- endoreg_db/models/other/information_source.py +159 -0
- endoreg_db/models/other/material.py +14 -2
- endoreg_db/models/other/resource.py +6 -2
- endoreg_db/models/other/tag.py +27 -0
- endoreg_db/models/other/transport_route.py +15 -3
- endoreg_db/models/{unit.py → other/unit.py} +16 -6
- endoreg_db/models/other/waste.py +10 -3
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +767 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +95 -0
- endoreg_db/models/requirement/requirement_operator.py +176 -0
- endoreg_db/models/requirement/requirement_set.py +287 -0
- endoreg_db/models/rule/__init__.py +13 -0
- endoreg_db/models/{rules → rule}/rule.py +6 -3
- endoreg_db/models/{rules → rule}/rule_attribute_dtype.py +0 -2
- endoreg_db/models/{rules → rule}/rule_type.py +0 -2
- endoreg_db/models/{rules → rule}/ruleset.py +0 -2
- endoreg_db/models/state/__init__.py +12 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/audit_ledger.py +150 -0
- endoreg_db/models/state/label_video_segment.py +22 -0
- endoreg_db/models/state/raw_pdf.py +187 -0
- endoreg_db/models/state/sensitive_meta.py +46 -0
- endoreg_db/models/state/video.py +232 -0
- endoreg_db/models/upload_job.py +99 -0
- endoreg_db/models/utils.py +135 -0
- endoreg_db/renames.yml +8 -0
- endoreg_db/root_urls.py +9 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +27 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
- endoreg_db/serializers/__init__.py +118 -10
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +223 -0
- endoreg_db/serializers/_old/raw_video_meta_validation.py +179 -0
- endoreg_db/serializers/_old/video.py +71 -0
- endoreg_db/serializers/administration/__init__.py +14 -0
- endoreg_db/serializers/administration/ai/__init__.py +10 -0
- endoreg_db/serializers/administration/ai/active_model.py +10 -0
- endoreg_db/serializers/administration/ai/ai_model.py +18 -0
- endoreg_db/serializers/administration/ai/model_type.py +10 -0
- endoreg_db/serializers/administration/center.py +9 -0
- endoreg_db/serializers/administration/gender.py +9 -0
- endoreg_db/serializers/anonymization.py +69 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +46 -0
- endoreg_db/serializers/examination/dropdown.py +21 -0
- endoreg_db/serializers/examination_serializer.py +12 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +54 -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 +13 -0
- endoreg_db/serializers/label/__init__.py +7 -0
- endoreg_db/serializers/label/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/__init__.py +7 -0
- endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
- endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
- endoreg_db/serializers/meta/__init__.py +19 -0
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
- endoreg_db/serializers/meta/report_meta.py +53 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -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 +182 -0
- endoreg_db/serializers/misc/sensitive_patient_data.py +120 -0
- endoreg_db/serializers/misc/stats.py +33 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +71 -0
- endoreg_db/serializers/patient/__init__.py +11 -0
- endoreg_db/serializers/patient/patient.py +86 -0
- endoreg_db/serializers/patient/patient_dropdown.py +27 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
- endoreg_db/serializers/pdf/__init__.py +5 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
- endoreg_db/serializers/report/__init__.py +9 -0
- endoreg_db/serializers/report/mixins.py +45 -0
- endoreg_db/serializers/report/report.py +105 -0
- endoreg_db/serializers/report/report_list.py +22 -0
- endoreg_db/serializers/report/secure_file_url.py +26 -0
- endoreg_db/serializers/requirements/requirement_schema.py +25 -0
- endoreg_db/serializers/requirements/requirement_sets.py +29 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/segmentation.py +263 -0
- endoreg_db/serializers/video/video_file_brief.py +10 -0
- endoreg_db/serializers/video/video_file_detail.py +83 -0
- endoreg_db/serializers/video/video_file_list.py +67 -0
- endoreg_db/serializers/video/video_metadata.py +105 -0
- endoreg_db/serializers/video/video_processing_history.py +153 -0
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +223 -0
- endoreg_db/services/examination_evaluation.py +149 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +411 -0
- endoreg_db/services/lookup_store.py +266 -0
- endoreg_db/services/pdf_import.py +1382 -0
- endoreg_db/services/polling_coordinator.py +288 -0
- endoreg_db/services/pseudonym_service.py +89 -0
- endoreg_db/services/requirements_object.py +147 -0
- endoreg_db/services/segment_sync.py +155 -0
- endoreg_db/services/storage_aware_video_processor.py +344 -0
- endoreg_db/services/video_import.py +1259 -0
- endoreg_db/tasks/upload_tasks.py +207 -0
- endoreg_db/tasks/video_ingest.py +157 -0
- endoreg_db/tasks/video_processing_tasks.py +327 -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 +83 -0
- endoreg_db/urls/anonymization.py +32 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +39 -0
- endoreg_db/urls/examination.py +54 -0
- endoreg_db/urls/files.py +6 -0
- endoreg_db/urls/label_video_segment_validate.py +33 -0
- endoreg_db/urls/label_video_segments.py +46 -0
- endoreg_db/urls/media.py +227 -0
- endoreg_db/urls/patient.py +19 -0
- endoreg_db/urls/report.py +48 -0
- endoreg_db/urls/requirements.py +13 -0
- endoreg_db/urls/sensitive_meta.py +0 -0
- endoreg_db/urls/stats.py +46 -0
- endoreg_db/urls/upload.py +20 -0
- endoreg_db/urls/video.py +61 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +88 -1
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/{models/ai_model/utils.py → utils/ai/get.py} +1 -4
- endoreg_db/utils/ai/inference_dataset.py +52 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +159 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +291 -0
- endoreg_db/utils/ai/preprocess.py +68 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +0 -0
- endoreg_db/utils/case_generator/case_generator.py +159 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/utils/case_generator/utils.py +30 -0
- endoreg_db/utils/check_video_files.py +148 -0
- endoreg_db/utils/dataloader.py +118 -35
- endoreg_db/utils/dates.py +60 -0
- endoreg_db/utils/env.py +33 -0
- endoreg_db/utils/extract_specific_frames.py +72 -0
- endoreg_db/utils/file_operations.py +29 -1
- endoreg_db/utils/fix_video_path_direct.py +141 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +123 -4
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +193 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +76 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/paths.py +95 -0
- endoreg_db/utils/permissions.py +143 -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 +120 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +20 -0
- endoreg_db/utils/product/sum_weights.py +18 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -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/lab_value_operators.py +578 -0
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/utils/translation.py +27 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/validate_video_detailed.py +357 -0
- endoreg_db/utils/video/__init__.py +26 -0
- endoreg_db/utils/video/extract_frames.py +88 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +835 -0
- endoreg_db/utils/video/names.py +42 -0
- endoreg_db/utils/video/streaming_processor.py +312 -0
- endoreg_db/utils/video/video_splitter.py +94 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
- endoreg_db/views/__init__.py +274 -0
- endoreg_db/views/anonymization/__init__.py +27 -0
- endoreg_db/views/anonymization/media_management.py +454 -0
- endoreg_db/views/anonymization/overview.py +216 -0
- endoreg_db/views/anonymization/validate.py +107 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +113 -0
- endoreg_db/views/examination/__init__.py +33 -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 +59 -0
- endoreg_db/views/examination/get_finding_classifications.py +36 -0
- endoreg_db/views/examination/get_findings.py +41 -0
- endoreg_db/views/examination/get_instruments.py +18 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +112 -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 +42 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
- endoreg_db/views/label/__init__.py +5 -0
- endoreg_db/views/label/label.py +15 -0
- endoreg_db/views/label_video_segment/__init__.py +16 -0
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
- endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
- endoreg_db/views/label_video_segment/validate.py +226 -0
- endoreg_db/views/media/__init__.py +45 -0
- endoreg_db/views/media/pdf_media.py +388 -0
- endoreg_db/views/media/segments.py +71 -0
- endoreg_db/views/media/sensitive_metadata.py +314 -0
- endoreg_db/views/media/video_media.py +272 -0
- endoreg_db/views/media/video_segments.py +524 -0
- endoreg_db/views/meta/__init__.py +15 -0
- endoreg_db/views/meta/available_files_list.py +146 -0
- endoreg_db/views/meta/report_meta.py +53 -0
- endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
- endoreg_db/views/meta/sensitive_meta_list.py +104 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
- endoreg_db/views/misc/__init__.py +63 -0
- endoreg_db/views/misc/center.py +13 -0
- endoreg_db/views/misc/csrf.py +7 -0
- endoreg_db/views/misc/gender.py +14 -0
- endoreg_db/views/misc/secure_file_serving_view.py +80 -0
- endoreg_db/views/misc/secure_file_url_view.py +84 -0
- endoreg_db/views/misc/secure_url_validate.py +79 -0
- endoreg_db/views/misc/stats.py +220 -0
- endoreg_db/views/misc/translation.py +182 -0
- endoreg_db/views/misc/upload_views.py +240 -0
- endoreg_db/views/patient/__init__.py +5 -0
- endoreg_db/views/patient/patient.py +210 -0
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +140 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
- endoreg_db/views/patient_examination/video.py +194 -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 +64 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
- endoreg_db/views/patient_finding_location/__init__.py +5 -0
- endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
- endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
- endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
- endoreg_db/views/pdf/__init__.py +8 -0
- endoreg_db/views/pdf/pdf_stream.py +187 -0
- endoreg_db/views/pdf/reimport.py +177 -0
- endoreg_db/views/report/__init__.py +9 -0
- endoreg_db/views/report/report_list.py +112 -0
- endoreg_db/views/report/report_with_secure_url.py +28 -0
- endoreg_db/views/report/start_examination.py +7 -0
- endoreg_db/views/requirement/__init__.py +10 -0
- endoreg_db/views/requirement/evaluate.py +279 -0
- endoreg_db/views/requirement/lookup.py +367 -0
- endoreg_db/views/requirement/lookup_store.py +252 -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 +229 -0
- endoreg_db/views/video/__init__.py +59 -0
- endoreg_db/views/video/correction.py +530 -0
- endoreg_db/views/video/reimport.py +195 -0
- endoreg_db/views/video/segmentation.py +274 -0
- endoreg_db/views/video/task_status.py +49 -0
- endoreg_db/views/video/timeline.py +46 -0
- endoreg_db/views/video/video_analyze.py +52 -0
- endoreg_db/views/video/video_apply_mask.py +48 -0
- endoreg_db/views/video/video_correction.py +21 -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_meta.py +29 -0
- endoreg_db/views/video/video_processing_history.py +24 -0
- endoreg_db/views/video/video_remove_frames.py +48 -0
- endoreg_db/views/video/video_stream.py +306 -0
- endoreg_db/views.py +0 -3
- endoreg_db-0.8.6.3.dist-info/METADATA +383 -0
- endoreg_db-0.8.6.3.dist-info/RECORD +793 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info}/WHEEL +1 -1
- endoreg_db/data/active_model/data.yaml +0 -3
- endoreg_db/data/agl_service/data.yaml +0 -19
- endoreg_db/data/label/label-set/data.yaml +0 -18
- endoreg_db/management/commands/_load_model_template.py +0 -41
- endoreg_db/management/commands/delete_all.py +0 -18
- endoreg_db/management/commands/delete_legacy_images.py +0 -19
- endoreg_db/management/commands/delete_legacy_videos.py +0 -17
- endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +0 -32
- endoreg_db/management/commands/fix_auth_permission.py +0 -20
- endoreg_db/management/commands/import_legacy_images.py +0 -94
- endoreg_db/management/commands/import_legacy_videos.py +0 -76
- endoreg_db/management/commands/load_active_model_data.py +0 -45
- endoreg_db/management/commands/load_endoscopy_processor_data.py +0 -45
- endoreg_db/management/commands/load_g_play_data.py +0 -113
- endoreg_db/management/commands/load_label_data.py +0 -67
- endoreg_db/management/commands/load_medication_indication_data.py +0 -63
- endoreg_db/management/commands/load_medication_indication_type_data.py +0 -41
- endoreg_db/management/commands/load_medication_schedule_data.py +0 -55
- endoreg_db/management/commands/load_network_data.py +0 -57
- endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
- endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
- endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
- endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
- endoreg_db/models/ai_model/__init__.py +0 -3
- endoreg_db/models/ai_model/active_model.py +0 -9
- endoreg_db/models/ai_model/model_meta.py +0 -24
- endoreg_db/models/annotation/__init__.py +0 -3
- endoreg_db/models/annotation/anonymized_image_annotation.py +0 -60
- endoreg_db/models/annotation/binary_classification_annotation_task.py +0 -80
- endoreg_db/models/annotation/image_classification.py +0 -27
- endoreg_db/models/center/center.py +0 -25
- endoreg_db/models/center/center_product.py +0 -34
- endoreg_db/models/center/center_resource.py +0 -19
- endoreg_db/models/center/center_waste.py +0 -11
- endoreg_db/models/data_file/__init__.py +0 -6
- endoreg_db/models/data_file/base_classes/__init__.py +0 -2
- endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -51
- endoreg_db/models/data_file/base_classes/abstract_video.py +0 -201
- endoreg_db/models/data_file/frame.py +0 -45
- endoreg_db/models/data_file/import_classes/__init__.py +0 -32
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +0 -35
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +0 -28
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +0 -260
- endoreg_db/models/data_file/import_classes/raw_pdf.py +0 -188
- endoreg_db/models/data_file/import_classes/raw_video.py +0 -343
- endoreg_db/models/data_file/metadata/__init__.py +0 -3
- endoreg_db/models/data_file/metadata/sensitive_meta.py +0 -31
- endoreg_db/models/data_file/metadata/video_meta.py +0 -133
- endoreg_db/models/data_file/report_file.py +0 -89
- endoreg_db/models/data_file/video/__init__.py +0 -7
- endoreg_db/models/data_file/video/import_meta.py +0 -25
- endoreg_db/models/data_file/video/video.py +0 -25
- endoreg_db/models/data_file/video_segment.py +0 -107
- endoreg_db/models/disease.py +0 -56
- endoreg_db/models/emission/__init__.py +0 -1
- endoreg_db/models/emission/emission_factor.py +0 -20
- endoreg_db/models/event.py +0 -22
- endoreg_db/models/examination/__init__.py +0 -4
- endoreg_db/models/examination/examination.py +0 -26
- endoreg_db/models/examination/examination_time.py +0 -27
- endoreg_db/models/examination/examination_time_type.py +0 -24
- endoreg_db/models/examination/examination_type.py +0 -18
- endoreg_db/models/hardware/__init__.py +0 -2
- endoreg_db/models/hardware/endoscope.py +0 -44
- endoreg_db/models/information_source.py +0 -29
- endoreg_db/models/laboratory/__init__.py +0 -1
- endoreg_db/models/laboratory/lab_value.py +0 -102
- endoreg_db/models/legacy_data/__init__.py +0 -3
- endoreg_db/models/legacy_data/image.py +0 -34
- endoreg_db/models/logging/__init__.py +0 -4
- endoreg_db/models/logging/agl_service.py +0 -19
- endoreg_db/models/logging/base.py +0 -22
- endoreg_db/models/logging/log_type.py +0 -23
- endoreg_db/models/logging/network_device.py +0 -24
- endoreg_db/models/medication/__init__.py +0 -1
- endoreg_db/models/medication/medication.py +0 -148
- endoreg_db/models/network/__init__.py +0 -3
- endoreg_db/models/network/agl_service.py +0 -38
- endoreg_db/models/network/network_device.py +0 -53
- endoreg_db/models/network/network_device_type.py +0 -23
- endoreg_db/models/other/distribution.py +0 -215
- endoreg_db/models/patient_examination/__init__.py +0 -35
- endoreg_db/models/permissions/__init__.py +0 -44
- endoreg_db/models/persons/__init__.py +0 -7
- endoreg_db/models/persons/examiner/__init__.py +0 -2
- endoreg_db/models/persons/examiner/examiner.py +0 -16
- endoreg_db/models/persons/examiner/examiner_type.py +0 -2
- endoreg_db/models/persons/patient/__init__.py +0 -8
- endoreg_db/models/persons/patient/case/case.py +0 -30
- endoreg_db/models/persons/patient/patient.py +0 -216
- endoreg_db/models/persons/patient/patient_disease.py +0 -16
- endoreg_db/models/persons/patient/patient_event.py +0 -22
- endoreg_db/models/persons/patient/patient_lab_sample.py +0 -106
- endoreg_db/models/persons/patient/patient_medication.py +0 -44
- endoreg_db/models/persons/patient/patient_medication_schedule.py +0 -28
- endoreg_db/models/persons/portal_user_information.py +0 -27
- endoreg_db/models/prediction/__init__.py +0 -2
- endoreg_db/models/prediction/image_classification.py +0 -37
- endoreg_db/models/prediction/video_prediction_meta.py +0 -244
- endoreg_db/models/product/__init__.py +0 -5
- endoreg_db/models/product/product.py +0 -97
- endoreg_db/models/product/product_group.py +0 -19
- endoreg_db/models/product/product_material.py +0 -24
- endoreg_db/models/questionnaires/__init__.py +0 -114
- endoreg_db/models/quiz/__init__.py +0 -2
- endoreg_db/models/quiz/quiz_answer.py +0 -41
- endoreg_db/models/quiz/quiz_question.py +0 -54
- endoreg_db/models/report_reader/__init__.py +0 -2
- endoreg_db/models/report_reader/report_reader_config.py +0 -53
- endoreg_db/models/rules/__init__.py +0 -5
- endoreg_db/queries/get/__init__.py +0 -6
- endoreg_db/queries/get/center.py +0 -42
- endoreg_db/queries/get/model.py +0 -13
- endoreg_db/queries/get/patient.py +0 -14
- endoreg_db/queries/get/patient_examination.py +0 -20
- endoreg_db/queries/get/report_file.py +0 -33
- endoreg_db/queries/get/video.py +0 -31
- endoreg_db/serializers/ai_model.py +0 -19
- endoreg_db/serializers/annotation.py +0 -17
- endoreg_db/serializers/center.py +0 -11
- endoreg_db/serializers/examination.py +0 -33
- endoreg_db/serializers/frame.py +0 -13
- endoreg_db/serializers/hardware.py +0 -21
- endoreg_db/serializers/label.py +0 -22
- endoreg_db/serializers/patient.py +0 -10
- endoreg_db/serializers/prediction.py +0 -15
- endoreg_db/serializers/report_file.py +0 -7
- endoreg_db/serializers/video.py +0 -27
- endoreg_db/tests.py +0 -3
- endoreg_db/utils/legacy_ocr.py +0 -201
- endoreg_db/utils/video_metadata.py +0 -87
- endoreg_db-0.4.5.dist-info/METADATA +0 -34
- endoreg_db-0.4.5.dist-info/RECORD +0 -316
- /endoreg_db/{data/distribution/numeric/.init → api/serializers/finding_descriptions.py} +0 -0
- /endoreg_db/{models/persons/patient/case/__init__.py → api/views/finding_descriptions.py} +0 -0
- /endoreg_db/{queries/get/annotation.py → config/__init__.py} +0 -0
- /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
- /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
- /endoreg_db/{queries/get/prediction.py → data/shift/m2.yaml} +0 -0
- /endoreg_db/{queries/get/video_import_meta.py → factories/__init__.py} +0 -0
- /endoreg_db/{queries/get/video_prediction_meta.py → helpers/__init__.py} +0 -0
- /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
- /endoreg_db/models/{persons → administration/person}/person.py +0 -0
- /endoreg_db/models/{report_reader → media/pdf/report_reader}/report_reader_flag.py +0 -0
- /endoreg_db/models/{rules → rule}/rule_applicator.py +0 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Set
|
|
3
|
+
from django.db import transaction
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models import VideoFile
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
@transaction.atomic
|
|
11
|
+
def _mark_frames_extracted_status(video: "VideoFile", extracted_frame_numbers: Set[int], status: bool):
|
|
12
|
+
"""
|
|
13
|
+
Bulk updates the is_extracted status for a set of frame numbers.
|
|
14
|
+
"""
|
|
15
|
+
from endoreg_db.models.media.frame import Frame
|
|
16
|
+
if not extracted_frame_numbers:
|
|
17
|
+
logger.warning("No frame numbers provided to update status for video %s.", video.uuid)
|
|
18
|
+
return 0
|
|
19
|
+
|
|
20
|
+
# --- Enhanced Logging ---
|
|
21
|
+
min_frame = min(extracted_frame_numbers) if extracted_frame_numbers else 'N/A'
|
|
22
|
+
max_frame = max(extracted_frame_numbers) if extracted_frame_numbers else 'N/A'
|
|
23
|
+
contains_zero = 0 in extracted_frame_numbers
|
|
24
|
+
logger.info(
|
|
25
|
+
"Attempting to mark %d Frame objects as is_extracted=%s for video %s. Frame numbers range: [%s-%s]. Contains frame 0: %s",
|
|
26
|
+
len(extracted_frame_numbers), status, video.uuid, min_frame, max_frame, contains_zero
|
|
27
|
+
)
|
|
28
|
+
# --- End Enhanced Logging ---
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
# Update Frame objects based on frame_number
|
|
32
|
+
# Convert set to list for potentially better compatibility with some DB backends
|
|
33
|
+
updated_count = Frame.objects.filter(
|
|
34
|
+
video=video,
|
|
35
|
+
frame_number__in=list(extracted_frame_numbers)
|
|
36
|
+
).update(is_extracted=status)
|
|
37
|
+
|
|
38
|
+
logger.info("Database reported updating %d Frame objects to is_extracted=%s for video %s.", updated_count, status, video.uuid)
|
|
39
|
+
|
|
40
|
+
# Verification step
|
|
41
|
+
if updated_count != len(extracted_frame_numbers):
|
|
42
|
+
logger.warning(
|
|
43
|
+
"Mismatch during status update for video %s. Expected to update %d frames, but DB reported updating %d.",
|
|
44
|
+
video.uuid, len(extracted_frame_numbers), updated_count
|
|
45
|
+
)
|
|
46
|
+
# --- Add detailed check for frame 0 if status is True and it should have been updated ---
|
|
47
|
+
if status is True and contains_zero and updated_count < len(extracted_frame_numbers):
|
|
48
|
+
try:
|
|
49
|
+
# Check the status of frame 0 directly after the update attempt
|
|
50
|
+
frame_zero = Frame.objects.get(video_file=video, frame_number=0)
|
|
51
|
+
if not frame_zero.is_extracted:
|
|
52
|
+
logger.error("Verification check: Frame 0 (PK: %s) was NOT updated to is_extracted=True for video %s.", frame_zero.pk, video.uuid)
|
|
53
|
+
else:
|
|
54
|
+
# This case should ideally not happen if updated_count < expected count, but log just in case
|
|
55
|
+
logger.info("Verification check: Frame 0 (PK: %s) IS is_extracted=True for video %s, despite count mismatch.", frame_zero.pk, video.uuid)
|
|
56
|
+
except Frame.DoesNotExist:
|
|
57
|
+
logger.error("Verification check: Frame 0 does not exist for video %s during status check.", video.uuid)
|
|
58
|
+
except Exception as verify_e:
|
|
59
|
+
logger.error("Verification check: Error checking frame 0 status for video %s: %s", video.uuid, verify_e)
|
|
60
|
+
# --- End detailed check ---
|
|
61
|
+
|
|
62
|
+
return updated_count
|
|
63
|
+
except Exception as e:
|
|
64
|
+
logger.error("Failed to bulk update is_extracted status for video %s: %s", video.uuid, e, exc_info=True)
|
|
65
|
+
raise # Re-raise to ensure transaction rollback if needed
|
|
File without changes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
|
+
from django.db import transaction
|
|
5
|
+
|
|
6
|
+
from ...utils import data_paths, ANONYM_VIDEO_DIR, VIDEO_DIR # Import VIDEO_DIR for correct path resolution
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from .video_file import VideoFile
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("video_file")
|
|
12
|
+
|
|
13
|
+
def _get_raw_file_path(video: "VideoFile") -> Optional[Path]:
|
|
14
|
+
"""
|
|
15
|
+
Resolves and returns the absolute path to the raw video file if available.
|
|
16
|
+
The FileField stores a path relative to the storage root. We need to join
|
|
17
|
+
that relative path onto the actual video directory under STORAGE_DIR.
|
|
18
|
+
"""
|
|
19
|
+
try:
|
|
20
|
+
if video.has_raw and video.raw_file.name:
|
|
21
|
+
# raw_file.name is a relative storage path like 'videos/<filename>'
|
|
22
|
+
raw_rel = Path(video.raw_file.name)
|
|
23
|
+
|
|
24
|
+
# If it already contains the video directory name, keep the tail
|
|
25
|
+
rel_name = raw_rel.name if raw_rel.parent.name == VIDEO_DIR.name else raw_rel
|
|
26
|
+
full_path = data_paths["video"] / rel_name
|
|
27
|
+
|
|
28
|
+
# If primary path doesn't exist, check alternative locations
|
|
29
|
+
if not full_path.exists():
|
|
30
|
+
# Check if file is in sensitive subdirectory
|
|
31
|
+
sensitive_path = data_paths["video"] / "sensitive" / rel_name
|
|
32
|
+
if sensitive_path.exists():
|
|
33
|
+
return sensitive_path.resolve()
|
|
34
|
+
|
|
35
|
+
# Check direct raw_file.path if available
|
|
36
|
+
# Check direct raw_file.path if available
|
|
37
|
+
try:
|
|
38
|
+
direct_path = Path(video.raw_file.path)
|
|
39
|
+
if direct_path.exists():
|
|
40
|
+
return direct_path.resolve()
|
|
41
|
+
except Exception as e:
|
|
42
|
+
logger.debug("Could not access direct raw_file.path for video %s: %s", video.uuid, e)
|
|
43
|
+
# Fallback to checking alternative paths
|
|
44
|
+
|
|
45
|
+
# Check common alternative paths
|
|
46
|
+
alternative_paths = [
|
|
47
|
+
Path("/home/admin/dev/lx-annotate/libs/data/videos") / rel_name,
|
|
48
|
+
Path("/home/admin/dev/lx-annotate/libs/data/videos/sensitive") / rel_name,
|
|
49
|
+
data_paths["video"].parent / "libs" / "data" / "videos" / rel_name,
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
for alt_path in alternative_paths:
|
|
53
|
+
if alt_path.exists():
|
|
54
|
+
return alt_path.resolve()
|
|
55
|
+
|
|
56
|
+
return full_path.resolve()
|
|
57
|
+
else:
|
|
58
|
+
return None
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logger.warning("Could not get path for raw file of VideoFile %s: %s", video.uuid, e)
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
def _get_processed_file_path(video: "VideoFile") -> Optional[Path]:
|
|
64
|
+
"""Returns the absolute Path object for the processed file, if it exists."""
|
|
65
|
+
try:
|
|
66
|
+
if video.is_processed and video.processed_file.name:
|
|
67
|
+
return Path(video.processed_file.path)
|
|
68
|
+
else:
|
|
69
|
+
return None
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logger.warning("Could not get path for processed file of VideoFile %s: %s", video.uuid, e)
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
@transaction.atomic
|
|
75
|
+
def _delete_with_file(video: "VideoFile", *args, **kwargs):
|
|
76
|
+
"""Deletes the VideoFile record and its associated physical files (raw, processed, frames)."""
|
|
77
|
+
# 1. Delete Frames (using the frame helper function via instance method)
|
|
78
|
+
try:
|
|
79
|
+
# delete_frames raises RuntimeError on state update failure
|
|
80
|
+
frame_delete_msg = video.delete_frames()
|
|
81
|
+
logger.info("Frame deletion result for video %s: %s", video.uuid, frame_delete_msg)
|
|
82
|
+
except Exception as frame_del_e:
|
|
83
|
+
# Log error but continue, as file deletion might still be possible
|
|
84
|
+
logger.error("Error during frame file/state deletion for video %s: %s", video.uuid, frame_del_e, exc_info=True)
|
|
85
|
+
|
|
86
|
+
# 2. Delete Raw File
|
|
87
|
+
raw_file_path = _get_raw_file_path(video)
|
|
88
|
+
if raw_file_path:
|
|
89
|
+
try:
|
|
90
|
+
if raw_file_path.exists():
|
|
91
|
+
raw_file_path.unlink()
|
|
92
|
+
logger.info("Deleted raw video file for %s: %s", video.uuid, raw_file_path)
|
|
93
|
+
else:
|
|
94
|
+
logger.warning("Raw video file not found at %s for video %s, skipping deletion.", raw_file_path, video.uuid)
|
|
95
|
+
|
|
96
|
+
except Exception as e:
|
|
97
|
+
# Log error but continue
|
|
98
|
+
logger.error("Error deleting raw video file %s for video %s: %s", raw_file_path, video.uuid, e, exc_info=True)
|
|
99
|
+
|
|
100
|
+
# 3. Delete Processed File
|
|
101
|
+
processed_file_path = _get_processed_file_path(video)
|
|
102
|
+
if processed_file_path:
|
|
103
|
+
try:
|
|
104
|
+
if processed_file_path.exists():
|
|
105
|
+
processed_file_path.unlink()
|
|
106
|
+
logger.info("Deleted processed video file for %s: %s", video.uuid, processed_file_path)
|
|
107
|
+
else:
|
|
108
|
+
logger.warning("Processed video file not found at %s for video %s, skipping deletion.", processed_file_path, video.uuid)
|
|
109
|
+
except Exception as e:
|
|
110
|
+
# Log error but continue
|
|
111
|
+
logger.error("Error deleting processed video file %s for video %s: %s", processed_file_path, video.uuid, e, exc_info=True)
|
|
112
|
+
|
|
113
|
+
# 4. Delete Database Record
|
|
114
|
+
try:
|
|
115
|
+
# Use 'super(type(video), video)' to call the parent's delete method
|
|
116
|
+
super(type(video), video).delete(*args, **kwargs)
|
|
117
|
+
logger.info("Deleted VideoFile database record PK %s (UUID: %s).", video.pk, video.uuid)
|
|
118
|
+
|
|
119
|
+
return f"Successfully deleted VideoFile {video.uuid} and attempted file cleanup."
|
|
120
|
+
except Exception as e:
|
|
121
|
+
logger.error("Error deleting VideoFile database record PK %s (UUID: %s): %s", video.pk, video.uuid, e, exc_info=True)
|
|
122
|
+
raise # Re-raise the exception for DB deletion failure
|
|
123
|
+
|
|
124
|
+
def _get_base_frame_dir(video: "VideoFile") -> Path:
|
|
125
|
+
"""Gets the base directory path for storing extracted frames."""
|
|
126
|
+
# Assuming data_paths['frame'] is the root directory for all frame storage
|
|
127
|
+
return data_paths["frame"] / str(video.uuid)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _set_frame_dir(video: "VideoFile", force_update: bool = False):
|
|
131
|
+
"""Sets the frame_dir field based on the video's UUID."""
|
|
132
|
+
target_dir = _get_base_frame_dir(video)
|
|
133
|
+
target_path_str = target_dir.as_posix() # Store as POSIX path string
|
|
134
|
+
|
|
135
|
+
if not video.frame_dir or video.frame_dir != target_path_str or force_update:
|
|
136
|
+
video.frame_dir = target_path_str
|
|
137
|
+
logger.info("Set frame_dir for video %s to %s", video.uuid, video.frame_dir)
|
|
138
|
+
# Avoid saving if called from within the save method itself
|
|
139
|
+
if not getattr(video, '_saving', False):
|
|
140
|
+
video.save(update_fields=['frame_dir'])
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _get_frame_dir_path(video: "VideoFile") -> Optional[Path]:
|
|
144
|
+
"""Returns the Path object for the frame directory, if set."""
|
|
145
|
+
if not video.frame_dir:
|
|
146
|
+
_set_frame_dir(video)
|
|
147
|
+
|
|
148
|
+
return Path(video.frame_dir)
|
|
149
|
+
|
|
150
|
+
def _get_temp_anonymized_frame_dir(video: "VideoFile") -> Path:
|
|
151
|
+
"""Gets the path for the temporary directory used during anonymization frame creation."""
|
|
152
|
+
base_frame_dir = _get_base_frame_dir(video)
|
|
153
|
+
# Place temp dir alongside the final frame dir but with a prefix/suffix
|
|
154
|
+
anon_dir = base_frame_dir.parent / f"anonymizing_{base_frame_dir.name}"
|
|
155
|
+
return anon_dir
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _get_target_anonymized_video_path(video: "VideoFile") -> Path:
|
|
159
|
+
"""Determines the target path for the anonymized/processed video file."""
|
|
160
|
+
if not video.has_raw or not video.raw_file.name:
|
|
161
|
+
# If raw is gone, maybe base it on UUID? Requires careful thought.
|
|
162
|
+
# For now, assume raw is needed to determine the original filename base.
|
|
163
|
+
raise ValueError("Cannot determine target anonymized path without a raw file reference.")
|
|
164
|
+
|
|
165
|
+
# Use the filename part of the raw file's relative path
|
|
166
|
+
raw_path_relative = Path(video.raw_file.name)
|
|
167
|
+
# Place it in the ANONYM_VIDEO_DIR using the same filename
|
|
168
|
+
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,45 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, List, Dict
|
|
3
|
+
from .get_endo_roi import _get_endo_roi
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..video_file import VideoFile
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _get_crop_template(video: "VideoFile") -> Optional[List[int]]:
|
|
12
|
+
"""Generates a crop template [y1, y2, x1, x2] from the endo ROI."""
|
|
13
|
+
endo_roi = _get_endo_roi(video) # Use the helper function
|
|
14
|
+
if not endo_roi:
|
|
15
|
+
logger.warning("Cannot generate crop template for video %s: Endo ROI not available.", video.uuid)
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
x = endo_roi["x"]
|
|
19
|
+
y = endo_roi["y"]
|
|
20
|
+
width = endo_roi["width"]
|
|
21
|
+
height = endo_roi["height"]
|
|
22
|
+
|
|
23
|
+
# Validate dimensions
|
|
24
|
+
if None in [x, y, width, height] or width <= 0 or height <= 0:
|
|
25
|
+
logger.warning("Invalid ROI dimensions for video %s: %s", video.uuid, endo_roi)
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
# Ensure crop boundaries are within image dimensions if available
|
|
29
|
+
img_h, img_w = video.height, video.width
|
|
30
|
+
if img_h and img_w:
|
|
31
|
+
y1 = max(0, y)
|
|
32
|
+
y2 = min(img_h, y + height)
|
|
33
|
+
x1 = max(0, x)
|
|
34
|
+
x2 = min(img_w, x + width)
|
|
35
|
+
if y1 >= y2 or x1 >= x2:
|
|
36
|
+
logger.warning("Calculated crop template has zero or negative size for video %s. ROI: %s, Img: %dx%d", video.uuid, endo_roi, img_w, img_h)
|
|
37
|
+
return None
|
|
38
|
+
crop_template = [y1, y2, x1, x2]
|
|
39
|
+
else:
|
|
40
|
+
# Proceed without boundary check if image dimensions unknown
|
|
41
|
+
crop_template = [y, y + height, x, x + width]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
logger.debug("Generated crop template for video %s: %s", video.uuid, crop_template)
|
|
45
|
+
return crop_template
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Dict
|
|
3
|
+
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from ..video_file import VideoFile
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
def _get_endo_roi(video: "VideoFile") -> Optional[Dict[str, int]]:
|
|
10
|
+
"""
|
|
11
|
+
Gets the endoscope region of interest (ROI) dictionary from the linked VideoMeta.
|
|
12
|
+
|
|
13
|
+
The ROI dictionary typically contains 'x', 'y', 'width', 'height'.
|
|
14
|
+
Returns None if VideoMeta is not linked or ROI is not properly defined.
|
|
15
|
+
"""
|
|
16
|
+
if not video.video_meta:
|
|
17
|
+
logger.warning("VideoMeta not linked for video %s. Cannot get endo ROI.", video.uuid)
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
# Assuming VideoMeta has a method get_endo_roi()
|
|
22
|
+
endo_roi = video.video_meta.get_endo_roi()
|
|
23
|
+
# Basic validation
|
|
24
|
+
if (
|
|
25
|
+
isinstance(endo_roi, dict)
|
|
26
|
+
and all(k in endo_roi for k in ("x", "y", "width", "height"))
|
|
27
|
+
and all(isinstance(v, int) and not isinstance(v, bool) for v in endo_roi.values())
|
|
28
|
+
):
|
|
29
|
+
logger.debug("Retrieved endo ROI for video %s: %s", video.uuid, endo_roi)
|
|
30
|
+
return endo_roi
|
|
31
|
+
else:
|
|
32
|
+
logger.warning("Endo ROI not fully defined or invalid in VideoMeta for video %s. ROI: %s", video.uuid, endo_roi)
|
|
33
|
+
return None
|
|
34
|
+
except AttributeError:
|
|
35
|
+
logger.error("VideoMeta object for video %s does not have a 'get_endo_roi' method.", video.uuid)
|
|
36
|
+
return None
|
|
37
|
+
except Exception as e:
|
|
38
|
+
logger.error("Error getting endo ROI from VideoMeta for video %s: %s", video.uuid, e, exc_info=True)
|
|
39
|
+
return None
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Dict
|
|
3
|
+
import cv2
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from ..video_file import VideoFile
|
|
8
|
+
|
|
9
|
+
def _validate_video_path(video_path: Path):
|
|
10
|
+
"""
|
|
11
|
+
Validates that the provided path is an existing video file.
|
|
12
|
+
|
|
13
|
+
Raises:
|
|
14
|
+
TypeError: If `video_path` is not a Path object.
|
|
15
|
+
FileNotFoundError: If the file does not exist at the specified path.
|
|
16
|
+
IsADirectoryError: If the path points to a directory instead of a file.
|
|
17
|
+
"""
|
|
18
|
+
if not isinstance(video_path, Path):
|
|
19
|
+
raise TypeError("video_path must be a Path object")
|
|
20
|
+
if not video_path.exists():
|
|
21
|
+
raise FileNotFoundError(f"Video file not found at {video_path}")
|
|
22
|
+
if not video_path.is_file():
|
|
23
|
+
raise IsADirectoryError(f"Path is a directory, not a file: {video_path}")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
def _get_fps(video: "VideoFile") -> float:
|
|
28
|
+
"""
|
|
29
|
+
Determine and return the frames per second (FPS) of a video associated with a VideoFile instance.
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
float: The frames per second (FPS) of the video.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValueError: If the FPS cannot be determined from any available source.
|
|
38
|
+
"""
|
|
39
|
+
from .video_meta import _update_video_meta
|
|
40
|
+
if video.fps is not None:
|
|
41
|
+
return video.fps
|
|
42
|
+
|
|
43
|
+
logger.debug("FPS not set on instance %s, checking VideoMeta.", video.uuid)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if not video.video_meta:
|
|
47
|
+
logger.info("VideoMeta not linked for %s, attempting update.", video.uuid)
|
|
48
|
+
|
|
49
|
+
_update_video_meta(video, save_instance=True) # Call the helper function
|
|
50
|
+
|
|
51
|
+
# Check again after potential update
|
|
52
|
+
if video.fps is not None:
|
|
53
|
+
return video.fps
|
|
54
|
+
elif video.video_meta and video.video_meta.fps is not None:
|
|
55
|
+
logger.info("Retrieved FPS %.2f from VideoMeta for %s.", video.video_meta.fps, video.uuid)
|
|
56
|
+
video.fps = video.video_meta.fps
|
|
57
|
+
# Avoid saving if called from within the save method itself
|
|
58
|
+
if not getattr(video, '_saving', False):
|
|
59
|
+
video.save(update_fields=["fps"])
|
|
60
|
+
return video.fps
|
|
61
|
+
else:
|
|
62
|
+
logger.warning("Could not determine FPS from VideoMeta for video %s. Trying direct raw file access.", video.uuid)
|
|
63
|
+
try:
|
|
64
|
+
if video.has_raw:
|
|
65
|
+
video_path = video.get_raw_file_path() # Use helper
|
|
66
|
+
if video_path and video_path.exists():
|
|
67
|
+
cap = cv2.VideoCapture(video_path.as_posix())
|
|
68
|
+
if not cap.isOpened():
|
|
69
|
+
raise IOError(f"Cannot open video file: {video_path}")
|
|
70
|
+
try:
|
|
71
|
+
fps = _get_fps_from_property(cap)
|
|
72
|
+
|
|
73
|
+
if fps is None or fps <= 0:
|
|
74
|
+
# Reset video capture to the beginning for manual calculation
|
|
75
|
+
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
|
|
76
|
+
fps = _calculate_fps_manually(cap, video_path)
|
|
77
|
+
finally:
|
|
78
|
+
cap.release()
|
|
79
|
+
if fps and fps > 0:
|
|
80
|
+
video.fps = fps
|
|
81
|
+
logger.info("Determined FPS %.2f directly from file for %s.", video.fps, video.uuid)
|
|
82
|
+
if not getattr(video, '_saving', False):
|
|
83
|
+
video.save(update_fields=["fps"])
|
|
84
|
+
return video.fps
|
|
85
|
+
else:
|
|
86
|
+
logger.warning("Could not determine a valid FPS for video file %s.", video_path)
|
|
87
|
+
elif video_path:
|
|
88
|
+
logger.warning("Raw file path %s does not exist for direct FPS check.", video_path)
|
|
89
|
+
else:
|
|
90
|
+
logger.warning("Raw file path is None for direct FPS check.")
|
|
91
|
+
else:
|
|
92
|
+
logger.warning("Raw file not available for direct FPS check.")
|
|
93
|
+
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.error("Error getting FPS directly from file %s: %s", video.raw_file.name if video.has_raw else 'N/A', e)
|
|
96
|
+
|
|
97
|
+
raise ValueError(
|
|
98
|
+
f"Could not determine FPS for video {video.uuid}. "
|
|
99
|
+
"Ensure the video file is valid and accessible."
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# TODO Refactor to utils / check if similar function exists in utils
|
|
105
|
+
def _get_fps_from_property(cap) -> float:
|
|
106
|
+
"""
|
|
107
|
+
Retrieve the frames per second (FPS) from an OpenCV video capture object using the appropriate property for the OpenCV version.
|
|
108
|
+
|
|
109
|
+
Parameters:
|
|
110
|
+
cap: An OpenCV video capture object.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
float: The FPS value obtained from the video capture properties, or 0.0 if unavailable.
|
|
114
|
+
"""
|
|
115
|
+
if hasattr(cv2, 'CAP_PROP_FPS'):
|
|
116
|
+
return cap.get(cv2.CAP_PROP_FPS)
|
|
117
|
+
# For older OpenCV versions
|
|
118
|
+
return cap.get(cv2.cv.CV_CAP_PROP_FPS) # type: ignore
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _calculate_fps_manually(cap, video_path: Path) -> float:
|
|
122
|
+
"""
|
|
123
|
+
Estimate the frames per second (FPS) of a video by reading all frames and dividing the total frame count by the elapsed time.
|
|
124
|
+
|
|
125
|
+
Parameters:
|
|
126
|
+
cap: An OpenCV video capture object positioned at the start of the video.
|
|
127
|
+
video_path (Path): Path to the video file, used for logging.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
float: The estimated FPS, or 0.0 if the duration is zero or calculation fails.
|
|
131
|
+
"""
|
|
132
|
+
logger.warning(f"Could not get a valid FPS for {video_path}. Trying to calculate manually.")
|
|
133
|
+
# This is less accurate and slower
|
|
134
|
+
num_frames = 0
|
|
135
|
+
start_time = cv2.getTickCount()
|
|
136
|
+
while True:
|
|
137
|
+
ret, _ = cap.read()
|
|
138
|
+
if not ret:
|
|
139
|
+
break
|
|
140
|
+
num_frames += 1
|
|
141
|
+
end_time = cv2.getTickCount()
|
|
142
|
+
seconds = (end_time - start_time) / cv2.getTickFrequency()
|
|
143
|
+
if seconds > 0:
|
|
144
|
+
return num_frames / seconds
|
|
145
|
+
|
|
146
|
+
logger.error(f"Manual FPS calculation failed for {video_path} due to zero duration.")
|
|
147
|
+
return 0.0
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# --- Add Imports ---
|
|
2
|
+
import logging
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
|
5
|
+
import cv2
|
|
6
|
+
# --- End Add Imports ---
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ..video_file import VideoFile # Correct import path
|
|
10
|
+
|
|
11
|
+
# --- Add Logger ---
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
# --- End Add Logger ---
|
|
14
|
+
|
|
15
|
+
def _initialize_video_specs(video: "VideoFile", use_raw: bool = True) -> bool:
|
|
16
|
+
"""
|
|
17
|
+
Initializes video specifications for a VideoFile object by reading from the video file.
|
|
18
|
+
|
|
19
|
+
Attempts to populate missing values for fps, width, height, frame count, and duration using OpenCV. Selects the raw file if available and requested, otherwise uses the active file. Updates only unset fields if valid values are obtained. Returns True if successful or if no updates are needed. Raises FileNotFoundError if the video file cannot be found, or RuntimeError if the file cannot be opened or properties cannot be read.
|
|
20
|
+
"""
|
|
21
|
+
video_path: Optional[Path] = None
|
|
22
|
+
target_file_name: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
if use_raw and video.has_raw:
|
|
25
|
+
video_path = video.get_raw_file_path() # Use IO helper
|
|
26
|
+
target_file_name = video.raw_file.name
|
|
27
|
+
elif video.active_file: # Fallback to active file if raw not requested or available
|
|
28
|
+
video_path = video.active_file_path # Use property relying on IO helpers
|
|
29
|
+
target_file_name = video.active_file.name
|
|
30
|
+
else:
|
|
31
|
+
logger.error("No suitable video file found for spec initialization for %s.", video.uuid)
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
if not video_path:
|
|
35
|
+
# Raise exception
|
|
36
|
+
raise FileNotFoundError(f"Could not determine video file path for spec initialization for {video.uuid}.")
|
|
37
|
+
|
|
38
|
+
logger.info("Initializing video specs directly from file %s (%s) for %s", target_file_name, video_path, video.uuid)
|
|
39
|
+
try:
|
|
40
|
+
if not video_path.exists():
|
|
41
|
+
# Raise exception
|
|
42
|
+
raise FileNotFoundError(f"Video file not found at {video_path} for spec initialization (Video: {video.uuid}).")
|
|
43
|
+
|
|
44
|
+
video_cap = cv2.VideoCapture(video_path.as_posix())
|
|
45
|
+
if not video_cap.isOpened():
|
|
46
|
+
# Raise exception
|
|
47
|
+
video_cap.release() # Ensure release
|
|
48
|
+
raise RuntimeError(f"Could not open video file {video_path} with OpenCV for spec initialization (Video: {video.uuid}).")
|
|
49
|
+
|
|
50
|
+
updated = False
|
|
51
|
+
fields_to_update = []
|
|
52
|
+
|
|
53
|
+
# Get current values before checking
|
|
54
|
+
current_fps = video.fps
|
|
55
|
+
current_width = video.width
|
|
56
|
+
current_height = video.height
|
|
57
|
+
current_frame_count = video.frame_count
|
|
58
|
+
current_duration = video.duration
|
|
59
|
+
|
|
60
|
+
# --- Get values from OpenCV ---
|
|
61
|
+
try:
|
|
62
|
+
file_fps = video_cap.get(cv2.CAP_PROP_FPS)
|
|
63
|
+
file_width = int(video_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
|
64
|
+
file_height = int(video_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
65
|
+
file_frame_count = int(video_cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
|
66
|
+
except Exception as cv_err:
|
|
67
|
+
logger.error("Error getting properties from OpenCV for %s (Video: %s): %s", video_path, video.uuid, cv_err, exc_info=True)
|
|
68
|
+
raise RuntimeError(f"OpenCV failed to get properties for {video_path}") from cv_err
|
|
69
|
+
finally:
|
|
70
|
+
video_cap.release() # Ensure release after getting props
|
|
71
|
+
|
|
72
|
+
# --- Update FPS ---
|
|
73
|
+
if current_fps is None and file_fps and file_fps > 0:
|
|
74
|
+
video.fps = file_fps
|
|
75
|
+
fields_to_update.append("fps")
|
|
76
|
+
updated = True
|
|
77
|
+
current_fps = file_fps # Update local var for duration calc
|
|
78
|
+
|
|
79
|
+
# --- Update Width ---
|
|
80
|
+
if current_width is None and file_width > 0:
|
|
81
|
+
video.width = file_width
|
|
82
|
+
fields_to_update.append("width")
|
|
83
|
+
updated = True
|
|
84
|
+
|
|
85
|
+
# --- Update Height ---
|
|
86
|
+
if current_height is None and file_height > 0:
|
|
87
|
+
video.height = file_height
|
|
88
|
+
fields_to_update.append("height")
|
|
89
|
+
updated = True
|
|
90
|
+
|
|
91
|
+
# --- Update Frame Count ---
|
|
92
|
+
if current_frame_count is None and file_frame_count and file_frame_count > 0:
|
|
93
|
+
video.frame_count = file_frame_count
|
|
94
|
+
fields_to_update.append("frame_count")
|
|
95
|
+
updated = True
|
|
96
|
+
elif file_frame_count is None or file_frame_count <= 0: # Log if not updated due to invalid file_frame_count
|
|
97
|
+
logger.warning(
|
|
98
|
+
"Invalid frame count (value: %s) obtained from OpenCV for %s. Video frame_count not updated.",
|
|
99
|
+
file_frame_count, video_path
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# --- Update Duration ---
|
|
103
|
+
if current_duration is None: # Only if duration isn't already set
|
|
104
|
+
# Use the potentially updated video.frame_count and current_fps (which reflects video.fps or file_fps)
|
|
105
|
+
final_frame_count_for_duration = video.frame_count
|
|
106
|
+
final_fps_for_duration = current_fps # This is video.fps after potential update from file_fps
|
|
107
|
+
|
|
108
|
+
if (final_frame_count_for_duration and final_frame_count_for_duration > 0 and
|
|
109
|
+
final_fps_for_duration and final_fps_for_duration > 0):
|
|
110
|
+
video.duration = final_frame_count_for_duration / final_fps_for_duration
|
|
111
|
+
fields_to_update.append("duration")
|
|
112
|
+
updated = True
|
|
113
|
+
else:
|
|
114
|
+
# Log if duration could not be calculated, indicating which component was missing/invalid
|
|
115
|
+
if not (final_frame_count_for_duration and final_frame_count_for_duration > 0):
|
|
116
|
+
logger.warning(
|
|
117
|
+
"Duration not calculated for %s: frame count is unavailable or invalid (value: %s).",
|
|
118
|
+
video_path, final_frame_count_for_duration
|
|
119
|
+
)
|
|
120
|
+
if not (final_fps_for_duration and final_fps_for_duration > 0):
|
|
121
|
+
logger.warning(
|
|
122
|
+
"Duration not calculated for %s: FPS is unavailable or invalid (value: %s).",
|
|
123
|
+
video_path, final_fps_for_duration
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# --- Save if updated ---
|
|
128
|
+
if updated:
|
|
129
|
+
logger.info("Updated video specs for %s from file %s: %s", video.uuid, target_file_name, ", ".join(fields_to_update))
|
|
130
|
+
video.save(update_fields=fields_to_update)
|
|
131
|
+
return True
|
|
132
|
+
else:
|
|
133
|
+
logger.info("No video specs needed updating for %s from file %s.", video.uuid, target_file_name)
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
except Exception as e:
|
|
137
|
+
# Log and re-raise exception
|
|
138
|
+
logger.error("Error initializing video specs for %s from file %s: %s", video.uuid, video_path, e, exc_info=True)
|
|
139
|
+
# Ensure capture is released in case of unexpected error
|
|
140
|
+
if 'video_cap' in locals() and video_cap.isOpened():
|
|
141
|
+
video_cap.release()
|
|
142
|
+
# Re-raise as RuntimeError
|
|
143
|
+
raise RuntimeError(f"Failed to initialize video specs for {video.uuid} from {video_path}") from e
|