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,332 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
import logging
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
# import endoreg_center_id from django settings
|
|
7
|
+
from django.conf import settings
|
|
8
|
+
|
|
9
|
+
# check if endoreg_center_id is set
|
|
10
|
+
if not hasattr(settings, "ENDOREG_CENTER_ID"):
|
|
11
|
+
ENDOREG_CENTER_ID = 9999
|
|
12
|
+
else:
|
|
13
|
+
ENDOREG_CENTER_ID = settings.ENDOREG_CENTER_ID
|
|
14
|
+
|
|
15
|
+
# Import the new utility function
|
|
16
|
+
from ...utils.video import ffmpeg_wrapper
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from ..administration import Center
|
|
22
|
+
from ..medical.hardware import EndoscopyProcessor, Endoscope
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# VideoMeta
|
|
26
|
+
class VideoMeta(models.Model):
|
|
27
|
+
"""
|
|
28
|
+
Stores technical and contextual metadata related to a video file.
|
|
29
|
+
|
|
30
|
+
Links to hardware (processor, endoscope), center, import details, and FFmpeg technical specs.
|
|
31
|
+
"""
|
|
32
|
+
processor = models.ForeignKey(
|
|
33
|
+
"EndoscopyProcessor", on_delete=models.CASCADE, blank=True, null=True
|
|
34
|
+
)
|
|
35
|
+
endoscope = models.ForeignKey(
|
|
36
|
+
"Endoscope", on_delete=models.CASCADE, blank=True, null=True
|
|
37
|
+
)
|
|
38
|
+
center = models.ForeignKey("Center", on_delete=models.CASCADE)
|
|
39
|
+
import_meta = models.OneToOneField(
|
|
40
|
+
"VideoImportMeta", on_delete=models.CASCADE, blank=True, null=True
|
|
41
|
+
)
|
|
42
|
+
ffmpeg_meta = models.OneToOneField(
|
|
43
|
+
"FFMpegMeta", on_delete=models.CASCADE, blank=True, null=True
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def create_from_file(
|
|
48
|
+
cls,
|
|
49
|
+
video_path: Path,
|
|
50
|
+
center: "Center",
|
|
51
|
+
processor: Optional["EndoscopyProcessor"] = None,
|
|
52
|
+
endoscope: Optional["Endoscope"] = None,
|
|
53
|
+
save_instance: bool = True,
|
|
54
|
+
) -> "VideoMeta":
|
|
55
|
+
"""
|
|
56
|
+
Create a new VideoMeta from a video file path, initializing FFMpegMeta.
|
|
57
|
+
Raises FileNotFoundError, TypeError, or RuntimeError on failure.
|
|
58
|
+
"""
|
|
59
|
+
if not isinstance(video_path, Path):
|
|
60
|
+
raise TypeError("video_path must be a Path object")
|
|
61
|
+
if not video_path.exists():
|
|
62
|
+
raise FileNotFoundError(f"Video file not found at {video_path}")
|
|
63
|
+
|
|
64
|
+
meta = cls(center=center, processor=processor, endoscope=endoscope)
|
|
65
|
+
try:
|
|
66
|
+
# initialize_ffmpeg_meta now raises exceptions on failure
|
|
67
|
+
meta.initialize_ffmpeg_meta(video_path)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
# Re-raise exceptions from ffmpeg meta initialization
|
|
70
|
+
logger.error("Failed during FFMpegMeta initialization within create_from_file for %s: %s", video_path.name, e, exc_info=True)
|
|
71
|
+
raise RuntimeError(f"Failed to initialize FFMpeg metadata for {video_path.name}") from e
|
|
72
|
+
|
|
73
|
+
if save_instance:
|
|
74
|
+
meta.save() # This ensures VideoImportMeta is created too
|
|
75
|
+
logger.info("Created and saved VideoMeta instance PK %s from %s", meta.pk, video_path.name)
|
|
76
|
+
else:
|
|
77
|
+
logger.info("Instantiated VideoMeta from %s (not saved yet)", video_path.name)
|
|
78
|
+
|
|
79
|
+
return meta
|
|
80
|
+
|
|
81
|
+
def __str__(self):
|
|
82
|
+
"""Returns a string summary of the video metadata."""
|
|
83
|
+
processor_name = self.processor.name if self.processor is not None else "None"
|
|
84
|
+
endoscope_name = self.endoscope.name if self.endoscope is not None else "None"
|
|
85
|
+
center_name = self.center.name if self.center is not None else "None"
|
|
86
|
+
ffmpeg_meta_str = self.ffmpeg_meta.__str__()
|
|
87
|
+
import_meta_str = self.import_meta.__str__()
|
|
88
|
+
|
|
89
|
+
result_html = ""
|
|
90
|
+
|
|
91
|
+
result_html += f"Processor: {processor_name}\n"
|
|
92
|
+
result_html += f"Endoscope: {endoscope_name}\n"
|
|
93
|
+
result_html += f"Center: {center_name}\n"
|
|
94
|
+
result_html += f"FFMpeg Meta: {ffmpeg_meta_str}\n"
|
|
95
|
+
result_html += f"Import Meta: {import_meta_str}\n"
|
|
96
|
+
|
|
97
|
+
return result_html
|
|
98
|
+
|
|
99
|
+
def save(self, *args, **kwargs):
|
|
100
|
+
"""Ensures VideoImportMeta exists before saving."""
|
|
101
|
+
if self.import_meta is None:
|
|
102
|
+
self.import_meta = VideoImportMeta.objects.create()
|
|
103
|
+
super(VideoMeta, self).save(*args, **kwargs)
|
|
104
|
+
|
|
105
|
+
def initialize_ffmpeg_meta(self, video_path: Path):
|
|
106
|
+
"""
|
|
107
|
+
Initializes FFMpeg metadata for the video file if not already done.
|
|
108
|
+
Raises RuntimeError if FFMpegMeta creation fails.
|
|
109
|
+
"""
|
|
110
|
+
if self.ffmpeg_meta:
|
|
111
|
+
logger.debug("FFMpegMeta already exists for VideoMeta PK %s. Skipping initialization.", self.pk)
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
logger.info("Initializing FFMpegMeta for VideoMeta PK %s from %s", self.pk if self.pk else "(unsaved)", video_path.name)
|
|
115
|
+
try:
|
|
116
|
+
# FFMpegMeta.create_from_file now raises exceptions on failure
|
|
117
|
+
ffmpeg_instance = FFMpegMeta.create_from_file(video_path)
|
|
118
|
+
# If create_from_file succeeds, link it. No need to check for None.
|
|
119
|
+
self.ffmpeg_meta = ffmpeg_instance
|
|
120
|
+
# If the VideoMeta instance is already saved, save the link immediately.
|
|
121
|
+
# Otherwise, the link will be saved when VideoMeta itself is saved.
|
|
122
|
+
if self.pk:
|
|
123
|
+
self.save(update_fields=['ffmpeg_meta'])
|
|
124
|
+
logger.info("Successfully created and linked FFMpegMeta PK %s", self.ffmpeg_meta.pk)
|
|
125
|
+
|
|
126
|
+
except Exception as e:
|
|
127
|
+
# Log the error and re-raise it
|
|
128
|
+
logger.error("Failed to create or link FFMpegMeta from %s: %s", video_path, e, exc_info=True)
|
|
129
|
+
raise RuntimeError(f"Failed to create FFMpeg metadata from {video_path}") from e
|
|
130
|
+
|
|
131
|
+
def update_meta(self, video_path: Path):
|
|
132
|
+
"""
|
|
133
|
+
Updates the FFMpeg metadata from the file, replacing existing data.
|
|
134
|
+
Raises RuntimeError if FFMpegMeta creation fails.
|
|
135
|
+
"""
|
|
136
|
+
logger.info("Updating FFMpegMeta for VideoMeta PK %s from %s", self.pk, video_path.name)
|
|
137
|
+
existing_ffmpeg_pk = None
|
|
138
|
+
if self.ffmpeg_meta:
|
|
139
|
+
existing_ffmpeg_pk = self.ffmpeg_meta.pk
|
|
140
|
+
logger.debug("Deleting existing FFMpegMeta PK %s before update.", existing_ffmpeg_pk)
|
|
141
|
+
# Nullify the relation first before deleting the related object
|
|
142
|
+
self.ffmpeg_meta = None
|
|
143
|
+
self.save(update_fields=['ffmpeg_meta']) # Save the null relation
|
|
144
|
+
FFMpegMeta.objects.filter(pk=existing_ffmpeg_pk).delete() # Delete the old object
|
|
145
|
+
|
|
146
|
+
# initialize_ffmpeg_meta handles creation, linking, saving the link, and raises exceptions
|
|
147
|
+
self.initialize_ffmpeg_meta(video_path)
|
|
148
|
+
|
|
149
|
+
def get_endo_roi(self):
|
|
150
|
+
"""Retrieves the endoscope region of interest (ROI) from the associated processor."""
|
|
151
|
+
from ..medical.hardware import EndoscopyProcessor
|
|
152
|
+
|
|
153
|
+
processor: EndoscopyProcessor = self.processor
|
|
154
|
+
endo_roi = processor.get_roi_endoscope_image()
|
|
155
|
+
return endo_roi
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def fps(self) -> Optional[float]:
|
|
159
|
+
"""Returns the frame rate (FPS) from the linked FFMpegMeta."""
|
|
160
|
+
if not self.ffmpeg_meta:
|
|
161
|
+
logger.warning("FFMpegMeta not linked for VideoMeta PK %s. Cannot get FPS.", self.pk)
|
|
162
|
+
return None
|
|
163
|
+
return self.ffmpeg_meta.fps
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def duration(self) -> Optional[float]:
|
|
167
|
+
"""Returns the duration in seconds from the linked FFMpegMeta."""
|
|
168
|
+
return self.ffmpeg_meta.duration if self.ffmpeg_meta else None
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def width(self) -> Optional[int]:
|
|
172
|
+
"""Returns the video width in pixels from the linked FFMpegMeta."""
|
|
173
|
+
return self.ffmpeg_meta.width if self.ffmpeg_meta else None
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def height(self) -> Optional[int]:
|
|
177
|
+
"""Returns the video height in pixels from the linked FFMpegMeta."""
|
|
178
|
+
return self.ffmpeg_meta.height if self.ffmpeg_meta else None
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def frame_count(self) -> Optional[int]:
|
|
182
|
+
"""Calculates frame count based on duration and FPS from FFMpegMeta."""
|
|
183
|
+
if self.ffmpeg_meta and self.ffmpeg_meta.duration is not None and self.ffmpeg_meta.fps is not None and self.ffmpeg_meta.fps > 0:
|
|
184
|
+
return int(self.ffmpeg_meta.duration * self.ffmpeg_meta.fps)
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class FFMpegMeta(models.Model):
|
|
189
|
+
"""
|
|
190
|
+
Stores technical video stream information extracted using FFmpeg (ffprobe).
|
|
191
|
+
"""
|
|
192
|
+
width = models.IntegerField(null=True, blank=True)
|
|
193
|
+
height = models.IntegerField(null=True, blank=True)
|
|
194
|
+
duration = models.FloatField(null=True, blank=True) # Duration in seconds
|
|
195
|
+
frame_rate_num = models.IntegerField(null=True, blank=True) # Numerator for frame rate
|
|
196
|
+
frame_rate_den = models.IntegerField(null=True, blank=True) # Denominator for frame rate
|
|
197
|
+
codec_name = models.CharField(max_length=50, null=True, blank=True)
|
|
198
|
+
pixel_format = models.CharField(max_length=50, null=True, blank=True)
|
|
199
|
+
bit_rate = models.BigIntegerField(null=True, blank=True) # Bit rate in bits per second
|
|
200
|
+
raw_probe_data = models.JSONField(null=True, blank=True) # Store the full JSON output for debugging or future use
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def fps(self) -> Optional[float]:
|
|
204
|
+
"""Calculates and returns the frames per second (FPS) if possible."""
|
|
205
|
+
if self.frame_rate_num is not None and self.frame_rate_den is not None and self.frame_rate_den != 0:
|
|
206
|
+
return self.frame_rate_num / self.frame_rate_den
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def create_from_file(cls, file_path: Path):
|
|
211
|
+
"""
|
|
212
|
+
Creates an FFMpegMeta instance by running ffprobe on the given file path.
|
|
213
|
+
Raises RuntimeError on failure.
|
|
214
|
+
"""
|
|
215
|
+
logger.info("Running ffprobe on %s", file_path)
|
|
216
|
+
try:
|
|
217
|
+
probe_data = ffmpeg_wrapper.get_stream_info(file_path) # Use the new utility
|
|
218
|
+
except Exception as probe_err:
|
|
219
|
+
logger.error("ffprobe execution failed for %s: %s", file_path, probe_err, exc_info=True)
|
|
220
|
+
raise RuntimeError(f"ffprobe execution failed for {file_path}") from probe_err
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
if not probe_data or "streams" not in probe_data:
|
|
224
|
+
logger.error("Failed to get valid stream info from ffprobe for %s", file_path)
|
|
225
|
+
# Raise exception instead of returning None
|
|
226
|
+
raise RuntimeError(f"Invalid stream info from ffprobe for {file_path}")
|
|
227
|
+
|
|
228
|
+
video_stream = next((s for s in probe_data["streams"] if s.get("codec_type") == "video"), None)
|
|
229
|
+
|
|
230
|
+
if not video_stream:
|
|
231
|
+
logger.warning("No video stream found in ffprobe output for %s", file_path)
|
|
232
|
+
# Raise exception instead of returning None
|
|
233
|
+
raise RuntimeError(f"No video stream found in {file_path}")
|
|
234
|
+
|
|
235
|
+
# Extract data safely using .get()
|
|
236
|
+
width = video_stream.get("width")
|
|
237
|
+
height = video_stream.get("height")
|
|
238
|
+
duration_str = video_stream.get("duration")
|
|
239
|
+
# --- FIX: Handle potential format key ---
|
|
240
|
+
if duration_str is None and 'format' in probe_data and 'duration' in probe_data['format']:
|
|
241
|
+
duration_str = probe_data['format']['duration']
|
|
242
|
+
logger.debug("Using duration from format block: %s", duration_str)
|
|
243
|
+
# --- End Fix ---
|
|
244
|
+
duration = float(duration_str) if duration_str else None
|
|
245
|
+
|
|
246
|
+
# Frame rate can be tricky, often represented as "num/den"
|
|
247
|
+
frame_rate_str = video_stream.get("r_frame_rate")
|
|
248
|
+
# --- FIX: Fallback to avg_frame_rate if r_frame_rate is invalid ---
|
|
249
|
+
if not frame_rate_str or frame_rate_str == "0/0":
|
|
250
|
+
frame_rate_str = video_stream.get("avg_frame_rate")
|
|
251
|
+
logger.debug("Using avg_frame_rate as fallback: %s", frame_rate_str)
|
|
252
|
+
# --- End Fix ---
|
|
253
|
+
frame_rate_num, frame_rate_den = None, None
|
|
254
|
+
if frame_rate_str and "/" in frame_rate_str:
|
|
255
|
+
try:
|
|
256
|
+
num_str, den_str = frame_rate_str.split('/')
|
|
257
|
+
frame_rate_num = int(num_str)
|
|
258
|
+
frame_rate_den = int(den_str)
|
|
259
|
+
if frame_rate_den == 0: # Avoid division by zero
|
|
260
|
+
logger.warning("Invalid frame rate denominator (0) for %s", file_path)
|
|
261
|
+
frame_rate_num, frame_rate_den = None, None
|
|
262
|
+
except ValueError:
|
|
263
|
+
logger.warning("Could not parse frame rate '%s' for %s", frame_rate_str, file_path)
|
|
264
|
+
frame_rate_num, frame_rate_den = None, None
|
|
265
|
+
|
|
266
|
+
codec_name = video_stream.get("codec_name")
|
|
267
|
+
pixel_format = video_stream.get("pix_fmt")
|
|
268
|
+
bit_rate_str = video_stream.get("bit_rate")
|
|
269
|
+
# --- FIX: Handle potential format key for bit_rate ---
|
|
270
|
+
if bit_rate_str is None and 'format' in probe_data and 'bit_rate' in probe_data['format']:
|
|
271
|
+
bit_rate_str = probe_data['format']['bit_rate']
|
|
272
|
+
logger.debug("Using bit_rate from format block: %s", bit_rate_str)
|
|
273
|
+
# --- End Fix ---
|
|
274
|
+
bit_rate = int(bit_rate_str) if bit_rate_str else None
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
instance = cls.objects.create(
|
|
278
|
+
width=width,
|
|
279
|
+
height=height,
|
|
280
|
+
duration=duration,
|
|
281
|
+
frame_rate_num=frame_rate_num,
|
|
282
|
+
frame_rate_den=frame_rate_den,
|
|
283
|
+
codec_name=codec_name,
|
|
284
|
+
pixel_format=pixel_format,
|
|
285
|
+
bit_rate=bit_rate,
|
|
286
|
+
raw_probe_data=probe_data,
|
|
287
|
+
)
|
|
288
|
+
logger.info("Successfully created FFMpegMeta for %s (ID: %d)", file_path.name, instance.pk)
|
|
289
|
+
return instance
|
|
290
|
+
except Exception as e:
|
|
291
|
+
logger.error("Error creating FFMpegMeta DB record from %s: %s", file_path.name, e, exc_info=True)
|
|
292
|
+
# Raise exception instead of returning None
|
|
293
|
+
raise RuntimeError(f"Database error creating FFMpegMeta for {file_path.name}") from e
|
|
294
|
+
|
|
295
|
+
def __str__(self):
|
|
296
|
+
"""Returns a string summary of the FFmpeg metadata."""
|
|
297
|
+
result_html = ""
|
|
298
|
+
|
|
299
|
+
result_html += f"Width: {self.width}\n"
|
|
300
|
+
result_html += f"Height: {self.height}\n"
|
|
301
|
+
result_html += f"Duration: {self.duration}\n"
|
|
302
|
+
result_html += f"Frame Rate: {self.fps}\n"
|
|
303
|
+
result_html += f"Codec Name: {self.codec_name}\n"
|
|
304
|
+
result_html += f"Pixel Format: {self.pixel_format}\n"
|
|
305
|
+
result_html += f"Bit Rate: {self.bit_rate}\n"
|
|
306
|
+
|
|
307
|
+
return result_html
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class VideoImportMeta(models.Model):
|
|
311
|
+
"""
|
|
312
|
+
Stores metadata related to the import and processing status of a video.
|
|
313
|
+
"""
|
|
314
|
+
file_name = models.CharField(max_length=255, blank=True, null=True)
|
|
315
|
+
video_anonymized = models.BooleanField(default=False)
|
|
316
|
+
video_patient_data_detected = models.BooleanField(default=False)
|
|
317
|
+
outside_detected = models.BooleanField(default=False)
|
|
318
|
+
patient_data_removed = models.BooleanField(default=False)
|
|
319
|
+
outside_removed = models.BooleanField(default=False)
|
|
320
|
+
|
|
321
|
+
def __str__(self):
|
|
322
|
+
"""Returns a string summary of the import metadata."""
|
|
323
|
+
result_html = ""
|
|
324
|
+
|
|
325
|
+
result_html += f"Video anonymized: {self.video_anonymized}\n"
|
|
326
|
+
result_html += (
|
|
327
|
+
f"Video patient data detected: {self.video_patient_data_detected}\n"
|
|
328
|
+
)
|
|
329
|
+
result_html += f"Outside detected: {self.outside_detected}\n"
|
|
330
|
+
result_html += f"Patient data removed: {self.patient_data_removed}\n"
|
|
331
|
+
result_html += f"Outside removed: {self.outside_removed}\n"
|
|
332
|
+
return result_html
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, List, Tuple, Optional
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
# Import necessary models and utils used by the logic
|
|
6
|
+
from ..utils import find_segments_in_prediction_array
|
|
7
|
+
from ..label.label_video_segment import LabelVideoSegment
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
|
|
13
|
+
DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from .video_prediction_meta import VideoPredictionMeta
|
|
17
|
+
from ..label import Label
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def apply_running_mean_logic(instance: "VideoPredictionMeta", confidence_array: np.ndarray, window_size_in_seconds: Optional[float] = None) -> np.ndarray:
|
|
21
|
+
"""
|
|
22
|
+
Apply a running mean filter to the confidence array for smoothing.
|
|
23
|
+
"""
|
|
24
|
+
video_obj = instance.get_video()
|
|
25
|
+
fps = video_obj.get_fps()
|
|
26
|
+
|
|
27
|
+
if fps is None or fps <= 0:
|
|
28
|
+
logger.warning(f"Invalid FPS ({fps}) for {video_obj}. Cannot apply running mean. Returning original array.")
|
|
29
|
+
return confidence_array
|
|
30
|
+
|
|
31
|
+
if window_size_in_seconds is None:
|
|
32
|
+
window_size_in_seconds = DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN
|
|
33
|
+
|
|
34
|
+
window_size_in_frames = int(window_size_in_seconds * fps)
|
|
35
|
+
window_size_in_frames = max(window_size_in_frames, 1)
|
|
36
|
+
|
|
37
|
+
window = np.ones(window_size_in_frames) / window_size_in_frames
|
|
38
|
+
pad_size = window_size_in_frames // 2
|
|
39
|
+
|
|
40
|
+
padded_confidences = np.pad(
|
|
41
|
+
confidence_array,
|
|
42
|
+
(pad_size, pad_size),
|
|
43
|
+
"constant",
|
|
44
|
+
constant_values=(0.5, 0.5),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
running_mean = np.convolve(padded_confidences, window, mode="same")
|
|
48
|
+
start_index = pad_size
|
|
49
|
+
end_index = start_index + len(confidence_array)
|
|
50
|
+
running_mean = running_mean[start_index:end_index]
|
|
51
|
+
|
|
52
|
+
if running_mean.shape != confidence_array.shape:
|
|
53
|
+
logger.warning(f"Running mean output shape {running_mean.shape} differs from input {confidence_array.shape}. Check padding/slicing.")
|
|
54
|
+
# Return original array on shape mismatch to avoid downstream errors
|
|
55
|
+
return confidence_array
|
|
56
|
+
|
|
57
|
+
return running_mean
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_size_in_seconds: Optional[float] = None) -> Optional[np.ndarray]:
|
|
61
|
+
"""
|
|
62
|
+
Fetches predictions, applies smoothing, and returns the binary prediction array.
|
|
63
|
+
Does not save the array itself.
|
|
64
|
+
"""
|
|
65
|
+
from ..label import ImageClassificationAnnotation
|
|
66
|
+
video_obj = instance.get_video()
|
|
67
|
+
model_meta = instance.model_meta
|
|
68
|
+
label_list = instance.get_label_list()
|
|
69
|
+
num_frames = video_obj.frame_count
|
|
70
|
+
|
|
71
|
+
if num_frames is None or num_frames <= 0:
|
|
72
|
+
logger.warning(f"Cannot calculate prediction array for {video_obj} with invalid frame count ({num_frames}).")
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
if not label_list:
|
|
76
|
+
logger.warning(f"No labels found for model {model_meta}. Cannot calculate prediction array.")
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
prediction_array = np.zeros((num_frames, len(label_list)))
|
|
80
|
+
|
|
81
|
+
base_pred_qs = ImageClassificationAnnotation.objects.filter(
|
|
82
|
+
model_meta=model_meta,
|
|
83
|
+
frame__video_file=video_obj
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
for i, label in enumerate(label_list):
|
|
87
|
+
predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list(
|
|
88
|
+
"frame__frame_number", "confidence"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Initialize with 0.5 (neutral confidence)
|
|
92
|
+
confidences = np.full(num_frames, 0.5)
|
|
93
|
+
found_predictions = False
|
|
94
|
+
for frame_num, confidence in predictions:
|
|
95
|
+
if 0 <= frame_num < num_frames:
|
|
96
|
+
confidences[frame_num] = confidence
|
|
97
|
+
found_predictions = True
|
|
98
|
+
else:
|
|
99
|
+
logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames-1}). Skipping.")
|
|
100
|
+
|
|
101
|
+
if not found_predictions:
|
|
102
|
+
logger.warning(f"No predictions found for label '{label.name}' in {video_obj}. Using default confidence.")
|
|
103
|
+
|
|
104
|
+
smooth_confidences = apply_running_mean_logic(
|
|
105
|
+
instance, confidences, window_size_in_seconds
|
|
106
|
+
)
|
|
107
|
+
# Threshold smoothed confidences
|
|
108
|
+
binary_predictions = smooth_confidences > 0.5
|
|
109
|
+
prediction_array[:, i] = binary_predictions
|
|
110
|
+
|
|
111
|
+
return prediction_array
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def create_video_segments_for_label_logic(instance: "VideoPredictionMeta", segments: List[Tuple[int, int]], label: "Label"):
|
|
115
|
+
"""
|
|
116
|
+
Creates LabelVideoSegment instances for the given label and segments.
|
|
117
|
+
"""
|
|
118
|
+
from ..other import InformationSource
|
|
119
|
+
video_obj = instance.get_video()
|
|
120
|
+
information_source, _ = InformationSource.objects.get_or_create(name="prediction")
|
|
121
|
+
|
|
122
|
+
segments_to_create = []
|
|
123
|
+
for start_frame, end_frame in segments:
|
|
124
|
+
segment_data = {
|
|
125
|
+
"start_frame_number": start_frame,
|
|
126
|
+
"end_frame_number": end_frame,
|
|
127
|
+
"source": information_source,
|
|
128
|
+
"label": label,
|
|
129
|
+
"prediction_meta": instance,
|
|
130
|
+
"video_file": video_obj,
|
|
131
|
+
}
|
|
132
|
+
# Check for existence before creating the object instance
|
|
133
|
+
if not LabelVideoSegment.objects.filter(
|
|
134
|
+
video_file=video_obj,
|
|
135
|
+
prediction_meta=instance,
|
|
136
|
+
label=label,
|
|
137
|
+
start_frame_number=start_frame,
|
|
138
|
+
end_frame_number=end_frame
|
|
139
|
+
).exists():
|
|
140
|
+
segments_to_create.append(LabelVideoSegment(**segment_data))
|
|
141
|
+
|
|
142
|
+
if segments_to_create:
|
|
143
|
+
LabelVideoSegment.objects.bulk_create(segments_to_create)
|
|
144
|
+
logger.info(f"Created {len(segments_to_create)} video segments for label '{label.name}' in {video_obj}.")
|
|
145
|
+
else:
|
|
146
|
+
logger.info(f"No new video segments needed for label '{label.name}' in {video_obj}.")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def create_video_segments_logic(instance: "VideoPredictionMeta", segment_length_threshold_in_s: Optional[float] = None):
|
|
150
|
+
"""
|
|
151
|
+
Generates LabelVideoSegments based on the stored prediction array.
|
|
152
|
+
"""
|
|
153
|
+
if segment_length_threshold_in_s is None:
|
|
154
|
+
segment_length_threshold_in_s = DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S
|
|
155
|
+
|
|
156
|
+
video_obj = instance.get_video()
|
|
157
|
+
fps = video_obj.get_fps()
|
|
158
|
+
|
|
159
|
+
if fps is None or fps <= 0:
|
|
160
|
+
logger.warning(f"Cannot create video segments for {video_obj} with invalid FPS ({fps}).")
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
min_frame_length = int(segment_length_threshold_in_s * fps)
|
|
164
|
+
min_frame_length = max(min_frame_length, 1) # Ensure minimum length is at least 1
|
|
165
|
+
|
|
166
|
+
label_list = instance.get_label_list()
|
|
167
|
+
if not label_list:
|
|
168
|
+
logger.warning(f"No labels associated with {instance}. Cannot create segments.")
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
prediction_array = instance.get_prediction_array()
|
|
172
|
+
if prediction_array is None:
|
|
173
|
+
logger.info(f"Prediction array not found for {instance}. Calculating...")
|
|
174
|
+
instance.calculate_prediction_array() # This will save the array internally
|
|
175
|
+
prediction_array = instance.get_prediction_array() # Fetch again
|
|
176
|
+
if prediction_array is None:
|
|
177
|
+
logger.error(f"Failed to get or calculate prediction array for {instance}. Cannot create segments.")
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
if prediction_array.shape[1] != len(label_list):
|
|
181
|
+
logger.warning(f"Prediction array shape {prediction_array.shape} incompatible with label list length {len(label_list)} for {instance}.")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
logger.info(f"Creating video segments for {instance} (min length: {min_frame_length} frames)...")
|
|
185
|
+
for i, label in enumerate(label_list):
|
|
186
|
+
binary_predictions = prediction_array[:, i].astype(bool)
|
|
187
|
+
segments = find_segments_in_prediction_array(binary_predictions, min_frame_length)
|
|
188
|
+
if segments:
|
|
189
|
+
create_video_segments_for_label_logic(instance, segments, label)
|
|
190
|
+
logger.info(f"Finished creating video segments for {instance}.")
|