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,511 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.db.models import Q, CheckConstraint, F
|
|
3
|
+
from typing import TYPE_CHECKING, Union, Optional, Tuple
|
|
4
|
+
from tqdm import tqdm
|
|
5
|
+
import logging
|
|
6
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
7
|
+
from ._create_from_video import _create_from_video
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from endoreg_db.models import (
|
|
13
|
+
LabelVideoSegmentState,
|
|
14
|
+
VideoFile,
|
|
15
|
+
Frame,
|
|
16
|
+
Label,
|
|
17
|
+
InformationSource,
|
|
18
|
+
ModelMeta,
|
|
19
|
+
VideoPredictionMeta,
|
|
20
|
+
PatientFinding,
|
|
21
|
+
ImageClassificationAnnotation,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
class LabelVideoSegment(models.Model):
|
|
25
|
+
"""
|
|
26
|
+
Represents a labeled segment within a video, defined by start and end frame numbers.
|
|
27
|
+
|
|
28
|
+
A segment must be associated with exactly one `VideoFile`.
|
|
29
|
+
If it originates from a prediction, it links to a single `VideoPredictionMeta`.
|
|
30
|
+
"""
|
|
31
|
+
start_frame_number = models.IntegerField()
|
|
32
|
+
end_frame_number = models.IntegerField()
|
|
33
|
+
source = models.ForeignKey(
|
|
34
|
+
"InformationSource", on_delete=models.SET_NULL, null=True
|
|
35
|
+
)
|
|
36
|
+
label = models.ForeignKey("Label", on_delete=models.SET_NULL, null=True, blank=True)
|
|
37
|
+
|
|
38
|
+
# Single ForeignKey to the unified VideoFile model
|
|
39
|
+
video_file = models.ForeignKey(
|
|
40
|
+
"VideoFile",
|
|
41
|
+
on_delete=models.CASCADE,
|
|
42
|
+
related_name="label_video_segments",
|
|
43
|
+
null=False,
|
|
44
|
+
blank=False,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Single ForeignKey to the unified VideoPredictionMeta model
|
|
48
|
+
prediction_meta = models.ForeignKey(
|
|
49
|
+
"VideoPredictionMeta",
|
|
50
|
+
on_delete=models.SET_NULL,
|
|
51
|
+
null=True,
|
|
52
|
+
blank=True,
|
|
53
|
+
related_name="label_video_segments",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# M2M relationship with patient finding
|
|
57
|
+
patient_findings = models.ManyToManyField(
|
|
58
|
+
"PatientFinding",
|
|
59
|
+
related_name="video_segments",
|
|
60
|
+
blank=True,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if TYPE_CHECKING:
|
|
64
|
+
video_file: "VideoFile"
|
|
65
|
+
label: Optional["Label"]
|
|
66
|
+
source: Optional["InformationSource"]
|
|
67
|
+
prediction_meta: Optional["VideoPredictionMeta"]
|
|
68
|
+
patient_findings: models.QuerySet["PatientFinding"]
|
|
69
|
+
model_meta: Optional["ModelMeta"]
|
|
70
|
+
state:"LabelVideoSegmentState"
|
|
71
|
+
|
|
72
|
+
class Meta:
|
|
73
|
+
constraints = [
|
|
74
|
+
CheckConstraint(
|
|
75
|
+
condition=Q(start_frame_number__lt=F("end_frame_number")),
|
|
76
|
+
name="segment_start_lt_end"
|
|
77
|
+
),
|
|
78
|
+
]
|
|
79
|
+
indexes = [
|
|
80
|
+
models.Index(fields=['video_file', 'label', 'start_frame_number']),
|
|
81
|
+
models.Index(fields=['prediction_meta', 'label']),
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def start_time(self) -> float:
|
|
86
|
+
"""
|
|
87
|
+
Return the segment's start time in seconds, calculated from the start frame number and video FPS.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
float: Start time in seconds. Returns 0.0 if FPS is unavailable or zero.
|
|
91
|
+
"""
|
|
92
|
+
fps = self._get_fps_safe()
|
|
93
|
+
if fps == 0.0:
|
|
94
|
+
return 0.0
|
|
95
|
+
return self.start_frame_number / fps
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def end_time(self) -> float:
|
|
99
|
+
"""
|
|
100
|
+
Return the segment's end time in seconds, calculated from the end frame number and video FPS.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
float: End time in seconds, or 0.0 if FPS is unavailable.
|
|
104
|
+
"""
|
|
105
|
+
fps = self._get_fps_safe()
|
|
106
|
+
if fps == 0.0:
|
|
107
|
+
return 0.0
|
|
108
|
+
return self.end_frame_number / fps
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def segment_duration(self) -> float:
|
|
112
|
+
"""
|
|
113
|
+
Returns the duration of the video segment in seconds, calculated as the difference between end and start times.
|
|
114
|
+
"""
|
|
115
|
+
return self.end_time - self.start_time
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def is_validated(self) -> bool:
|
|
119
|
+
"""
|
|
120
|
+
Returns True if the segment's associated state indicates it is validated; otherwise, returns False if the state is missing or inaccessible.
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
# Access the related state object directly.
|
|
124
|
+
# Assumes the OneToOneField relationship ensures its existence after save.
|
|
125
|
+
return self.state.is_validated
|
|
126
|
+
except ObjectDoesNotExist:
|
|
127
|
+
# This might happen if the state wasn't created yet, though the save method tries to prevent this.
|
|
128
|
+
logger.warning("LabelVideoSegmentState not found for LabelVideoSegment %s.", self.pk)
|
|
129
|
+
return False
|
|
130
|
+
except AttributeError:
|
|
131
|
+
# Should not happen if self.state exists and has the is_validated attribute.
|
|
132
|
+
logger.error("AttributeError accessing 'state.is_validated' for LabelVideoSegment %s.", self.pk)
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def extract_segment_frame_files(self, overwrite: bool = False, **kwargs) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
Extracts frame files specifically for this segment using the associated VideoFile.
|
|
138
|
+
Passes additional keyword arguments to extract_frames.
|
|
139
|
+
"""
|
|
140
|
+
from endoreg_db.models import VideoFile
|
|
141
|
+
if not isinstance(self.video_file, VideoFile):
|
|
142
|
+
raise ValueError("Cannot extract frame files: No associated VideoFile.")
|
|
143
|
+
return self.video_file.extract_specific_frame_range(
|
|
144
|
+
start_frame=self.start_frame_number,
|
|
145
|
+
end_frame=self.end_frame_number,
|
|
146
|
+
overwrite=overwrite,
|
|
147
|
+
**kwargs
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def delete_frame_files(self) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Delete the frame files corresponding to this segment's frame range from the associated video file.
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
ValueError: If there is no associated VideoFile.
|
|
156
|
+
"""
|
|
157
|
+
from endoreg_db.models import VideoFile
|
|
158
|
+
if not isinstance(self.video_file, VideoFile):
|
|
159
|
+
raise ValueError("Cannot delete frame files: No associated VideoFile.")
|
|
160
|
+
self.video_file.delete_specific_frame_range(
|
|
161
|
+
start_frame=self.start_frame_number,
|
|
162
|
+
end_frame=self.end_frame_number
|
|
163
|
+
)
|
|
164
|
+
@classmethod
|
|
165
|
+
def safe_create(cls, video_file, label, start_frame_number, end_frame_number, **kwargs):
|
|
166
|
+
"""
|
|
167
|
+
Create a new LabelVideoSegment instance after validating the frame range.
|
|
168
|
+
|
|
169
|
+
Validates that the provided start and end frame numbers are appropriate for the given video file before creating the segment. Raises a ValueError if validation fails.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
LabelVideoSegment: The newly created segment instance.
|
|
173
|
+
"""
|
|
174
|
+
cls.validate_frame_range(start_frame_number, end_frame_number, video_file=video_file)
|
|
175
|
+
return cls.objects.create(
|
|
176
|
+
video_file=video_file,
|
|
177
|
+
label=label,
|
|
178
|
+
start_frame_number=start_frame_number,
|
|
179
|
+
end_frame_number=end_frame_number,
|
|
180
|
+
**kwargs
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def save(self, *args, **kwargs):
|
|
184
|
+
"""
|
|
185
|
+
Saves the LabelVideoSegment instance and ensures its associated state object exists.
|
|
186
|
+
|
|
187
|
+
Overrides the default save behavior to guarantee that a related LabelVideoSegmentState is created or retrieved after saving.
|
|
188
|
+
"""
|
|
189
|
+
from endoreg_db.models import LabelVideoSegmentState
|
|
190
|
+
# Call the original save method first
|
|
191
|
+
super().save(*args, **kwargs)
|
|
192
|
+
|
|
193
|
+
# Ensure state exists after saving, without nested transactions
|
|
194
|
+
if self.pk:
|
|
195
|
+
# `defaults={}` ensures we do not re-fetch the just-saved object.
|
|
196
|
+
# This logic is now encapsulated in get_or_create_state
|
|
197
|
+
self.get_or_create_state()
|
|
198
|
+
|
|
199
|
+
def get_or_create_state(self) -> Tuple["LabelVideoSegmentState", bool]:
|
|
200
|
+
"""
|
|
201
|
+
Retrieves or creates the associated LabelVideoSegmentState object.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Tuple[LabelVideoSegmentState, bool]: A tuple containing the state
|
|
205
|
+
object and a boolean indicating
|
|
206
|
+
if it was created.
|
|
207
|
+
"""
|
|
208
|
+
from endoreg_db.models import LabelVideoSegmentState
|
|
209
|
+
state, created = LabelVideoSegmentState.objects.get_or_create(origin=self)
|
|
210
|
+
return state, created
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def create_from_video(
|
|
214
|
+
cls,
|
|
215
|
+
source: "VideoFile",
|
|
216
|
+
prediction_meta: Optional["VideoPredictionMeta"],
|
|
217
|
+
label: Optional["Label"],
|
|
218
|
+
start_frame_number: int,
|
|
219
|
+
end_frame_number: int,
|
|
220
|
+
):
|
|
221
|
+
"""
|
|
222
|
+
Create a LabelVideoSegment instance from a VideoFile.
|
|
223
|
+
"""
|
|
224
|
+
return _create_from_video(
|
|
225
|
+
cls,
|
|
226
|
+
source,
|
|
227
|
+
prediction_meta,
|
|
228
|
+
label,
|
|
229
|
+
start_frame_number,
|
|
230
|
+
end_frame_number
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def get_video(self) -> "VideoFile":
|
|
234
|
+
"""Returns the associated VideoFile instance."""
|
|
235
|
+
try:
|
|
236
|
+
# Accessing the field directly is sufficient.
|
|
237
|
+
# Django handles the retrieval or raises an appropriate exception if not set/found.
|
|
238
|
+
_ = self.video_file.pk # Access pk to ensure it's loaded
|
|
239
|
+
return self.video_file
|
|
240
|
+
except ObjectDoesNotExist:
|
|
241
|
+
# This might occur if the related VideoFile was deleted unexpectedly.
|
|
242
|
+
logger.error("Associated VideoFile not found for LabelVideoSegment %s.", self.pk)
|
|
243
|
+
raise ValueError(f"LabelVideoSegment {self.pk} is not associated with a valid VideoFile.")
|
|
244
|
+
|
|
245
|
+
def __str__(self):
|
|
246
|
+
try:
|
|
247
|
+
video_obj = self.get_video()
|
|
248
|
+
label_name = self.label.name if self.label else "No Label"
|
|
249
|
+
active_path = video_obj.active_file_path
|
|
250
|
+
video_identifier = active_path.name if active_path else f"UUID {video_obj.uuid}"
|
|
251
|
+
|
|
252
|
+
str_repr = (
|
|
253
|
+
f"{video_identifier} Label - {label_name} - "
|
|
254
|
+
f"{self.start_frame_number} - {self.end_frame_number}"
|
|
255
|
+
)
|
|
256
|
+
except ObjectDoesNotExist: # More specific exception
|
|
257
|
+
str_repr = f"Segment {self.pk} (Error: Associated VideoFile missing)"
|
|
258
|
+
except ValueError as e: # Catch specific error from get_video
|
|
259
|
+
str_repr = f"Segment {self.pk} (Error: {e})"
|
|
260
|
+
except Exception as e:
|
|
261
|
+
logger.warning("Error generating string representation for LabelVideoSegment %s: %s", self.pk, e)
|
|
262
|
+
str_repr = f"Segment {self.pk} (Error: {e})"
|
|
263
|
+
|
|
264
|
+
return str_repr
|
|
265
|
+
|
|
266
|
+
def get_model_meta(self) -> Optional["ModelMeta"]:
|
|
267
|
+
"""
|
|
268
|
+
Retrieve the associated ModelMeta object from the segment's prediction metadata, if available.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
ModelMeta or None: The related ModelMeta instance, or None if no prediction metadata is set.
|
|
272
|
+
"""
|
|
273
|
+
if self.prediction_meta:
|
|
274
|
+
return self.prediction_meta.model_meta
|
|
275
|
+
return None
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def frames(self) -> Union[models.QuerySet["Frame"], list]:
|
|
279
|
+
"""
|
|
280
|
+
Return all frames within the segment's frame range.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
QuerySet[Frame] or list: Frames from the associated video file that fall within the segment's start and end frame numbers. Returns an empty list if the video file is unavailable.
|
|
284
|
+
"""
|
|
285
|
+
return self.get_frames()
|
|
286
|
+
|
|
287
|
+
def get_frames(self) -> Union[models.QuerySet["Frame"], list]:
|
|
288
|
+
"""
|
|
289
|
+
Retrieve all frames within the segment's frame range from the associated video.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
QuerySet[Frame]: Frames with frame numbers in [start_frame_number, end_frame_number) ordered by frame number, or an empty queryset if unavailable.
|
|
293
|
+
"""
|
|
294
|
+
from endoreg_db.models.media.frame import Frame
|
|
295
|
+
try:
|
|
296
|
+
video_obj = self.get_video()
|
|
297
|
+
return video_obj.frames.filter(
|
|
298
|
+
frame_number__gte=self.start_frame_number,
|
|
299
|
+
frame_number__lt=self.end_frame_number
|
|
300
|
+
).order_by('frame_number')
|
|
301
|
+
except ValueError:
|
|
302
|
+
logger.error("Cannot get frames for segment %s: No associated VideoFile.", self.pk)
|
|
303
|
+
return Frame.objects.none()
|
|
304
|
+
except AttributeError:
|
|
305
|
+
logger.error("Cannot get frames for segment %s: 'frames' related manager not found on VideoFile.", self.pk)
|
|
306
|
+
return Frame.objects.none()
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def all_frame_annotations(self) -> models.QuerySet["ImageClassificationAnnotation"]:
|
|
310
|
+
"""
|
|
311
|
+
Return all image classification annotations for frames within this segment that match the segment's label.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
QuerySet: ImageClassificationAnnotation objects for frames in the segment with the segment's label. Returns an empty queryset if the segment is not associated with a video.
|
|
315
|
+
"""
|
|
316
|
+
from endoreg_db.models import ImageClassificationAnnotation
|
|
317
|
+
|
|
318
|
+
try:
|
|
319
|
+
video_obj = self.get_video()
|
|
320
|
+
return ImageClassificationAnnotation.objects.filter(
|
|
321
|
+
frame__video=video_obj, # Changed frame__video_file to frame__video
|
|
322
|
+
frame__frame_number__gte=self.start_frame_number,
|
|
323
|
+
frame__frame_number__lt=self.end_frame_number,
|
|
324
|
+
label=self.label
|
|
325
|
+
)
|
|
326
|
+
except ValueError:
|
|
327
|
+
logger.error("Cannot get annotations for segment %s: No associated VideoFile.", self.pk)
|
|
328
|
+
return ImageClassificationAnnotation.objects.none()
|
|
329
|
+
|
|
330
|
+
@property
|
|
331
|
+
def frame_predictions(self) -> models.QuerySet["ImageClassificationAnnotation"]:
|
|
332
|
+
"""
|
|
333
|
+
Return prediction annotations for frames within this segment and matching the segment's label.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
QuerySet: ImageClassificationAnnotation objects for frames in the segment, filtered by label and information source type "prediction".
|
|
337
|
+
"""
|
|
338
|
+
from endoreg_db.models import ImageClassificationAnnotation
|
|
339
|
+
|
|
340
|
+
try:
|
|
341
|
+
video_obj = self.get_video()
|
|
342
|
+
return ImageClassificationAnnotation.objects.filter(
|
|
343
|
+
frame__video=video_obj, # Changed frame__video_file to frame__video
|
|
344
|
+
frame__frame_number__gte=self.start_frame_number,
|
|
345
|
+
frame__frame_number__lt=self.end_frame_number,
|
|
346
|
+
label=self.label,
|
|
347
|
+
information_source__information_source_types__name="prediction"
|
|
348
|
+
)
|
|
349
|
+
except ValueError:
|
|
350
|
+
logger.error("Cannot get predictions for segment %s: No associated VideoFile.", self.pk)
|
|
351
|
+
return ImageClassificationAnnotation.objects.none()
|
|
352
|
+
|
|
353
|
+
@property
|
|
354
|
+
def manual_frame_annotations(self) -> models.QuerySet["ImageClassificationAnnotation"]:
|
|
355
|
+
"""
|
|
356
|
+
Return manual image classification annotations for frames within this segment and matching the segment's label.
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
QuerySet: Manual `ImageClassificationAnnotation` objects for the segment's frames and label. Returns an empty queryset if the segment is not associated with a video.
|
|
360
|
+
"""
|
|
361
|
+
from endoreg_db.models import ImageClassificationAnnotation
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
video_obj = self.get_video()
|
|
365
|
+
return ImageClassificationAnnotation.objects.filter(
|
|
366
|
+
frame__video=video_obj, # Changed frame__video_file to frame__video
|
|
367
|
+
frame__frame_number__gte=self.start_frame_number,
|
|
368
|
+
frame__frame_number__lt=self.end_frame_number,
|
|
369
|
+
label=self.label,
|
|
370
|
+
information_source__information_source_types__name="manual_annotation"
|
|
371
|
+
)
|
|
372
|
+
except ValueError:
|
|
373
|
+
logger.error("Cannot get manual annotations for segment %s: No associated VideoFile.", self.pk)
|
|
374
|
+
return ImageClassificationAnnotation.objects.none()
|
|
375
|
+
|
|
376
|
+
def get_segment_len_in_s(self) -> float:
|
|
377
|
+
"""
|
|
378
|
+
Return the duration of the video segment in seconds, based on frame numbers and video FPS.
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
float: Segment duration in seconds, or 0.0 if FPS is invalid or video is unavailable.
|
|
382
|
+
"""
|
|
383
|
+
try:
|
|
384
|
+
video_obj = self.get_video()
|
|
385
|
+
fps = video_obj.get_fps()
|
|
386
|
+
if fps is None or fps <= 0:
|
|
387
|
+
logger.warning("Could not determine valid FPS for %s. Cannot calculate segment length in seconds.", video_obj)
|
|
388
|
+
return 0.0
|
|
389
|
+
return (self.end_frame_number - self.start_frame_number) / fps
|
|
390
|
+
except ValueError as e: # Catch error from get_video
|
|
391
|
+
logger.error("Cannot calculate segment length for segment %s: %s", self.pk, e)
|
|
392
|
+
return 0.0
|
|
393
|
+
|
|
394
|
+
def get_frames_without_annotation(self, n_frames: int) -> Union[list["Frame"], list]:
|
|
395
|
+
"""
|
|
396
|
+
Get up to n frames within the segment that do not have an ImageClassificationAnnotation
|
|
397
|
+
for this segment's label.
|
|
398
|
+
"""
|
|
399
|
+
from endoreg_db.models import ImageClassificationAnnotation
|
|
400
|
+
|
|
401
|
+
frames_qs = self.get_frames()
|
|
402
|
+
if not isinstance(frames_qs, models.QuerySet) or not frames_qs.exists():
|
|
403
|
+
return []
|
|
404
|
+
|
|
405
|
+
if not self.label:
|
|
406
|
+
logger.warning("Segment %s has no label. Cannot find frames without annotation.", self.pk)
|
|
407
|
+
return []
|
|
408
|
+
|
|
409
|
+
annotated_frame_ids = ImageClassificationAnnotation.objects.filter(
|
|
410
|
+
frame__in=frames_qs.values_list('id', flat=True),
|
|
411
|
+
label=self.label
|
|
412
|
+
).values_list('frame_id', flat=True)
|
|
413
|
+
|
|
414
|
+
frames_without_annotation = list(frames_qs.exclude(id__in=annotated_frame_ids)[:n_frames])
|
|
415
|
+
return frames_without_annotation
|
|
416
|
+
|
|
417
|
+
def generate_annotations(self):
|
|
418
|
+
"""
|
|
419
|
+
Creates image classification annotations for all frames in the segment if the segment is linked to a prediction, avoiding duplicates.
|
|
420
|
+
|
|
421
|
+
Annotations are generated only if the segment has associated prediction metadata, model metadata, and label. Existing annotations for the same frame, label, model, and information source are not duplicated. Uses bulk creation for efficiency.
|
|
422
|
+
"""
|
|
423
|
+
if not self.prediction_meta:
|
|
424
|
+
logger.info("Skipping annotation generation for segment %s: Requires linked VideoPredictionMeta.", self.id)
|
|
425
|
+
return
|
|
426
|
+
|
|
427
|
+
from endoreg_db.models import ImageClassificationAnnotation, InformationSource
|
|
428
|
+
|
|
429
|
+
information_source = self.source
|
|
430
|
+
if not information_source:
|
|
431
|
+
information_source, _ = InformationSource.objects.get_or_create(name="prediction")
|
|
432
|
+
|
|
433
|
+
model_meta = self.get_model_meta()
|
|
434
|
+
label = self.label
|
|
435
|
+
|
|
436
|
+
if not model_meta or not label:
|
|
437
|
+
logger.warning("Missing model_meta or label for segment %s. Skipping annotation generation.", self.id)
|
|
438
|
+
return
|
|
439
|
+
|
|
440
|
+
frames_queryset = self.get_frames().only('id')
|
|
441
|
+
if not isinstance(frames_queryset, models.QuerySet):
|
|
442
|
+
logger.error("Could not get frame queryset for segment %s. Skipping.", self.id)
|
|
443
|
+
return
|
|
444
|
+
|
|
445
|
+
existing_annotation_frame_ids = set(
|
|
446
|
+
ImageClassificationAnnotation.objects.filter(
|
|
447
|
+
frame_id__in=frames_queryset.values('id'),
|
|
448
|
+
label=label,
|
|
449
|
+
model_meta=model_meta,
|
|
450
|
+
information_source=information_source,
|
|
451
|
+
).values_list('frame_id', flat=True)
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
annotations_to_create = []
|
|
455
|
+
frames_to_annotate = frames_queryset.exclude(id__in=existing_annotation_frame_ids)
|
|
456
|
+
|
|
457
|
+
for frame in tqdm(frames_to_annotate.iterator(), total=frames_to_annotate.count(), desc=f"Preparing annotations for segment {self.id} ({label.name})"):
|
|
458
|
+
annotations_to_create.append(
|
|
459
|
+
ImageClassificationAnnotation(
|
|
460
|
+
frame=frame,
|
|
461
|
+
label=label,
|
|
462
|
+
model_meta=model_meta,
|
|
463
|
+
value=True,
|
|
464
|
+
information_source=information_source,
|
|
465
|
+
)
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
if annotations_to_create:
|
|
469
|
+
logger.info("Bulk creating %d annotations for segment %s...", len(annotations_to_create), self.id)
|
|
470
|
+
ImageClassificationAnnotation.objects.bulk_create(annotations_to_create, ignore_conflicts=True)
|
|
471
|
+
logger.info("Bulk creation complete.")
|
|
472
|
+
else:
|
|
473
|
+
logger.info("No new annotations needed for segment %s.", self.id)
|
|
474
|
+
|
|
475
|
+
def _get_fps_safe(self):
|
|
476
|
+
"""
|
|
477
|
+
Safely retrieves the frames per second (FPS) value from the associated video.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
float: The FPS of the associated video, or 0.0 if unavailable or invalid.
|
|
481
|
+
"""
|
|
482
|
+
video_obj = self.get_video()
|
|
483
|
+
if video_obj is None or video_obj.get_fps() is None:
|
|
484
|
+
return 0.0
|
|
485
|
+
return video_obj.get_fps()
|
|
486
|
+
|
|
487
|
+
@staticmethod
|
|
488
|
+
def validate_frame_range(start_frame_number: int, end_frame_number: int, video_file=None):
|
|
489
|
+
"""
|
|
490
|
+
Validate that the provided frame numbers define a valid segment range, optionally checking against a video's frame count.
|
|
491
|
+
|
|
492
|
+
Parameters:
|
|
493
|
+
start_frame_number (int): The starting frame number of the segment.
|
|
494
|
+
end_frame_number (int): The ending frame number of the segment.
|
|
495
|
+
video_file: Optional video file object to validate frame numbers against its frame count.
|
|
496
|
+
|
|
497
|
+
Raises:
|
|
498
|
+
ValueError: If frame numbers are not integers, are negative, are out of order, or exceed the video's frame count.
|
|
499
|
+
"""
|
|
500
|
+
if not isinstance(start_frame_number, int) or not isinstance(end_frame_number, int):
|
|
501
|
+
raise ValueError("start_frame_number and end_frame_number must be integers.")
|
|
502
|
+
if start_frame_number < 0:
|
|
503
|
+
raise ValueError("start_frame_number must be non-negative.")
|
|
504
|
+
if end_frame_number < start_frame_number:
|
|
505
|
+
raise ValueError("end_frame_number must be equal or greater than start_frame_number.")
|
|
506
|
+
if video_file is not None:
|
|
507
|
+
frame_count = getattr(video_file, 'frame_count', None)
|
|
508
|
+
if frame_count is not None and end_frame_number > frame_count:
|
|
509
|
+
raise ValueError(f"end_frame_number ({end_frame_number}) exceeds video frame count ({frame_count}).")
|
|
510
|
+
|
|
511
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
class VideoSegmentationLabelManager(models.Manager):
|
|
4
|
+
"""
|
|
5
|
+
Manager for VideoSegmentationLabel with custom query methods.
|
|
6
|
+
"""
|
|
7
|
+
def get_by_natural_key(self, name: str) -> "VideoSegmentationLabel":
|
|
8
|
+
return self.get(name=name)
|
|
9
|
+
|
|
10
|
+
class VideoSegmentationLabel(models.Model):
|
|
11
|
+
"""
|
|
12
|
+
Represents a label for video segmentation annotations.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
name (str): The name of the label.
|
|
16
|
+
description (str): A description of the label.
|
|
17
|
+
color (str): The color associated with the label.
|
|
18
|
+
order_priority (int): The priority for ordering labels.
|
|
19
|
+
"""
|
|
20
|
+
objects = VideoSegmentationLabelManager()
|
|
21
|
+
|
|
22
|
+
name = models.CharField(max_length=255)
|
|
23
|
+
description = models.TextField(blank=True, null=True)
|
|
24
|
+
color = models.CharField(max_length=255, blank=True, null=True)
|
|
25
|
+
order_priority = models.IntegerField(default=0)
|
|
26
|
+
|
|
27
|
+
def natural_key(self) -> tuple[str]:
|
|
28
|
+
return (self.name,)
|
|
29
|
+
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
return str(self.name)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models import VideoSegmentationLabel
|
|
7
|
+
|
|
8
|
+
class VideoSegmentationLabelSetManager(models.Manager):
|
|
9
|
+
def get_by_natural_key(self, name):
|
|
10
|
+
return self.get(name=name)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class VideoSegmentationLabelSet(models.Model):
|
|
14
|
+
name = models.CharField(max_length=255)
|
|
15
|
+
description = models.TextField(blank=True, null=True)
|
|
16
|
+
labels = models.ManyToManyField("VideoSegmentationLabel", related_name="labelsets")
|
|
17
|
+
|
|
18
|
+
objects = VideoSegmentationLabelSetManager()
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
labels: models.QuerySet["VideoSegmentationLabel"]
|
|
22
|
+
|
|
23
|
+
def natural_key(self):
|
|
24
|
+
return (self.name,)
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return str(self.name)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .video import VideoFile, VideoMetadata, VideoProcessingHistory
|
|
2
|
+
from .frame import Frame
|
|
3
|
+
from .pdf import RawPdfFile, DocumentType, AnonymExaminationReport, ReportReaderConfig, ReportReaderFlag, AnonymHistologyReport
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"VideoFile",
|
|
7
|
+
"Frame",
|
|
8
|
+
"RawPdfFile",
|
|
9
|
+
"DocumentType",
|
|
10
|
+
"AnonymExaminationReport",
|
|
11
|
+
"AnonymHistologyReport",
|
|
12
|
+
'ReportReaderConfig',
|
|
13
|
+
'ReportReaderFlag',
|
|
14
|
+
'VideoMetadata',
|
|
15
|
+
'VideoProcessingHistory',
|
|
16
|
+
]
|