endoreg-db 0.8.8.0__py3-none-any.whl → 0.8.9.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/data/__init__.py +22 -8
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +0 -1
- endoreg_db/data/examination/examinations/data.yaml +114 -14
- endoreg_db/data/examination/time-type/data.yaml +0 -3
- endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/{colonoscopy_bowel_preparation.yaml → 02_colonoscopy_baseline.yaml} +35 -20
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
- endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
- endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
- endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml → finding_classification_choice/02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_location.yaml → finding_classification_choice/02_colonoscopy_location.yaml} +23 -4
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/{_examples/finding_classification_choice/colon_lesion_paris.yaml → finding_classification_choice/02_colonoscopy_polyp_morphology.yaml} +26 -8
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_type/data.yaml +8 -12
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +0 -2
- endoreg_db/data/requirement_set/90_coloreg.yaml +20 -8
- endoreg_db/exceptions.py +0 -1
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +124 -52
- endoreg_db/helpers/default_objects.py +116 -81
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +43 -0
- endoreg_db/import_files/context/validate_directories.py +56 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +76 -0
- endoreg_db/import_files/file_storage/create_video_file.py +75 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
- endoreg_db/import_files/file_storage/state_management.py +496 -0
- endoreg_db/import_files/file_storage/storage.py +36 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
- endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
- endoreg_db/import_files/report_import_service.py +141 -0
- endoreg_db/import_files/video_import_service.py +150 -0
- endoreg_db/management/commands/import_report.py +130 -65
- endoreg_db/management/commands/import_video_with_classification.py +1 -1
- endoreg_db/management/commands/load_ai_model_data.py +5 -5
- endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
- endoreg_db/management/commands/load_base_db_data.py +5 -134
- endoreg_db/management/commands/load_contraindication_data.py +14 -16
- endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
- endoreg_db/management/commands/load_disease_classification_data.py +15 -18
- endoreg_db/management/commands/load_disease_data.py +25 -28
- endoreg_db/management/commands/load_endoscope_data.py +20 -27
- endoreg_db/management/commands/load_event_data.py +14 -16
- endoreg_db/management/commands/load_examination_data.py +31 -44
- endoreg_db/management/commands/load_examination_indication_data.py +20 -21
- endoreg_db/management/commands/load_finding_data.py +52 -80
- endoreg_db/management/commands/load_information_source.py +21 -23
- endoreg_db/management/commands/load_lab_value_data.py +17 -26
- endoreg_db/management/commands/load_medication_data.py +13 -12
- endoreg_db/management/commands/load_organ_data.py +15 -19
- endoreg_db/management/commands/load_pdf_type_data.py +19 -18
- endoreg_db/management/commands/load_profession_data.py +14 -17
- endoreg_db/management/commands/load_qualification_data.py +20 -23
- endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
- endoreg_db/management/commands/load_requirement_data.py +14 -20
- endoreg_db/management/commands/load_risk_data.py +7 -6
- endoreg_db/management/commands/load_shift_data.py +20 -23
- endoreg_db/management/commands/load_tag_data.py +8 -11
- endoreg_db/management/commands/load_unit_data.py +17 -19
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +1360 -1812
- endoreg_db/models/administration/person/patient/patient.py +72 -46
- endoreg_db/models/label/__init__.py +2 -2
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +18 -26
- endoreg_db/models/label/label_video_segment/label_video_segment.py +23 -1
- endoreg_db/models/media/pdf/raw_pdf.py +136 -64
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +34 -10
- endoreg_db/models/media/processing_history/__init__.py +5 -0
- endoreg_db/models/media/processing_history/processing_history.py +96 -0
- endoreg_db/models/media/video/create_from_file.py +101 -31
- endoreg_db/models/media/video/video_file.py +125 -105
- endoreg_db/models/media/video/video_file_io.py +31 -26
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/examination/examination.py +28 -8
- endoreg_db/models/medical/examination/examination_indication.py +13 -79
- endoreg_db/models/medical/examination/examination_time.py +8 -3
- endoreg_db/models/medical/finding/finding.py +5 -12
- endoreg_db/models/medical/finding/finding_classification.py +18 -37
- endoreg_db/models/medical/finding/finding_intervention.py +7 -9
- endoreg_db/models/medical/hardware/endoscope.py +6 -0
- endoreg_db/models/medical/patient/medication_examples.py +5 -1
- endoreg_db/models/medical/patient/patient_finding.py +1 -1
- endoreg_db/models/metadata/pdf_meta.py +22 -10
- endoreg_db/models/metadata/sensitive_meta.py +3 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +200 -124
- endoreg_db/models/other/information_source.py +27 -6
- endoreg_db/models/report/__init__.py +0 -0
- endoreg_db/models/report/images.py +0 -0
- endoreg_db/models/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +59 -399
- endoreg_db/models/requirement/requirement_operator.py +86 -98
- endoreg_db/models/state/audit_ledger.py +4 -5
- endoreg_db/models/state/raw_pdf.py +69 -30
- endoreg_db/models/state/video.py +65 -49
- endoreg_db/models/upload_job.py +33 -9
- endoreg_db/models/utils.py +27 -23
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
- endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
- endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +63 -26
- endoreg_db/services/lookup_service.py +28 -28
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1480
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1165
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +0 -14
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +21 -24
- endoreg_db/utils/dataloader.py +87 -57
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +217 -52
- endoreg_db/views/__init__.py +85 -173
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +8 -7
- endoreg_db/views/anonymization/overview.py +97 -68
- endoreg_db/views/anonymization/validate.py +25 -21
- endoreg_db/views/media/__init__.py +5 -20
- endoreg_db/views/media/pdf_media.py +109 -65
- endoreg_db/views/media/sensitive_metadata.py +163 -148
- endoreg_db/views/meta/__init__.py +0 -8
- endoreg_db/views/misc/__init__.py +1 -7
- endoreg_db/views/misc/upload_views.py +94 -93
- endoreg_db/views/report/__init__.py +7 -0
- endoreg_db/views/{pdf → report}/reimport.py +45 -24
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +40 -32
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/video/__init__.py +23 -22
- endoreg_db/views/video/correction.py +201 -172
- endoreg_db/views/video/reimport.py +1 -1
- endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +75 -37
- endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
- endoreg_db/views/video/video_stream.py +7 -8
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/METADATA +2 -2
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/RECORD +217 -335
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/WHEEL +1 -1
- endoreg_db/data/_examples/disease.yaml +0 -55
- endoreg_db/data/_examples/disease_classification.yaml +0 -13
- endoreg_db/data/_examples/disease_classification_choice.yaml +0 -62
- endoreg_db/data/_examples/event.yaml +0 -64
- endoreg_db/data/_examples/examination.yaml +0 -72
- endoreg_db/data/_examples/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/_examples/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/_examples/finding/complication.yaml +0 -16
- endoreg_db/data/_examples/finding/data.yaml +0 -105
- endoreg_db/data/_examples/finding/examination_setting.yaml +0 -16
- endoreg_db/data/_examples/finding/medication_related.yaml +0 -18
- endoreg_db/data/_examples/finding/outcome.yaml +0 -12
- endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +0 -68
- endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +0 -68
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +0 -80
- endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/_examples/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/_examples/finding_classification/histology_colo.yaml +0 -51
- endoreg_db/data/_examples/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/_examples/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/_examples/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +0 -78
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/histology.yaml +0 -24
- endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +0 -20
- endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +0 -11
- endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +0 -48
- endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +0 -15
- endoreg_db/data/_examples/finding_type/data.yaml +0 -43
- endoreg_db/data/_examples/requirement/age.yaml +0 -26
- endoreg_db/data/_examples/requirement/gender.yaml +0 -25
- endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +0 -48
- endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +0 -57
- endoreg_db/data/_examples/requirement_set/endoscopy_bleeding_risk.yaml +0 -52
- endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
- endoreg_db/data/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/finding/complication.yaml +0 -16
- endoreg_db/data/finding/data.yaml +0 -105
- endoreg_db/data/finding/examination_setting.yaml +0 -16
- endoreg_db/data/finding/medication_related.yaml +0 -18
- endoreg_db/data/finding/outcome.yaml +0 -12
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -38
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -49
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/finding_classification/histology_colo.yaml +0 -43
- endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +0 -57
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +0 -229
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +0 -19
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
- endoreg_db/data/requirement/age.yaml +0 -26
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +0 -45
- endoreg_db/data/requirement/disease_cardiovascular.yaml +0 -79
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +0 -41
- endoreg_db/data/requirement/disease_hepatology.yaml +0 -12
- endoreg_db/data/requirement/disease_misc.yaml +0 -12
- endoreg_db/data/requirement/disease_renal.yaml +0 -96
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +0 -59
- endoreg_db/data/requirement/event_cardiology.yaml +0 -251
- endoreg_db/data/requirement/event_requirements.yaml +0 -145
- endoreg_db/data/requirement/finding_colon_polyp.yaml +0 -50
- endoreg_db/data/requirement/gender.yaml +0 -25
- endoreg_db/data/requirement/lab_value.yaml +0 -441
- endoreg_db/data/requirement/medication.yaml +0 -93
- endoreg_db/data/requirement_operator/age.yaml +0 -13
- endoreg_db/data/requirement_operator/lab_operators.yaml +0 -129
- endoreg_db/data/requirement_operator/model_operators.yaml +0 -96
- endoreg_db/management/commands/init_default_ai_model.py +0 -112
- endoreg_db/management/commands/reset_celery_schedule.py +0 -9
- endoreg_db/management/commands/validate_video.py +0 -204
- endoreg_db/migrations/0002_requirementset_depends_on.py +0 -18
- endoreg_db/migrations/_old/0001_initial.py +0 -1857
- endoreg_db/migrations/_old/0002_add_video_correction_models.py +0 -52
- endoreg_db/migrations/_old/0003_add_center_display_name.py +0 -30
- endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +0 -68
- endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +0 -77
- endoreg_db/migrations/_old/0005_merge_20251111_1003.py +0 -14
- endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +0 -68
- endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +0 -89
- endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +0 -27
- endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +0 -21
- endoreg_db/renames.yml +0 -8
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
- endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
- endoreg_db/serializers/_old/video.py +0 -71
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
- endoreg_db/serializers/meta/report_meta.py +0 -53
- endoreg_db/serializers/report/__init__.py +0 -9
- endoreg_db/serializers/report/mixins.py +0 -45
- endoreg_db/serializers/report/report.py +0 -105
- endoreg_db/serializers/report/report_list.py +0 -22
- endoreg_db/serializers/report/secure_file_url.py +0 -26
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -370
- endoreg_db/urls/files.py +0 -6
- endoreg_db/urls/label_video_segment_validate.py +0 -33
- endoreg_db/urls/label_video_segments.py +0 -46
- endoreg_db/views/label/__init__.py +0 -5
- endoreg_db/views/label/label.py +0 -15
- endoreg_db/views/label_video_segment/__init__.py +0 -16
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
- endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
- endoreg_db/views/label_video_segment/validate.py +0 -226
- endoreg_db/views/media/segments.py +0 -71
- endoreg_db/views/meta/available_files_list.py +0 -146
- endoreg_db/views/meta/report_meta.py +0 -53
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -85
- endoreg_db/views/misc/secure_file_serving_view.py +0 -80
- endoreg_db/views/misc/secure_file_url_view.py +0 -84
- endoreg_db/views/misc/secure_url_validate.py +0 -79
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
- endoreg_db/views/patient_finding_location/__init__.py +0 -5
- endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
- endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
- endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
- endoreg_db/views/pdf/__init__.py +0 -8
- endoreg_db/views/video/segmentation.py +0 -274
- endoreg_db/views/video/task_status.py +0 -49
- endoreg_db/views/video/timeline.py +0 -46
- endoreg_db/views/video/video_analyze.py +0 -52
- /endoreg_db/data/requirement/{colon_polyp_intervention.yaml → old/colon_polyp_intervention.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/colonoscopy_baseline_austria.yaml +0 -0
- /endoreg_db/data/requirement/{coloreg_colon_polyp.yaml → old/coloreg_colon_polyp.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_cardiovascular.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_classification_choice_cardiovascular.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_hepatology.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_misc.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_renal.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/endoscopy_bleeding_risk.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/event_cardiology.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/event_requirements.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/finding_colon_polyp.yaml +0 -0
- /endoreg_db/{urls/sensitive_meta.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/lab_value.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/medication.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/age.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/lab_operators.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/model_operators.yaml +0 -0
- /endoreg_db/{views/pdf/pdf_stream_views.py → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{model_evaluators.py → _old/model_evaluators.py} +0 -0
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import shutil
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Optional
|
|
6
|
-
|
|
7
|
-
from django.db import transaction
|
|
8
|
-
|
|
9
|
-
from endoreg_db.exceptions import InsufficientStorageError
|
|
10
|
-
from endoreg_db.models import AnonymizationTask, VideoFile
|
|
11
|
-
|
|
12
|
-
# from endoreg_db.models.media.video.create_from_file import check_storage_capacity
|
|
13
|
-
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class StorageAwareVideoProcessor:
|
|
18
|
-
"""
|
|
19
|
-
Enhanced video processor with built-in storage management and automatic cleanup.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
def __init__(self, auto_cleanup: bool = True, min_free_space_gb: float = 10.0):
|
|
23
|
-
self.auto_cleanup = auto_cleanup
|
|
24
|
-
self.min_free_space_gb = min_free_space_gb
|
|
25
|
-
|
|
26
|
-
def check_and_ensure_storage(self, required_space_estimate: int = None) -> bool:
|
|
27
|
-
"""
|
|
28
|
-
Check storage capacity and perform cleanup if needed.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
required_space_estimate: Estimated space needed in bytes
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
True if enough space is available, False otherwise
|
|
35
|
-
|
|
36
|
-
Raises:
|
|
37
|
-
InsufficientStorageError: If space cannot be freed
|
|
38
|
-
"""
|
|
39
|
-
try:
|
|
40
|
-
# Get current storage stats
|
|
41
|
-
total, used, free = shutil.disk_usage("/")
|
|
42
|
-
free_gb = free / (1024**3)
|
|
43
|
-
usage_percent = (used / total) * 100
|
|
44
|
-
|
|
45
|
-
logger.info(
|
|
46
|
-
f"Storage check: {free_gb:.1f}GB free ({usage_percent:.1f}% used)"
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
# Check if we need emergency cleanup
|
|
50
|
-
needs_cleanup = (
|
|
51
|
-
usage_percent >= 95.0
|
|
52
|
-
or free_gb < self.min_free_space_gb
|
|
53
|
-
or (required_space_estimate and free < required_space_estimate * 1.2)
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
if needs_cleanup and self.auto_cleanup:
|
|
57
|
-
logger.warning(
|
|
58
|
-
f"Storage critically low ({usage_percent:.1f}%), performing automatic cleanup"
|
|
59
|
-
)
|
|
60
|
-
self._perform_emergency_cleanup()
|
|
61
|
-
|
|
62
|
-
# Re-check after cleanup
|
|
63
|
-
total, used, free = shutil.disk_usage("/")
|
|
64
|
-
free_gb = free / (1024**3)
|
|
65
|
-
usage_percent = (used / total) * 100
|
|
66
|
-
|
|
67
|
-
if usage_percent >= 98.0:
|
|
68
|
-
raise InsufficientStorageError(
|
|
69
|
-
f"Storage critically low even after cleanup: {usage_percent:.1f}% used, "
|
|
70
|
-
f"only {free_gb:.1f}GB free",
|
|
71
|
-
required_space=required_space_estimate
|
|
72
|
-
or int(self.min_free_space_gb * 1024**3),
|
|
73
|
-
available_space=free,
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
return True
|
|
77
|
-
|
|
78
|
-
except Exception as e:
|
|
79
|
-
logger.error(f"Storage check failed: {e}")
|
|
80
|
-
raise
|
|
81
|
-
|
|
82
|
-
def _perform_emergency_cleanup(self) -> int:
|
|
83
|
-
"""
|
|
84
|
-
Perform emergency storage cleanup.
|
|
85
|
-
|
|
86
|
-
Returns:
|
|
87
|
-
Bytes freed
|
|
88
|
-
"""
|
|
89
|
-
total_freed = 0
|
|
90
|
-
|
|
91
|
-
try:
|
|
92
|
-
# 1. Clean up extracted frames for completed videos
|
|
93
|
-
frames_freed = self._cleanup_completed_video_frames()
|
|
94
|
-
total_freed += frames_freed
|
|
95
|
-
|
|
96
|
-
# 2. Clean up upload cache older than 1 day
|
|
97
|
-
uploads_freed = self._cleanup_old_uploads(max_age_hours=24)
|
|
98
|
-
total_freed += uploads_freed
|
|
99
|
-
|
|
100
|
-
# 3. Clean up large log files
|
|
101
|
-
logs_freed = self._cleanup_large_logs()
|
|
102
|
-
total_freed += logs_freed
|
|
103
|
-
|
|
104
|
-
# 4. Clean up temporary files
|
|
105
|
-
temp_freed = self._cleanup_temp_files()
|
|
106
|
-
total_freed += temp_freed
|
|
107
|
-
|
|
108
|
-
logger.info(
|
|
109
|
-
f"Emergency cleanup completed: {total_freed / (1024**3):.2f}GB freed"
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
except Exception as e:
|
|
113
|
-
logger.error(f"Emergency cleanup failed: {e}")
|
|
114
|
-
|
|
115
|
-
return total_freed
|
|
116
|
-
|
|
117
|
-
def _cleanup_completed_video_frames(self) -> int:
|
|
118
|
-
"""Clean up frames for videos that have completed processing."""
|
|
119
|
-
total_freed = 0
|
|
120
|
-
|
|
121
|
-
try:
|
|
122
|
-
from django.conf import settings
|
|
123
|
-
|
|
124
|
-
frames_dir = Path(settings.BASE_DIR).parent / "storage" / "frames"
|
|
125
|
-
|
|
126
|
-
if not frames_dir.exists():
|
|
127
|
-
return 0
|
|
128
|
-
|
|
129
|
-
# Find videos with completed anonymization
|
|
130
|
-
completed_videos = VideoFile.objects.filter(
|
|
131
|
-
anonymization_tasks__status="done_processing_anonymization"
|
|
132
|
-
).distinct()
|
|
133
|
-
|
|
134
|
-
for video in completed_videos:
|
|
135
|
-
# Find frame directories for this video
|
|
136
|
-
video_frame_dirs = list(frames_dir.glob(f"*{video.uuid}*"))
|
|
137
|
-
|
|
138
|
-
for frame_dir in video_frame_dirs:
|
|
139
|
-
if frame_dir.is_dir():
|
|
140
|
-
try:
|
|
141
|
-
# Calculate directory size
|
|
142
|
-
dir_size = sum(
|
|
143
|
-
f.stat().st_size
|
|
144
|
-
for f in frame_dir.rglob("*")
|
|
145
|
-
if f.is_file()
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
# Remove the directory
|
|
149
|
-
shutil.rmtree(frame_dir, ignore_errors=True)
|
|
150
|
-
total_freed += dir_size
|
|
151
|
-
|
|
152
|
-
logger.info(
|
|
153
|
-
f"Cleaned frames for {video.uuid}: {dir_size / (1024**2):.1f}MB"
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
except Exception as e:
|
|
157
|
-
logger.warning(
|
|
158
|
-
f"Failed to clean frames for {video.uuid}: {e}"
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
except Exception as e:
|
|
162
|
-
logger.error(f"Frame cleanup failed: {e}")
|
|
163
|
-
|
|
164
|
-
return total_freed
|
|
165
|
-
|
|
166
|
-
def _cleanup_old_uploads(self, max_age_hours: int = 24) -> int:
|
|
167
|
-
"""Clean up old upload cache files."""
|
|
168
|
-
total_freed = 0
|
|
169
|
-
|
|
170
|
-
try:
|
|
171
|
-
from django.conf import settings
|
|
172
|
-
|
|
173
|
-
uploads_dir = Path(settings.BASE_DIR).parent / "storage" / "uploads"
|
|
174
|
-
|
|
175
|
-
if not uploads_dir.exists():
|
|
176
|
-
return 0
|
|
177
|
-
|
|
178
|
-
cutoff_time = datetime.now().timestamp() - (max_age_hours * 3600)
|
|
179
|
-
|
|
180
|
-
for file_path in uploads_dir.rglob("*"):
|
|
181
|
-
if file_path.is_file():
|
|
182
|
-
try:
|
|
183
|
-
if file_path.stat().st_mtime < cutoff_time:
|
|
184
|
-
file_size = file_path.stat().st_size
|
|
185
|
-
file_path.unlink()
|
|
186
|
-
total_freed += file_size
|
|
187
|
-
|
|
188
|
-
except Exception as e:
|
|
189
|
-
logger.warning(f"Failed to clean upload file {file_path}: {e}")
|
|
190
|
-
|
|
191
|
-
except Exception as e:
|
|
192
|
-
logger.error(f"Upload cleanup failed: {e}")
|
|
193
|
-
|
|
194
|
-
return total_freed
|
|
195
|
-
|
|
196
|
-
def _cleanup_large_logs(self, max_size_mb: int = 50) -> int:
|
|
197
|
-
"""Clean up large log files by truncating them."""
|
|
198
|
-
total_freed = 0
|
|
199
|
-
|
|
200
|
-
try:
|
|
201
|
-
from django.conf import settings
|
|
202
|
-
|
|
203
|
-
project_root = Path(settings.BASE_DIR).parent
|
|
204
|
-
max_size_bytes = max_size_mb * 1024 * 1024
|
|
205
|
-
|
|
206
|
-
for log_file in project_root.rglob("*.log"):
|
|
207
|
-
try:
|
|
208
|
-
if log_file.stat().st_size > max_size_bytes:
|
|
209
|
-
original_size = log_file.stat().st_size
|
|
210
|
-
|
|
211
|
-
# Truncate the log file
|
|
212
|
-
with open(log_file, "w") as f:
|
|
213
|
-
f.write(
|
|
214
|
-
f"# Log truncated at {datetime.now()} due to size limit\n"
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
total_freed += original_size
|
|
218
|
-
logger.info(
|
|
219
|
-
f"Truncated log {log_file}: {original_size / (1024**2):.1f}MB"
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
except Exception as e:
|
|
223
|
-
logger.warning(f"Failed to truncate log {log_file}: {e}")
|
|
224
|
-
|
|
225
|
-
except Exception as e:
|
|
226
|
-
logger.error(f"Log cleanup failed: {e}")
|
|
227
|
-
|
|
228
|
-
return total_freed
|
|
229
|
-
|
|
230
|
-
def _cleanup_temp_files(self) -> int:
|
|
231
|
-
"""Clean up temporary files."""
|
|
232
|
-
total_freed = 0
|
|
233
|
-
|
|
234
|
-
try:
|
|
235
|
-
temp_patterns = [
|
|
236
|
-
"/tmp/tmp*",
|
|
237
|
-
"/tmp/temp*",
|
|
238
|
-
"/tmp/django*",
|
|
239
|
-
"/tmp/ffmpeg*",
|
|
240
|
-
]
|
|
241
|
-
|
|
242
|
-
for pattern in temp_patterns:
|
|
243
|
-
import glob
|
|
244
|
-
|
|
245
|
-
for temp_file in glob.glob(pattern):
|
|
246
|
-
try:
|
|
247
|
-
temp_path = Path(temp_file)
|
|
248
|
-
if temp_path.is_file():
|
|
249
|
-
file_size = temp_path.stat().st_size
|
|
250
|
-
temp_path.unlink()
|
|
251
|
-
total_freed += file_size
|
|
252
|
-
|
|
253
|
-
except Exception as e:
|
|
254
|
-
logger.warning(f"Failed to clean temp file {temp_file}: {e}")
|
|
255
|
-
|
|
256
|
-
except Exception as e:
|
|
257
|
-
logger.error(f"Temp file cleanup failed: {e}")
|
|
258
|
-
|
|
259
|
-
return total_freed
|
|
260
|
-
|
|
261
|
-
def process_video_with_storage_management(
|
|
262
|
-
self,
|
|
263
|
-
video_file: VideoFile,
|
|
264
|
-
cleanup_frames_after: bool = True,
|
|
265
|
-
progress_callback: Optional[callable] = None,
|
|
266
|
-
) -> bool:
|
|
267
|
-
"""
|
|
268
|
-
Process a video with automatic storage management.
|
|
269
|
-
|
|
270
|
-
Args:
|
|
271
|
-
video_file: VideoFile instance to process
|
|
272
|
-
cleanup_frames_after: Whether to clean up frames after processing
|
|
273
|
-
progress_callback: Optional progress callback function
|
|
274
|
-
|
|
275
|
-
Returns:
|
|
276
|
-
True if processing succeeded, False otherwise
|
|
277
|
-
"""
|
|
278
|
-
try:
|
|
279
|
-
# Estimate required space (rough calculation)
|
|
280
|
-
video_size = 0
|
|
281
|
-
if video_file.raw_file and hasattr(video_file.raw_file, "size"):
|
|
282
|
-
video_size = video_file.raw_file.size
|
|
283
|
-
|
|
284
|
-
# Estimate: frames ~= 3x video size, processing ~= 2x video size
|
|
285
|
-
estimated_space_needed = video_size * 5
|
|
286
|
-
|
|
287
|
-
# Check storage before starting
|
|
288
|
-
self.check_and_ensure_storage(estimated_space_needed)
|
|
289
|
-
|
|
290
|
-
# Update task status
|
|
291
|
-
task = self._get_or_create_task(video_file)
|
|
292
|
-
task.start_processing()
|
|
293
|
-
|
|
294
|
-
if progress_callback:
|
|
295
|
-
progress_callback(10, "Starting video processing...")
|
|
296
|
-
|
|
297
|
-
# Run the actual video processing pipeline
|
|
298
|
-
success = video_file.pipe_1(
|
|
299
|
-
model_name="image_multilabel_classification_colonoscopy_default",
|
|
300
|
-
delete_frames_after=cleanup_frames_after,
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
if success:
|
|
304
|
-
if progress_callback:
|
|
305
|
-
progress_callback(90, "Processing completed, cleaning up...")
|
|
306
|
-
|
|
307
|
-
# Mark as completed
|
|
308
|
-
task.mark_completed("Video processing completed successfully")
|
|
309
|
-
|
|
310
|
-
# Additional cleanup if requested
|
|
311
|
-
if cleanup_frames_after:
|
|
312
|
-
self._cleanup_video_frames(video_file)
|
|
313
|
-
|
|
314
|
-
if progress_callback:
|
|
315
|
-
progress_callback(100, "Processing completed successfully")
|
|
316
|
-
|
|
317
|
-
logger.info(
|
|
318
|
-
f"Video processing completed successfully: {video_file.uuid}"
|
|
319
|
-
)
|
|
320
|
-
return True
|
|
321
|
-
|
|
322
|
-
task.mark_failed("Video processing pipeline failed")
|
|
323
|
-
logger.error(f"Video processing failed: {video_file.uuid}")
|
|
324
|
-
return False
|
|
325
|
-
|
|
326
|
-
except InsufficientStorageError as e:
|
|
327
|
-
logger.error(f"Storage error during video processing: {e}")
|
|
328
|
-
task = self._get_or_create_task(video_file)
|
|
329
|
-
task.mark_failed(f"Insufficient storage: {e}")
|
|
330
|
-
return False
|
|
331
|
-
|
|
332
|
-
except Exception as e:
|
|
333
|
-
logger.error(f"Video processing failed: {e}")
|
|
334
|
-
task = self._get_or_create_task(video_file)
|
|
335
|
-
task.mark_failed(f"Processing error: {e}")
|
|
336
|
-
return False
|
|
337
|
-
|
|
338
|
-
def _get_or_create_task(self, video_file: VideoFile) -> AnonymizationTask:
|
|
339
|
-
"""Get or create an anonymization task for the video."""
|
|
340
|
-
task, created = AnonymizationTask.objects.get_or_create(
|
|
341
|
-
video_file=video_file,
|
|
342
|
-
defaults={
|
|
343
|
-
"status": "not_started",
|
|
344
|
-
"progress": 0,
|
|
345
|
-
"message": "Initializing...",
|
|
346
|
-
},
|
|
347
|
-
)
|
|
348
|
-
return task
|
|
349
|
-
|
|
350
|
-
def _cleanup_video_frames(self, video_file: VideoFile):
|
|
351
|
-
"""Clean up frames for a specific video."""
|
|
352
|
-
try:
|
|
353
|
-
from django.conf import settings
|
|
354
|
-
|
|
355
|
-
frames_dir = Path(settings.BASE_DIR).parent / "storage" / "frames"
|
|
356
|
-
|
|
357
|
-
# Find frame directories for this video
|
|
358
|
-
video_frame_dirs = list(frames_dir.glob(f"*{video_file.uuid}*"))
|
|
359
|
-
|
|
360
|
-
for frame_dir in video_frame_dirs:
|
|
361
|
-
if frame_dir.is_dir():
|
|
362
|
-
shutil.rmtree(frame_dir, ignore_errors=True)
|
|
363
|
-
logger.info(f"Cleaned up frames for video {video_file.uuid}")
|
|
364
|
-
|
|
365
|
-
except Exception as e:
|
|
366
|
-
logger.warning(f"Failed to clean up frames for {video_file.uuid}: {e}")
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
# Global instance for easy access
|
|
370
|
-
storage_aware_processor = StorageAwareVideoProcessor()
|
endoreg_db/urls/files.py
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from django.urls import path
|
|
2
|
-
|
|
3
|
-
from endoreg_db.views.label_video_segment.validate import (
|
|
4
|
-
LabelVideoSegmentValidateView,
|
|
5
|
-
BulkSegmentValidateView,
|
|
6
|
-
VideoSegmentValidationCompleteView
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
url_patterns = [
|
|
10
|
-
# Einzelne Segment-Validierung
|
|
11
|
-
# POST /api/label-video-segment/<int:segment_id>/validate/
|
|
12
|
-
path(
|
|
13
|
-
'label-video-segment/<int:segment_id>/validate/',
|
|
14
|
-
LabelVideoSegmentValidateView.as_view(),
|
|
15
|
-
name='label_video_segment_validate'
|
|
16
|
-
),
|
|
17
|
-
|
|
18
|
-
# Bulk-Validierung mehrerer Segmente
|
|
19
|
-
# POST /api/label-video-segments/validate-bulk/
|
|
20
|
-
path(
|
|
21
|
-
'label-video-segments/validate-bulk/',
|
|
22
|
-
BulkSegmentValidateView.as_view(),
|
|
23
|
-
name='label_video_segments_validate_bulk'
|
|
24
|
-
),
|
|
25
|
-
|
|
26
|
-
# Alle Segmente eines Videos als validiert markieren
|
|
27
|
-
# POST /api/videos/<int:video_id>/segments/validate-complete/
|
|
28
|
-
path(
|
|
29
|
-
'videos/<int:video_id>/segments/validate-complete/',
|
|
30
|
-
VideoSegmentValidationCompleteView.as_view(),
|
|
31
|
-
name='video_segments_validate_complete'
|
|
32
|
-
),
|
|
33
|
-
]
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
from django.urls import path
|
|
2
|
-
from endoreg_db.views import (
|
|
3
|
-
create_video_segment_annotation,
|
|
4
|
-
update_label_video_segment,
|
|
5
|
-
SensitiveMetaDetailView,
|
|
6
|
-
video_segments_view,
|
|
7
|
-
video_segment_detail_view,
|
|
8
|
-
get_lvs_by_name_and_video_id
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
url_patterns = [
|
|
14
|
-
path(
|
|
15
|
-
"lvs/by-label-name/<str:label_name>/by-video-id/<int:video_id>/",
|
|
16
|
-
get_lvs_by_name_and_video_id,
|
|
17
|
-
name='get_lvs_by_name_and_video_id'
|
|
18
|
-
),
|
|
19
|
-
path(
|
|
20
|
-
'annotations/',
|
|
21
|
-
create_video_segment_annotation,
|
|
22
|
-
name='create_annotation'
|
|
23
|
-
),
|
|
24
|
-
path(
|
|
25
|
-
'annotations/<int:annotation_id>/',
|
|
26
|
-
update_label_video_segment,
|
|
27
|
-
name='update_annotation'
|
|
28
|
-
),
|
|
29
|
-
path(
|
|
30
|
-
'save-anonymization-annotation-video/<int:annotation_id>/',
|
|
31
|
-
SensitiveMetaDetailView.as_view(),
|
|
32
|
-
name='save_anonymization_annotation_video'
|
|
33
|
-
),
|
|
34
|
-
# Label Video Segment API endpoints
|
|
35
|
-
path(
|
|
36
|
-
'video-segments/',
|
|
37
|
-
video_segments_view,
|
|
38
|
-
name='video_segments'
|
|
39
|
-
),
|
|
40
|
-
path(
|
|
41
|
-
'video-segments/<int:segment_id>/',
|
|
42
|
-
video_segment_detail_view,
|
|
43
|
-
name='video_segment_detail'
|
|
44
|
-
),
|
|
45
|
-
|
|
46
|
-
]
|
endoreg_db/views/label/label.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from rest_framework.viewsets import ReadOnlyModelViewSet
|
|
3
|
-
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
|
4
|
-
from endoreg_db.models import (
|
|
5
|
-
Label,
|
|
6
|
-
)
|
|
7
|
-
from endoreg_db.serializers.label import LabelSerializer
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class LabelViewSet(ReadOnlyModelViewSet):
|
|
12
|
-
queryset = Label.objects.all()
|
|
13
|
-
serializer_class = LabelSerializer
|
|
14
|
-
permission_classes = [IsAuthenticatedOrReadOnly]
|
|
15
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from .create_lvs_from_annotation import create_video_segment_annotation
|
|
2
|
-
from .label_video_segment_by_label import video_segments_by_label_id_view, video_segments_by_label_name_view
|
|
3
|
-
from .label_video_segment_detail import video_segment_detail_view
|
|
4
|
-
from .label_video_segment import video_segments_view
|
|
5
|
-
from .update_lvs_from_annotation import update_label_video_segment
|
|
6
|
-
from .get_lvs_by_name_and_video import get_lvs_by_name_and_video_id
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
'create_video_segment_annotation',
|
|
10
|
-
'video_segments_by_label_id_view',
|
|
11
|
-
'video_segments_by_label_name_view',
|
|
12
|
-
'video_segment_detail_view',
|
|
13
|
-
'video_segments_view',
|
|
14
|
-
'update_label_video_segment',
|
|
15
|
-
"get_lvs_by_name_and_video_id"
|
|
16
|
-
]
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import LabelVideoSegment
|
|
2
|
-
from endoreg_db.serializers.label_video_segment.label_video_segment_annotation import LabelVideoSegmentAnnotationSerializer
|
|
3
|
-
|
|
4
|
-
from django.db import transaction
|
|
5
|
-
from rest_framework import status
|
|
6
|
-
from rest_framework.decorators import api_view, permission_classes
|
|
7
|
-
from rest_framework.permissions import IsAuthenticated
|
|
8
|
-
from rest_framework.response import Response
|
|
9
|
-
|
|
10
|
-
import logging
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
@api_view(['POST'])
|
|
15
|
-
@permission_classes([IsAuthenticated])
|
|
16
|
-
def create_video_segment_annotation(request):
|
|
17
|
-
"""
|
|
18
|
-
Create a new annotation.
|
|
19
|
-
If annotation type is 'segment', creates a user-source LabelVideoSegment.
|
|
20
|
-
"""
|
|
21
|
-
logger.info(f"Creating annotation with data: {request.data}")
|
|
22
|
-
|
|
23
|
-
with transaction.atomic():
|
|
24
|
-
serializer = LabelVideoSegmentAnnotationSerializer(data=request.data)
|
|
25
|
-
if serializer.is_valid():
|
|
26
|
-
annotation = serializer.save()
|
|
27
|
-
|
|
28
|
-
# If the annotation type is 'segment', create a new LabelVideoSegment
|
|
29
|
-
if annotation.type == 'segment':
|
|
30
|
-
metadata = annotation.metadata or {}
|
|
31
|
-
#TODO @coderabbitai we should create a followup issue for @Hamzaukw so we adress this naming inconsistency in future
|
|
32
|
-
LabelVideoSegment.objects.create(
|
|
33
|
-
video_id=annotation.video_id,
|
|
34
|
-
start_frame=metadata.get('start_frame'),
|
|
35
|
-
end_frame=metadata.get('end_frame'),
|
|
36
|
-
label=metadata.get('label'),
|
|
37
|
-
source='user'
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
logger.info(f"Successfully created annotation {annotation.id}")
|
|
41
|
-
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
42
|
-
|
|
43
|
-
logger.error(f"Failed to create annotation with data: {request.data}, errors: {serializer.errors}")
|
|
44
|
-
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import Label, LabelVideoSegment, VideoFile
|
|
2
|
-
from endoreg_db.serializers.label_video_segment.label_video_segment import LabelVideoSegmentSerializer
|
|
3
|
-
|
|
4
|
-
from rest_framework import status
|
|
5
|
-
from rest_framework.decorators import api_view, permission_classes
|
|
6
|
-
from rest_framework.response import Response
|
|
7
|
-
|
|
8
|
-
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
9
|
-
import logging
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
@api_view(['GET'])
|
|
13
|
-
@permission_classes([EnvironmentAwarePermission])
|
|
14
|
-
def get_lvs_by_name_and_video_id(request, label_name, video_id):
|
|
15
|
-
"""
|
|
16
|
-
Handles creation and retrieval of labeled video segments.
|
|
17
|
-
GET lists all labeled video segments, filtered by video ID and label name.
|
|
18
|
-
Returns appropriate error responses for invalid input or missing referenced objects.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
# Check if label exists
|
|
22
|
-
try:
|
|
23
|
-
_label = Label.objects.get(name=label_name)
|
|
24
|
-
except Label.DoesNotExist:
|
|
25
|
-
logger.error(f"Label with name '{label_name}' does not exist.")
|
|
26
|
-
return Response(
|
|
27
|
-
{"error": f"Label with name '{label_name}' does not exist."},
|
|
28
|
-
status=status.HTTP_404_NOT_FOUND
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
# Check if video exists
|
|
32
|
-
try:
|
|
33
|
-
_video = VideoFile.objects.get(id=video_id)
|
|
34
|
-
except VideoFile.DoesNotExist:
|
|
35
|
-
logger.error(f"Video with ID '{video_id}' does not exist.")
|
|
36
|
-
return Response(
|
|
37
|
-
{"error": f"Video with ID '{video_id}' does not exist."},
|
|
38
|
-
status=status.HTTP_404_NOT_FOUND
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
# get all segments for the given video and label name
|
|
42
|
-
queryset = LabelVideoSegment.objects.filter(
|
|
43
|
-
video_file__id=video_id,
|
|
44
|
-
label__name=label_name
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
# Order by video and start time for consistent results
|
|
48
|
-
segments = queryset.order_by('video_file__id', 'start_frame_number')
|
|
49
|
-
serializer = LabelVideoSegmentSerializer(segments, many=True)
|
|
50
|
-
return Response(serializer.data)
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import Label, LabelVideoSegment, VideoFile
|
|
2
|
-
from endoreg_db.serializers.label_video_segment.label_video_segment import LabelVideoSegmentSerializer
|
|
3
|
-
|
|
4
|
-
from django.db import transaction
|
|
5
|
-
from rest_framework import status
|
|
6
|
-
from rest_framework.decorators import api_view, permission_classes
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
|
|
9
|
-
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
10
|
-
import logging
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
@api_view(['POST', 'GET'])
|
|
14
|
-
@permission_classes([EnvironmentAwarePermission])
|
|
15
|
-
def video_segments_view(request):
|
|
16
|
-
"""
|
|
17
|
-
Handles creation and retrieval of labeled video segments.
|
|
18
|
-
|
|
19
|
-
POST creates a new labeled video segment with validated data and returns the created segment. GET lists all labeled video segments, optionally filtered by video ID and/or label ID. Returns appropriate error responses for invalid input or missing referenced objects.
|
|
20
|
-
"""
|
|
21
|
-
if request.method == 'POST':
|
|
22
|
-
logger.info(f"Creating new video segment with data: {request.data}")
|
|
23
|
-
|
|
24
|
-
with transaction.atomic():
|
|
25
|
-
serializer = LabelVideoSegmentSerializer(data=request.data)
|
|
26
|
-
if serializer.is_valid():
|
|
27
|
-
try:
|
|
28
|
-
segment = serializer.save()
|
|
29
|
-
logger.info(f"Successfully created video segment {segment.pk}")
|
|
30
|
-
return Response(
|
|
31
|
-
LabelVideoSegmentSerializer(segment).data,
|
|
32
|
-
status=status.HTTP_201_CREATED
|
|
33
|
-
)
|
|
34
|
-
except Exception as e:
|
|
35
|
-
logger.error(f"Error creating video segment: {str(e)}")
|
|
36
|
-
return Response(
|
|
37
|
-
{'error': f'Failed to create segment: {str(e)}'},
|
|
38
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
39
|
-
)
|
|
40
|
-
else:
|
|
41
|
-
logger.warning(f"Invalid data for video segment creation: {serializer.errors}")
|
|
42
|
-
return Response(
|
|
43
|
-
{'error': 'Invalid data', 'details': serializer.errors},
|
|
44
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
elif request.method == 'GET':
|
|
48
|
-
# Optional filtering by video_id
|
|
49
|
-
video_id = request.GET.get('video_id')
|
|
50
|
-
label_id = request.GET.get('label_id')
|
|
51
|
-
|
|
52
|
-
queryset = LabelVideoSegment.objects.all()
|
|
53
|
-
|
|
54
|
-
if video_id:
|
|
55
|
-
try:
|
|
56
|
-
video = VideoFile.objects.get(id=video_id)
|
|
57
|
-
queryset = queryset.filter(video_file=video)
|
|
58
|
-
except VideoFile.DoesNotExist:
|
|
59
|
-
return Response(
|
|
60
|
-
{'error': f'Video with id {video_id} not found'},
|
|
61
|
-
status=status.HTTP_404_NOT_FOUND
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
if label_id:
|
|
65
|
-
try:
|
|
66
|
-
label = Label.objects.get(id=label_id)
|
|
67
|
-
queryset = queryset.filter(label=label)
|
|
68
|
-
except Label.DoesNotExist:
|
|
69
|
-
return Response(
|
|
70
|
-
{'error': f'Label with id {label_id} not found'},
|
|
71
|
-
status=status.HTTP_404_NOT_FOUND
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# Order by video and start time for consistent results
|
|
75
|
-
segments = queryset.order_by('video_file__id', 'start_frame_number')
|
|
76
|
-
serializer = LabelVideoSegmentSerializer(segments, many=True)
|
|
77
|
-
return Response(serializer.data)
|