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
endoreg_db/utils/dataloader.py
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from datetime import UTC, datetime
|
|
3
|
+
|
|
2
4
|
import yaml
|
|
3
5
|
from django.core.exceptions import ObjectDoesNotExist
|
|
4
6
|
from django.db import OperationalError, transaction
|
|
5
7
|
|
|
8
|
+
from endoreg_db.utils.paths import STORAGE_DIR
|
|
9
|
+
|
|
10
|
+
_WARNING_LOG_PATH = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_warning_log_path():
|
|
14
|
+
"""Return the path used for warning logs, creating it on first access."""
|
|
15
|
+
global _WARNING_LOG_PATH
|
|
16
|
+
if _WARNING_LOG_PATH is None:
|
|
17
|
+
log_dir = STORAGE_DIR / "logs"
|
|
18
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
19
|
+
timestamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
|
20
|
+
_WARNING_LOG_PATH = log_dir / f"dataloader_warnings_{timestamp}.log"
|
|
21
|
+
return _WARNING_LOG_PATH
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _record_warning(command, message, verbose, context):
|
|
25
|
+
"""Write a warning to stdout (when verbose) and append it to the log file."""
|
|
26
|
+
prefix = f"[{context}] " if context else ""
|
|
27
|
+
full_message = f"{prefix}{message}"
|
|
28
|
+
|
|
29
|
+
if verbose:
|
|
30
|
+
command.stdout.write(command.style.WARNING(full_message))
|
|
31
|
+
|
|
32
|
+
log_path = _get_warning_log_path()
|
|
33
|
+
with open(log_path, "a", encoding="utf-8") as log_file:
|
|
34
|
+
log_file.write(f"{datetime.now(UTC).isoformat()}Z {full_message}\n")
|
|
35
|
+
|
|
36
|
+
|
|
6
37
|
def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
7
38
|
"""
|
|
8
39
|
Load model data from YAML files.
|
|
@@ -15,6 +46,10 @@ def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
|
15
46
|
"""
|
|
16
47
|
if verbose:
|
|
17
48
|
command.stdout.write(f"Start loading {model_name}")
|
|
49
|
+
|
|
50
|
+
warning_log_path = _get_warning_log_path()
|
|
51
|
+
if verbose:
|
|
52
|
+
command.stdout.write(f"Warning log file: {warning_log_path}")
|
|
18
53
|
model = metadata["model"]
|
|
19
54
|
dir_path = metadata["dir"]
|
|
20
55
|
foreign_keys = metadata["foreign_keys"]
|
|
@@ -29,7 +64,14 @@ def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
|
29
64
|
yaml_data = yaml.safe_load(file)
|
|
30
65
|
|
|
31
66
|
load_data_with_foreign_keys(
|
|
32
|
-
command,
|
|
67
|
+
command,
|
|
68
|
+
model,
|
|
69
|
+
yaml_data,
|
|
70
|
+
foreign_keys,
|
|
71
|
+
foreign_key_models,
|
|
72
|
+
validators,
|
|
73
|
+
verbose,
|
|
74
|
+
log_context=model_name or model.__name__,
|
|
33
75
|
)
|
|
34
76
|
|
|
35
77
|
|
|
@@ -41,10 +83,11 @@ def load_data_with_foreign_keys(
|
|
|
41
83
|
foreign_key_models,
|
|
42
84
|
validators,
|
|
43
85
|
verbose,
|
|
86
|
+
log_context=None,
|
|
44
87
|
):
|
|
45
88
|
"""
|
|
46
89
|
Load YAML data into Django model instances with FK and M2M support.
|
|
47
|
-
|
|
90
|
+
|
|
48
91
|
Processes each YAML entry to create or update a model instance. For each entry, the
|
|
49
92
|
function extracts field data and uses the presence of a 'name' field to decide whether
|
|
50
93
|
to update an existing instance or create a new one. Foreign key fields listed in
|
|
@@ -52,7 +95,7 @@ def load_data_with_foreign_keys(
|
|
|
52
95
|
contains a list, it is treated as a many-to-many relationship and the corresponding
|
|
53
96
|
objects are set after the instance is saved. Missing or unresolved foreign keys trigger
|
|
54
97
|
warnings if verbose output is enabled.
|
|
55
|
-
|
|
98
|
+
|
|
56
99
|
Parameters:
|
|
57
100
|
model: The Django model class representing the data.
|
|
58
101
|
yaml_data: A list of dictionaries representing YAML entries.
|
|
@@ -62,7 +105,10 @@ def load_data_with_foreign_keys(
|
|
|
62
105
|
validator receives a shallow copy of the entry's field dictionary along with
|
|
63
106
|
the original entry and model for context.
|
|
64
107
|
verbose: If True, prints detailed output and warnings during processing.
|
|
108
|
+
log_context: Label that identifies the source dataset inside the warning log.
|
|
65
109
|
"""
|
|
110
|
+
context_label = log_context or getattr(model, "__name__", "dataloader")
|
|
111
|
+
|
|
66
112
|
for entry in yaml_data:
|
|
67
113
|
raw_fields = entry.get("fields", {})
|
|
68
114
|
|
|
@@ -72,30 +118,21 @@ def load_data_with_foreign_keys(
|
|
|
72
118
|
fields = dict(raw_fields)
|
|
73
119
|
name = fields.pop("name", None)
|
|
74
120
|
|
|
75
|
-
|
|
76
121
|
if getattr(model, "_meta", None) and model._meta.model_name == "requirement":
|
|
77
122
|
requirement_types = fields.get("requirement_types", [])
|
|
78
|
-
|
|
79
|
-
|
|
123
|
+
|
|
80
124
|
if not requirement_types:
|
|
81
|
-
raise ValueError(
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
if not operators:
|
|
85
|
-
raise ValueError(
|
|
86
|
-
f"Requirement '{name}' must define at least one operators entry."
|
|
87
|
-
)
|
|
88
|
-
|
|
125
|
+
raise ValueError(f"Requirement '{name}' must define at least one requirement_types entry.")
|
|
126
|
+
|
|
89
127
|
####################
|
|
90
|
-
#TODO REMOVE AFTER TRANSLATION SUPPORT IS ADDED
|
|
91
|
-
SKIP_NAMES=[
|
|
128
|
+
# TODO REMOVE AFTER TRANSLATION SUPPORT IS ADDED
|
|
129
|
+
SKIP_NAMES = [
|
|
92
130
|
"name_de", # German name, not used
|
|
93
131
|
"name_en", # English name, not used
|
|
94
132
|
"description_de", # German description
|
|
95
133
|
"description_en", # English description
|
|
96
134
|
]
|
|
97
135
|
|
|
98
|
-
|
|
99
136
|
# Remove fields that are not needed
|
|
100
137
|
for skip_name in SKIP_NAMES:
|
|
101
138
|
if skip_name in fields:
|
|
@@ -115,12 +152,12 @@ def load_data_with_foreign_keys(
|
|
|
115
152
|
|
|
116
153
|
# Ensure the foreign key exists
|
|
117
154
|
if target_keys is None:
|
|
118
|
-
|
|
119
|
-
command
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
155
|
+
_record_warning(
|
|
156
|
+
command,
|
|
157
|
+
f"Foreign key {fk_field} not found in fields",
|
|
158
|
+
verbose,
|
|
159
|
+
context_label,
|
|
160
|
+
)
|
|
124
161
|
continue # Skip if no foreign key provided
|
|
125
162
|
|
|
126
163
|
# Process many-to-many fields or foreign keys
|
|
@@ -130,20 +167,17 @@ def load_data_with_foreign_keys(
|
|
|
130
167
|
try:
|
|
131
168
|
obj = fk_model.objects.get_by_natural_key(key)
|
|
132
169
|
except ObjectDoesNotExist:
|
|
133
|
-
|
|
134
|
-
command
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
170
|
+
_record_warning(
|
|
171
|
+
command,
|
|
172
|
+
f"{fk_model.__name__} with key {key} not found",
|
|
173
|
+
verbose,
|
|
174
|
+
context_label,
|
|
175
|
+
)
|
|
139
176
|
continue
|
|
140
177
|
related_objects.append(obj)
|
|
141
178
|
m2m_relationships[fk_field] = related_objects
|
|
142
179
|
else: # Single foreign key relationship
|
|
143
|
-
if
|
|
144
|
-
model.__name__ == "ModelMeta"
|
|
145
|
-
and fk_field == "labelset"
|
|
146
|
-
):
|
|
180
|
+
if model.__name__ == "ModelMeta" and fk_field == "labelset":
|
|
147
181
|
labelset_version = fields.pop("labelset_version", None)
|
|
148
182
|
|
|
149
183
|
if isinstance(target_keys, (tuple, list)):
|
|
@@ -154,10 +188,12 @@ def load_data_with_foreign_keys(
|
|
|
154
188
|
labelset_name = target_keys
|
|
155
189
|
|
|
156
190
|
if not labelset_name:
|
|
157
|
-
|
|
158
|
-
command
|
|
159
|
-
|
|
160
|
-
|
|
191
|
+
_record_warning(
|
|
192
|
+
command,
|
|
193
|
+
"LabelSet name missing for ModelMeta entry",
|
|
194
|
+
verbose,
|
|
195
|
+
context_label,
|
|
196
|
+
)
|
|
161
197
|
continue
|
|
162
198
|
|
|
163
199
|
queryset = fk_model.objects.filter(name=labelset_name)
|
|
@@ -170,24 +206,24 @@ def load_data_with_foreign_keys(
|
|
|
170
206
|
|
|
171
207
|
obj = queryset.order_by("-version").first()
|
|
172
208
|
if obj is None:
|
|
173
|
-
|
|
174
|
-
command
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
209
|
+
_record_warning(
|
|
210
|
+
command,
|
|
211
|
+
f"LabelSet '{labelset_name}' (version={labelset_version}) not found",
|
|
212
|
+
verbose,
|
|
213
|
+
context_label,
|
|
214
|
+
)
|
|
179
215
|
continue
|
|
180
216
|
fields[fk_field] = obj
|
|
181
217
|
else:
|
|
182
218
|
try:
|
|
183
219
|
obj = fk_model.objects.get_by_natural_key(target_keys)
|
|
184
220
|
except ObjectDoesNotExist:
|
|
185
|
-
|
|
186
|
-
command
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
221
|
+
_record_warning(
|
|
222
|
+
command,
|
|
223
|
+
f"{fk_model.__name__} with key {target_keys} not found",
|
|
224
|
+
verbose,
|
|
225
|
+
context_label,
|
|
226
|
+
)
|
|
191
227
|
continue
|
|
192
228
|
fields[fk_field] = obj
|
|
193
229
|
|
|
@@ -229,9 +265,7 @@ def load_data_with_foreign_keys(
|
|
|
229
265
|
obj, created = _save_instance()
|
|
230
266
|
|
|
231
267
|
if created and verbose:
|
|
232
|
-
command.stdout.write(
|
|
233
|
-
command.style.SUCCESS(f"Created {model.__name__} {name}")
|
|
234
|
-
)
|
|
268
|
+
command.stdout.write(command.style.SUCCESS(f"Created {model.__name__} {name}"))
|
|
235
269
|
elif verbose:
|
|
236
270
|
pass
|
|
237
271
|
|
|
@@ -240,8 +274,4 @@ def load_data_with_foreign_keys(
|
|
|
240
274
|
if related_objs: # Only set if there are objects to set
|
|
241
275
|
getattr(obj, field_name).set(related_objs)
|
|
242
276
|
if verbose:
|
|
243
|
-
command.stdout.write(
|
|
244
|
-
command.style.SUCCESS(
|
|
245
|
-
f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"
|
|
246
|
-
)
|
|
247
|
-
)
|
|
277
|
+
command.stdout.write(command.style.SUCCESS(f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"))
|
endoreg_db/utils/paths.py
CHANGED
|
@@ -7,89 +7,153 @@ It provides a unified dictionary 'data_paths' for accessing all path objects.
|
|
|
7
7
|
|
|
8
8
|
from logging import getLogger
|
|
9
9
|
|
|
10
|
-
from sphinx.search import no
|
|
11
10
|
logger = getLogger(__name__)
|
|
12
11
|
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
from typing import Dict
|
|
15
12
|
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Dict, Union
|
|
15
|
+
|
|
16
16
|
# Alternative approach using env_path helper, deprecated since monorepo setup. Alright for single install, env is always preferred.
|
|
17
|
-
#from endoreg_db.config.env import env_path
|
|
17
|
+
# from endoreg_db.config.env import env_path
|
|
18
18
|
|
|
19
|
-
STORAGE_DIR = Path(os.getenv("STORAGE_DIR", "
|
|
19
|
+
STORAGE_DIR = Path(os.getenv("STORAGE_DIR", "internal_storage"))
|
|
20
20
|
|
|
21
21
|
storage_dir_env = os.getenv("STORAGE_DIR")
|
|
22
22
|
if storage_dir_env is None:
|
|
23
23
|
raise RuntimeError("STORAGE_DIR environment variable is not set.")
|
|
24
|
-
|
|
25
|
-
STORAGE_DIR =
|
|
24
|
+
storage_dir = Path(storage_dir_env)
|
|
25
|
+
STORAGE_DIR = storage_dir
|
|
26
26
|
if not STORAGE_DIR.exists():
|
|
27
27
|
STORAGE_DIR.mkdir(parents=True, exist_ok=True)
|
|
28
28
|
|
|
29
|
+
|
|
29
30
|
PREFIX_RAW = "raw_"
|
|
31
|
+
io_dir_env = Path(os.getenv("IO_DIR", "data"))
|
|
32
|
+
io_dir = Path(io_dir_env)
|
|
33
|
+
IO_DIR = io_dir
|
|
34
|
+
if not STORAGE_DIR.exists():
|
|
35
|
+
STORAGE_DIR.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Data dropoff folders - These can be external, determined by IO_DIR (Default: set to desktop root folder of OS)
|
|
39
|
+
|
|
30
40
|
IMPORT_DIR_NAME = "import"
|
|
31
41
|
EXPORT_DIR_NAME = "export"
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
IMPORT_DIR = IO_DIR / IMPORT_DIR_NAME # data/import
|
|
44
|
+
EXPORT_DIR = IO_DIR / EXPORT_DIR_NAME # data/export
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
IMPORT_VIDEO_DIR_NAME = "video_import"
|
|
48
|
+
REPORT_IMPORT_DIR_NAME = "report_import"
|
|
49
|
+
|
|
50
|
+
VIDEO_EXPORT_DIR_NAME = "video_export"
|
|
51
|
+
REPORT_EXPORT_DIR_NAME = "report_export"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
IMPORT_VIDEO_DIR = IMPORT_DIR / IMPORT_VIDEO_DIR_NAME
|
|
55
|
+
IMPORT_REPORT_DIR = IMPORT_DIR / REPORT_IMPORT_DIR_NAME
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
VIDEO_EXPORT_DIR = EXPORT_DIR / VIDEO_EXPORT_DIR_NAME
|
|
59
|
+
REPORT_EXPORT_DIR = EXPORT_DIR / REPORT_EXPORT_DIR_NAME
|
|
60
|
+
|
|
61
|
+
# Document Dir
|
|
62
|
+
|
|
63
|
+
DOCUMENT_DIR = STORAGE_DIR / "documents"
|
|
64
|
+
|
|
65
|
+
# After initial import, files will remain here.
|
|
66
|
+
|
|
67
|
+
TRANSCODING_DIR = STORAGE_DIR /"temp"
|
|
68
|
+
|
|
69
|
+
SENSITIVE_VIDEO_DIR_NAME = "sensitive_videos"
|
|
70
|
+
SENSITIVE_REPORT_DIR_NAME = "sensitive_reports"
|
|
71
|
+
ANONYM_VIDEO_DIR_NAME = "processed_videos_final"
|
|
72
|
+
ANONYM_REPORT_DIR_NAME = "processed_reports_final"
|
|
73
|
+
|
|
74
|
+
RAW_FRAME_DIR_NAME = f"{PREFIX_RAW}frames"
|
|
35
75
|
FRAME_DIR_NAME = "frames"
|
|
36
|
-
PDF_DIR_NAME = "pdfs" # Changed from reports
|
|
37
76
|
WEIGHTS_DIR_NAME = "model_weights"
|
|
38
77
|
EXAMINATION_DIR_NAME = "examinations"
|
|
39
78
|
|
|
40
|
-
RAW_VIDEO_DIR_NAME = f"{PREFIX_RAW}videos"
|
|
41
|
-
RAW_FRAME_DIR_NAME = f"{PREFIX_RAW}frames"
|
|
42
|
-
RAW_PDF_DIR_NAME = f"{PREFIX_RAW}pdfs" # Changed from reports
|
|
43
|
-
|
|
44
79
|
# Define data subdirectories under STORAGE_DIR
|
|
45
|
-
|
|
46
|
-
|
|
80
|
+
ANONYM_VIDEO_DIR = STORAGE_DIR / ANONYM_VIDEO_DIR_NAME
|
|
81
|
+
SENSITIVE_VIDEO_DIR = STORAGE_DIR / SENSITIVE_VIDEO_DIR_NAME
|
|
82
|
+
ANONYM_REPORT_DIR = STORAGE_DIR / ANONYM_REPORT_DIR_NAME
|
|
83
|
+
SENSITIVE_REPORT_DIR = STORAGE_DIR / SENSITIVE_REPORT_DIR_NAME
|
|
84
|
+
|
|
47
85
|
FRAME_DIR = STORAGE_DIR / FRAME_DIR_NAME
|
|
48
|
-
|
|
86
|
+
|
|
87
|
+
|
|
49
88
|
WEIGHTS_DIR = STORAGE_DIR / WEIGHTS_DIR_NAME
|
|
50
|
-
RAW_VIDEO_DIR = STORAGE_DIR / RAW_VIDEO_DIR_NAME
|
|
51
89
|
RAW_FRAME_DIR = STORAGE_DIR / RAW_FRAME_DIR_NAME
|
|
52
|
-
RAW_PDF_DIR = STORAGE_DIR / RAW_PDF_DIR_NAME # Changed
|
|
53
90
|
|
|
54
|
-
IMPORT_DIR = STORAGE_DIR / IMPORT_DIR_NAME
|
|
55
|
-
VIDEO_IMPORT_DIR = IMPORT_DIR / VIDEO_DIR_NAME
|
|
56
|
-
FRAME_IMPORT_DIR = IMPORT_DIR / FRAME_DIR_NAME
|
|
57
|
-
PDF_IMPORT_DIR = IMPORT_DIR / PDF_DIR_NAME # Changed
|
|
58
91
|
WEIGHTS_IMPORT_DIR = IMPORT_DIR / WEIGHTS_DIR_NAME
|
|
92
|
+
WEIGHTS_EXPORT_DIR = EXPORT_DIR / WEIGHTS_DIR_NAME
|
|
93
|
+
|
|
94
|
+
FRAME_IMPORT_DIR = IMPORT_DIR / FRAME_DIR_NAME
|
|
59
95
|
|
|
60
|
-
|
|
96
|
+
FRAME_EXPORT_DIR = EXPORT_DIR / FRAME_DIR_NAME
|
|
61
97
|
|
|
62
|
-
|
|
98
|
+
|
|
99
|
+
data_paths: Dict[str, Path] = {
|
|
63
100
|
"storage": STORAGE_DIR,
|
|
64
|
-
"video": VIDEO_DIR,
|
|
65
|
-
"anonym_video": ANONYM_VIDEO_DIR, # Added
|
|
66
|
-
"frame": FRAME_DIR,
|
|
67
|
-
"pdf": PDF_DIR, # Changed
|
|
68
101
|
"import": IMPORT_DIR,
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
102
|
+
"import_video": IMPORT_VIDEO_DIR,
|
|
103
|
+
"sensitive_video": SENSITIVE_VIDEO_DIR,
|
|
104
|
+
"sensitive_report": SENSITIVE_REPORT_DIR,
|
|
105
|
+
"anonym_video": ANONYM_VIDEO_DIR,
|
|
106
|
+
"anonym_report": ANONYM_REPORT_DIR,
|
|
107
|
+
"import_frame": FRAME_IMPORT_DIR,
|
|
108
|
+
"import_report": IMPORT_REPORT_DIR,
|
|
73
109
|
"raw_frame": RAW_FRAME_DIR,
|
|
74
|
-
"raw_pdf": RAW_PDF_DIR, # Changed
|
|
75
110
|
"weights": WEIGHTS_DIR,
|
|
76
111
|
"weights_import": WEIGHTS_IMPORT_DIR,
|
|
77
112
|
"export": EXPORT_DIR,
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"frame_export":
|
|
81
|
-
"pdf_export": EXPORT_DIR / PDF_DIR_NAME, # Changed
|
|
113
|
+
"report_export": REPORT_EXPORT_DIR,
|
|
114
|
+
"video_export": VIDEO_EXPORT_DIR,
|
|
115
|
+
"frame_export": FRAME_EXPORT_DIR,
|
|
82
116
|
"weights_export": EXPORT_DIR / WEIGHTS_DIR_NAME,
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"raw_pdf_export": EXPORT_DIR / RAW_PDF_DIR_NAME, # Changed
|
|
117
|
+
"transcoding": TRANSCODING_DIR,
|
|
118
|
+
"frame": FRAME_DIR,
|
|
119
|
+
"documents": DOCUMENT_DIR
|
|
87
120
|
}
|
|
88
121
|
|
|
89
122
|
logger.info(f"Storage directory: {STORAGE_DIR.resolve()}")
|
|
90
123
|
logger.info(f"Export directory: {EXPORT_DIR.resolve()}")
|
|
91
124
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
for key, path in data_paths.items():
|
|
126
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
127
|
+
|
|
128
|
+
logger.info(f"{key.capitalize()} directory: {path.resolve()}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def to_storage_relative(path: Union[str, Path]) -> str:
|
|
132
|
+
"""
|
|
133
|
+
Return a path string relative to STORAGE_DIR, suitable for Django FileField.name.
|
|
134
|
+
|
|
135
|
+
- If `path` is inside STORAGE_DIR (absolute or contains STORAGE_DIR as prefix),
|
|
136
|
+
we strip the STORAGE_DIR prefix and return the relative part.
|
|
137
|
+
- If `path` is outside STORAGE_DIR, we return it as a string unchanged
|
|
138
|
+
(caller can decide what to do).
|
|
139
|
+
"""
|
|
140
|
+
# Normalize input to Path
|
|
141
|
+
p = Path(path)
|
|
142
|
+
|
|
143
|
+
# Resolve absolute path for comparison
|
|
144
|
+
storage_root = STORAGE_DIR.resolve()
|
|
145
|
+
|
|
146
|
+
if not p.is_absolute():
|
|
147
|
+
# Resolve relative path against current working directory
|
|
148
|
+
# (in tests, cwd should be project root, so this still lands under STORAGE_DIR)
|
|
149
|
+
p = p.resolve()
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
rel = p.relative_to(storage_root)
|
|
153
|
+
except ValueError:
|
|
154
|
+
# Not under STORAGE_DIR – probably already a relative name or external.
|
|
155
|
+
# In that case, just return the string representation as-is.
|
|
156
|
+
return str(path)
|
|
157
|
+
|
|
158
|
+
# Use POSIX-style separators for Django FileField
|
|
159
|
+
return rel.as_posix()
|
|
@@ -154,7 +154,7 @@ At this point in the pipeline:
|
|
|
154
154
|
`VideoFile.processed_file`
|
|
155
155
|
- Video hash is calculated and saved in:
|
|
156
156
|
`VideoFile.processed_video_hash`
|
|
157
|
-
- `VideoState.
|
|
157
|
+
- `VideoState.state.anonymization_status.mark_anonymized()`
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, Tuple, Union
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from endoreg_db.models import Patient, PatientExamination, Requirement
|
|
5
|
+
from endoreg_db.models.requirement.requirement_operator import OperatorInstructions, RequirementOperator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def fetch_input_target(input_object: Union["Patient", "PatientExamination"], operator_instructions: "OperatorInstructions") -> Tuple[str, Any]:
|
|
9
|
+
input_target_names = operator_instructions.input_targets
|
|
10
|
+
|
|
11
|
+
# Iterate over targets and stop with first successful fetch
|
|
12
|
+
for input_target in input_target_names:
|
|
13
|
+
# separate input_target using "." for nested attributes
|
|
14
|
+
attributes = input_target.split(".")
|
|
15
|
+
current_value = input_object
|
|
16
|
+
try:
|
|
17
|
+
for attr in attributes:
|
|
18
|
+
current_value = getattr(current_value, attr)
|
|
19
|
+
return (input_target, current_value)
|
|
20
|
+
except AttributeError:
|
|
21
|
+
continue # Try next input target
|
|
22
|
+
|
|
23
|
+
raise AttributeError(f"None of the input targets {input_target_names} could be resolved on the input object.")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def fetch_requirement_targets(
|
|
27
|
+
requirement: "Requirement",
|
|
28
|
+
operator_instructions: "OperatorInstructions",
|
|
29
|
+
):
|
|
30
|
+
attribute_target_names = operator_instructions.requirement_targets
|
|
31
|
+
target_values = {}
|
|
32
|
+
|
|
33
|
+
for target_name in attribute_target_names:
|
|
34
|
+
try:
|
|
35
|
+
target_value = getattr(requirement, target_name)
|
|
36
|
+
target_values[target_name] = target_value
|
|
37
|
+
except AttributeError:
|
|
38
|
+
raise AttributeError(f"Requirement does not have attribute '{target_name}'.")
|
|
39
|
+
target_values[target_name] = target_value
|
|
40
|
+
|
|
41
|
+
return target_values
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def model_attribute_set_any(
|
|
45
|
+
input_object: Any,
|
|
46
|
+
operator_instructions: "OperatorInstructions",
|
|
47
|
+
requirement: "Requirement",
|
|
48
|
+
) -> bool:
|
|
49
|
+
input_target_name, input_value = fetch_input_target(input_object, operator_instructions)
|
|
50
|
+
|
|
51
|
+
if not input_value:
|
|
52
|
+
return False
|
|
53
|
+
else:
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def model_attribute_numeric_in_range(
|
|
58
|
+
input_object: Any,
|
|
59
|
+
operator_instructions: "OperatorInstructions",
|
|
60
|
+
requirement: "Requirement",
|
|
61
|
+
) -> bool:
|
|
62
|
+
input_target_name, input_value = fetch_input_target(input_object, operator_instructions)
|
|
63
|
+
|
|
64
|
+
# make sure, input_value is numeric
|
|
65
|
+
try:
|
|
66
|
+
numeric_value = float(input_value)
|
|
67
|
+
except (TypeError, ValueError):
|
|
68
|
+
raise ValueError(f"Input value for target '{input_target_name}' is not numeric: {input_value}")
|
|
69
|
+
|
|
70
|
+
_min = requirement.numeric_value_min
|
|
71
|
+
_max = requirement.numeric_value_max
|
|
72
|
+
|
|
73
|
+
assert _min is not None and _max is not None, "Numeric range requires both min and max values to be set."
|
|
74
|
+
|
|
75
|
+
return_value = _min <= numeric_value <= _max
|
|
76
|
+
return return_value
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def model_attribute_is_among_values(
|
|
80
|
+
input_object: Any,
|
|
81
|
+
operator_instructions: "OperatorInstructions",
|
|
82
|
+
requirement: "Requirement",
|
|
83
|
+
) -> bool:
|
|
84
|
+
input_target_name, input_value = fetch_input_target(input_object, operator_instructions)
|
|
85
|
+
target_values = fetch_requirement_targets(requirement, operator_instructions)
|
|
86
|
+
|
|
87
|
+
for target_name, target_values in target_values.items():
|
|
88
|
+
if input_value in target_values:
|
|
89
|
+
return True
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
REQUIREMENT_OPERATORS = {
|
|
94
|
+
"model_attribute_set_any": model_attribute_set_any,
|
|
95
|
+
"model_attribute_numeric_in_range": model_attribute_numeric_in_range,
|
|
96
|
+
"model_attribute_is_among_values": model_attribute_is_among_values,
|
|
97
|
+
}
|