endoreg-db 0.8.8.0__py3-none-any.whl → 0.8.8.9__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 +400 -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/processing/video_processing/video_cleanup_on_error.py +119 -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/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 +64 -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/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.8.9.dist-info}/METADATA +2 -2
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +217 -335
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.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/{migrations/__init__.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/{urls/sensitive_meta.py → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/{views/pdf/pdf_stream_views.py → import_files/pseudonymization/pseudonymize.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.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from logging import getLogger # Added logger
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Union
|
|
3
3
|
|
|
4
4
|
from django.db import models
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from endoreg_db.utils.requirement_operator_logic.new_operator_logic import REQUIREMENT_OPERATORS, model_attribute_set_any
|
|
5
8
|
|
|
6
9
|
# see how operator evaluation function is fetched, add to docs #TODO
|
|
7
10
|
# endoreg_db/utils/requirement_operator_logic/model_evaluators.py
|
|
@@ -14,6 +17,65 @@ if TYPE_CHECKING:
|
|
|
14
17
|
logger = getLogger(__name__) # Added logger instance
|
|
15
18
|
|
|
16
19
|
|
|
20
|
+
class OperatorInstructions(BaseModel):
|
|
21
|
+
input_targets: List[str] = []
|
|
22
|
+
requirement_targets: List[str] = []
|
|
23
|
+
kwargs: Dict[str, Union[str, int, float, bool]] = {}
|
|
24
|
+
args: List[Union[str, int, float, bool]] = []
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _parse_operator_instructions(raw: str):
|
|
28
|
+
target_attributes_list = [_.strip() for _ in raw.split(";") if _.strip()]
|
|
29
|
+
|
|
30
|
+
input_targets = []
|
|
31
|
+
kwargs: Dict[str, Union[str, int, float, bool]] = {}
|
|
32
|
+
args: List[Union[str, int, float, bool]] = []
|
|
33
|
+
|
|
34
|
+
valid_prefixes = [
|
|
35
|
+
"!", # Requirement target
|
|
36
|
+
"?", # Input target
|
|
37
|
+
"$", # Keyword argument, keyword and value separated by ":"
|
|
38
|
+
"@", # Positional argument
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
for entry in target_attributes_list:
|
|
42
|
+
_prefix = entry[0]
|
|
43
|
+
|
|
44
|
+
if _prefix in valid_prefixes:
|
|
45
|
+
_attribute = entry[1:].strip()
|
|
46
|
+
if _prefix == "!":
|
|
47
|
+
# Requirement target
|
|
48
|
+
input_targets.append(_attribute)
|
|
49
|
+
elif _prefix == "?":
|
|
50
|
+
# Input target
|
|
51
|
+
input_targets.append(_attribute)
|
|
52
|
+
elif _prefix == "$":
|
|
53
|
+
# Keyword argument
|
|
54
|
+
if ":" in _attribute:
|
|
55
|
+
key, value = _attribute.split(":", 1)
|
|
56
|
+
kwargs[key.strip()] = value.strip()
|
|
57
|
+
else:
|
|
58
|
+
raise ValueError(f"Invalid keyword argument format in target_attributes: '{entry}'. Expected format is '$key:value'.")
|
|
59
|
+
elif _prefix == "@":
|
|
60
|
+
# Positional argument
|
|
61
|
+
args.append(_attribute)
|
|
62
|
+
else:
|
|
63
|
+
raise ValueError(f"Invalid prefix '{_prefix}' in target_attributes entry: '{entry}'. Valid prefixes are {valid_prefixes}.")
|
|
64
|
+
return OperatorInstructions(
|
|
65
|
+
input_targets=input_targets,
|
|
66
|
+
requirement_targets=input_targets,
|
|
67
|
+
kwargs=kwargs,
|
|
68
|
+
args=args,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _validate_operator_instructions(instance: "Requirement") -> bool:
|
|
73
|
+
"""Ensures requirement fixtures declare at least one target attribute."""
|
|
74
|
+
if not instance.operator_instructions_parsed:
|
|
75
|
+
raise ValueError(f"Requirement '{instance.name}' must declare at least one target attribute.")
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
|
|
17
79
|
class RequirementOperatorManager(models.Manager):
|
|
18
80
|
def get_by_natural_key(self, name):
|
|
19
81
|
"""
|
|
@@ -48,16 +110,18 @@ class RequirementOperator(models.Model):
|
|
|
48
110
|
|
|
49
111
|
requirements: models.QuerySet[Requirement]
|
|
50
112
|
|
|
51
|
-
@
|
|
52
|
-
def
|
|
113
|
+
@classmethod
|
|
114
|
+
def parse_instructions(cls, raw: str) -> OperatorInstructions:
|
|
53
115
|
"""
|
|
54
|
-
|
|
116
|
+
Parses the raw target attributes string into structured operator instructions.
|
|
55
117
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
from .requirement_evaluation.operator_evaluation_models import operator_evaluation_models
|
|
118
|
+
Args:
|
|
119
|
+
raw: The raw target attributes string.
|
|
59
120
|
|
|
60
|
-
|
|
121
|
+
Returns:
|
|
122
|
+
An OperatorInstructions instance containing parsed input targets, requirement targets, kwargs, and args.
|
|
123
|
+
"""
|
|
124
|
+
return _parse_operator_instructions(raw)
|
|
61
125
|
|
|
62
126
|
@property
|
|
63
127
|
def data_model_dict(self):
|
|
@@ -84,96 +148,20 @@ class RequirementOperator(models.Model):
|
|
|
84
148
|
"""
|
|
85
149
|
return str(self.name)
|
|
86
150
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
|
|
151
|
+
def get_operator_function(self) -> Callable[..., bool]:
|
|
152
|
+
_operator_function = REQUIREMENT_OPERATORS.get(self.name)
|
|
153
|
+
if not _operator_function:
|
|
154
|
+
raise ValueError(f"Operator function for '{self.name}' not found in REQUIREMENT_OPERATORS.")
|
|
155
|
+
return _operator_function
|
|
90
156
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
157
|
+
def evaluate(self, operator_instructions: "OperatorInstructions", requirement: "Requirement", input_obj: Any, **kwargs) -> bool:
|
|
158
|
+
""" """
|
|
159
|
+
eval_result: bool = False
|
|
160
|
+
requirement_links: "RequirementLinks" = requirement.links
|
|
161
|
+
expected_input_models = requirement.expected_models
|
|
162
|
+
operator_function = self.get_operator_function()
|
|
97
163
|
|
|
98
|
-
|
|
99
|
-
|
|
164
|
+
input_model = type(input_obj)
|
|
165
|
+
assert input_model in expected_input_models, f"Input model {input_model} not in expected models {expected_input_models}"
|
|
100
166
|
|
|
101
|
-
|
|
102
|
-
NotImplementedError: If the evaluation logic for the operator's name is not implemented.
|
|
103
|
-
"""
|
|
104
|
-
# kwargs should contain 'requirement' (the Requirement instance) passed from Requirement.evaluate()
|
|
105
|
-
if self.evaluation_function_name:
|
|
106
|
-
eval_func = getattr(self, self.evaluation_function_name, None)
|
|
107
|
-
if eval_func and callable(eval_func):
|
|
108
|
-
result = eval_func(requirement_links=requirement_links, input_links=input_links, **kwargs)
|
|
109
|
-
assert isinstance(result, bool), (
|
|
110
|
-
f"Evaluation function '{self.evaluation_function_name}' for operator '{self.name}' must return a boolean value."
|
|
111
|
-
)
|
|
112
|
-
return result
|
|
113
|
-
else:
|
|
114
|
-
logger.error(
|
|
115
|
-
f"Evaluation function '{self.evaluation_function_name}' not found or not callable on {self.__class__.__name__} for operator '{self.name}'."
|
|
116
|
-
)
|
|
117
|
-
raise NotImplementedError(f"Evaluation function '{self.evaluation_function_name}' not implemented correctly for operator '{self.name}'.")
|
|
118
|
-
else:
|
|
119
|
-
# Fallback to the central dispatcher if no specific function name is provided
|
|
120
|
-
from endoreg_db.utils.requirement_operator_logic.model_evaluators import dispatch_operator_evaluation
|
|
121
|
-
|
|
122
|
-
return dispatch_operator_evaluation(
|
|
123
|
-
operator_name=self.name,
|
|
124
|
-
requirement_links=requirement_links,
|
|
125
|
-
input_links=input_links,
|
|
126
|
-
operator_instance=self, # Pass the operator instance
|
|
127
|
-
**kwargs,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
from ..medical.medication import MedicationSchedule as MedicationScheduleTemplate # Added with alias
|
|
131
|
-
from ..medical.patient.patient_medication import PatientMedication # Added
|
|
132
|
-
|
|
133
|
-
def _evaluate_patient_medication_schedule_matches_template(
|
|
134
|
-
self,
|
|
135
|
-
requirement_links: "RequirementLinks",
|
|
136
|
-
input_links: "RequirementLinks",
|
|
137
|
-
requirement: "Requirement", # Added requirement
|
|
138
|
-
**kwargs,
|
|
139
|
-
) -> bool:
|
|
140
|
-
"""
|
|
141
|
-
Checks if any PatientMedication in the input PatientMedicationSchedule
|
|
142
|
-
matches the profile (medication, dose, unit, intake times)
|
|
143
|
-
of any MedicationSchedule template linked to the requirement.
|
|
144
|
-
"""
|
|
145
|
-
# Get MedicationSchedule templates from the requirement
|
|
146
|
-
req_schedule_templates = requirement_links.medication_schedules
|
|
147
|
-
if not req_schedule_templates:
|
|
148
|
-
# If the requirement doesn't specify any templates to match against,
|
|
149
|
-
# it's ambiguous. Consider this a non-match.
|
|
150
|
-
return False
|
|
151
|
-
|
|
152
|
-
# Get PatientMedication instances from the input (derived from PatientMedicationSchedule.links)
|
|
153
|
-
input_patient_medications = input_links.patient_medications
|
|
154
|
-
if not input_patient_medications:
|
|
155
|
-
# If the input schedule has no medications, it cannot match any template.
|
|
156
|
-
return False
|
|
157
|
-
|
|
158
|
-
for pm_instance in input_patient_medications:
|
|
159
|
-
pm_intake_times_set = set(pm_instance.intake_times.all())
|
|
160
|
-
for schedule_template in req_schedule_templates:
|
|
161
|
-
template_intake_times_set = set(schedule_template.intake_times.all())
|
|
162
|
-
|
|
163
|
-
# Check for profile match
|
|
164
|
-
medication_match = pm_instance.medication == schedule_template.medication
|
|
165
|
-
dose_match = pm_instance.dosage == schedule_template.dose
|
|
166
|
-
unit_match = pm_instance.unit == schedule_template.unit
|
|
167
|
-
intake_times_match = pm_intake_times_set == template_intake_times_set
|
|
168
|
-
|
|
169
|
-
# Debugging output (optional, can be removed)
|
|
170
|
-
# print(f"Comparing PM ID {pm_instance.id} with Template {schedule_template.name}:")
|
|
171
|
-
# print(f" Medication: {pm_instance.medication} vs {schedule_template.medication} -> {medication_match}")
|
|
172
|
-
# print(f" Dose: {pm_instance.dosage} vs {schedule_template.dose} -> {dose_match}")
|
|
173
|
-
# print(f" Unit: {pm_instance.unit} vs {schedule_template.unit} -> {unit_match}")
|
|
174
|
-
# print(f" Intake Times: {pm_intake_times_set} vs {template_intake_times_set} -> {intake_times_match}")
|
|
175
|
-
|
|
176
|
-
if medication_match and dose_match and unit_match and intake_times_match:
|
|
177
|
-
return True # Found a match
|
|
178
|
-
|
|
179
|
-
return False # No PatientMedication matched any template
|
|
167
|
+
return eval_result
|
|
@@ -89,7 +89,7 @@ class AuditLedger(models.Model):
|
|
|
89
89
|
"""
|
|
90
90
|
payload = {
|
|
91
91
|
"ts": self.ts.isoformat(),
|
|
92
|
-
"uid": str(self.
|
|
92
|
+
"uid": str(self.id),
|
|
93
93
|
"obj": f"{self.object_type}:{self.object_pk}",
|
|
94
94
|
"act": self.action,
|
|
95
95
|
"data": self.data,
|
|
@@ -97,7 +97,7 @@ class AuditLedger(models.Model):
|
|
|
97
97
|
}
|
|
98
98
|
return hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
|
|
99
99
|
|
|
100
|
-
def log_validation(user, instance, action: str, extra=None):
|
|
100
|
+
def log_validation(self, user, instance, action: str, extra=None):
|
|
101
101
|
"""
|
|
102
102
|
Creates an audit record for a validation action performed by a user on a specific model instance.
|
|
103
103
|
|
|
@@ -115,7 +115,8 @@ class AuditLedger(models.Model):
|
|
|
115
115
|
data=extra or {},
|
|
116
116
|
)
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
@classmethod
|
|
119
|
+
def _distinct(self, object_type: str, action: str):
|
|
119
120
|
"""
|
|
120
121
|
Returns the number of distinct objects of a given type that have a specific audit action recorded.
|
|
121
122
|
|
|
@@ -142,8 +143,6 @@ class AuditLedger(models.Model):
|
|
|
142
143
|
"totalAnnotations": AuditLedger.objects.filter(action="annotation_added").count(),
|
|
143
144
|
"totalAnonymizations": AuditLedger._distinct("VideoFile", "anonymized"),
|
|
144
145
|
"totalImages": AuditLedger._distinct("Image", "created"),
|
|
145
|
-
# video breakdown
|
|
146
146
|
"videosCompleted": AuditLedger._distinct("VideoFile", "validated"),
|
|
147
147
|
"videosAnonym": AuditLedger._distinct("VideoFile", "anonymized"),
|
|
148
|
-
# add more as needed …
|
|
149
148
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Defines state tracking models related to
|
|
2
|
+
Defines state tracking models related to report processing, including extraction of text and metadata, AI predictions, and anonymization status for RawPdfFile instances.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
from enum import Enum
|
|
7
7
|
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
-
from django.db import models
|
|
9
|
+
from django.db import models, transaction
|
|
10
10
|
|
|
11
11
|
from endoreg_db.models.state.anonymization import AnonymizationState
|
|
12
12
|
|
|
@@ -22,7 +22,9 @@ class RawPdfState(models.Model):
|
|
|
22
22
|
Uses BooleanFields for clear, distinct states.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
text_meta_extracted = models.BooleanField(
|
|
25
|
+
text_meta_extracted = models.BooleanField(
|
|
26
|
+
default=False, help_text="True if text metadata (OCR) has been extracted."
|
|
27
|
+
)
|
|
26
28
|
|
|
27
29
|
# AI / Annotation related states
|
|
28
30
|
initial_prediction_completed = models.BooleanField(
|
|
@@ -31,26 +33,39 @@ class RawPdfState(models.Model):
|
|
|
31
33
|
|
|
32
34
|
# Processing state
|
|
33
35
|
sensitive_meta_processed = models.BooleanField(
|
|
34
|
-
default=False,
|
|
36
|
+
default=False,
|
|
37
|
+
help_text="True if the video has been fully processed, meaning a anonymized person was created.",
|
|
35
38
|
)
|
|
36
39
|
|
|
37
40
|
# Anonymization state
|
|
38
|
-
anonymized = models.BooleanField(
|
|
39
|
-
|
|
41
|
+
anonymized = models.BooleanField(
|
|
42
|
+
default=False, help_text="True if the anonymized video file has been created."
|
|
43
|
+
)
|
|
44
|
+
anonymization_validated = models.BooleanField(
|
|
45
|
+
default=False,
|
|
46
|
+
help_text="True if the anonymization process has been validated and confirmed.",
|
|
47
|
+
)
|
|
40
48
|
|
|
41
49
|
# Processing state
|
|
42
|
-
processing_started = models.BooleanField(
|
|
43
|
-
|
|
50
|
+
processing_started = models.BooleanField(
|
|
51
|
+
default=False,
|
|
52
|
+
help_text="True if the processing has started, but not yet completed.",
|
|
53
|
+
)
|
|
54
|
+
processing_error = models.BooleanField(
|
|
55
|
+
default=False, help_text="True if an error occurred during processing."
|
|
56
|
+
)
|
|
44
57
|
|
|
45
58
|
# Timestamps
|
|
46
59
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
47
60
|
date_modified = models.DateTimeField(auto_now=True)
|
|
48
61
|
|
|
49
|
-
was_created = models.BooleanField(
|
|
62
|
+
was_created = models.BooleanField(
|
|
63
|
+
default=True, help_text="True if this state was created for the first time."
|
|
64
|
+
)
|
|
50
65
|
|
|
51
|
-
#
|
|
66
|
+
# report metadata extraction state
|
|
52
67
|
pdf_meta_extracted = models.BooleanField(
|
|
53
|
-
default=False, help_text="True if
|
|
68
|
+
default=False, help_text="True if report metadata has been extracted."
|
|
54
69
|
)
|
|
55
70
|
|
|
56
71
|
if TYPE_CHECKING:
|
|
@@ -58,7 +73,7 @@ class RawPdfState(models.Model):
|
|
|
58
73
|
|
|
59
74
|
def __str__(self):
|
|
60
75
|
"""
|
|
61
|
-
Return a string summarizing the RawPdfState instance, including the related
|
|
76
|
+
Return a string summarizing the RawPdfState instance, including the related report file UUID and key processing state flags with timestamps.
|
|
62
77
|
"""
|
|
63
78
|
try:
|
|
64
79
|
uuid = self.raw_pdf_file.pk
|
|
@@ -79,25 +94,50 @@ class RawPdfState(models.Model):
|
|
|
79
94
|
@property
|
|
80
95
|
def anonymization_status(self) -> AnonymizationState:
|
|
81
96
|
"""
|
|
82
|
-
Determines the current anonymization workflow status for the
|
|
97
|
+
Determines the current anonymization workflow status for the report processing state.
|
|
83
98
|
|
|
84
99
|
Returns:
|
|
85
100
|
AnonymizationStatus: The current status, reflecting progress or failure in the anonymization process.
|
|
86
101
|
"""
|
|
87
102
|
if self.anonymization_validated:
|
|
88
|
-
return AnonymizationState.VALIDATED
|
|
103
|
+
return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
|
|
89
104
|
if self.sensitive_meta_processed:
|
|
90
|
-
return
|
|
91
|
-
|
|
105
|
+
return (
|
|
106
|
+
AnonymizationState.DONE_PROCESSING_ANONYMIZATION
|
|
107
|
+
) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
|
|
108
|
+
if (
|
|
109
|
+
self.processing_started
|
|
110
|
+
and not self.processing_error
|
|
111
|
+
and not self.anonymized
|
|
112
|
+
):
|
|
92
113
|
return AnonymizationState.PROCESSING_ANONYMIZING
|
|
93
114
|
if getattr(self, "processing_error", False):
|
|
94
|
-
return
|
|
115
|
+
return (
|
|
116
|
+
AnonymizationState.FAILED
|
|
117
|
+
) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
|
|
95
118
|
if self.processing_started:
|
|
96
|
-
return
|
|
119
|
+
return (
|
|
120
|
+
AnonymizationState.STARTED
|
|
121
|
+
) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
|
|
97
122
|
if self.anonymized:
|
|
98
123
|
return AnonymizationState.ANONYMIZED
|
|
99
124
|
return AnonymizationState.NOT_STARTED
|
|
100
125
|
|
|
126
|
+
def mark_processing_not_started(self) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Mark the processing as not started and optionally save the updated state.
|
|
129
|
+
|
|
130
|
+
Parameters:
|
|
131
|
+
save (bool): If True, persist the change to the database immediately. Defaults to True.
|
|
132
|
+
"""
|
|
133
|
+
with transaction.atomic():
|
|
134
|
+
self.processing_started = False
|
|
135
|
+
self.anonymized = False
|
|
136
|
+
self.was_created = False
|
|
137
|
+
self.sensitive_meta_processed = False
|
|
138
|
+
self.anonymization_validated = False
|
|
139
|
+
self.save()
|
|
140
|
+
|
|
101
141
|
def mark_processing_started(self, *, save: bool = True) -> None:
|
|
102
142
|
"""
|
|
103
143
|
Mark the processing as started and optionally save the updated state.
|
|
@@ -106,13 +146,12 @@ class RawPdfState(models.Model):
|
|
|
106
146
|
save (bool): If True, persist the change to the database immediately. Defaults to True.
|
|
107
147
|
"""
|
|
108
148
|
self.processing_started = True
|
|
109
|
-
|
|
110
|
-
self.save(update_fields=["processing_started", "date_modified"])
|
|
149
|
+
self.save(update_fields=["processing_started", "date_modified"])
|
|
111
150
|
|
|
112
151
|
# ---- Single‑responsibility mutators ---------------------------------
|
|
113
152
|
def mark_sensitive_meta_processed(self, *, save: bool = True) -> None:
|
|
114
153
|
"""
|
|
115
|
-
Mark the sensitive metadata processing step as completed for this
|
|
154
|
+
Mark the sensitive metadata processing step as completed for this report state.
|
|
116
155
|
|
|
117
156
|
Parameters:
|
|
118
157
|
save (bool): If True, immediately saves the updated state to the database.
|
|
@@ -123,7 +162,7 @@ class RawPdfState(models.Model):
|
|
|
123
162
|
|
|
124
163
|
def mark_anonymization_validated(self, *, save: bool = True) -> None:
|
|
125
164
|
"""
|
|
126
|
-
Mark the anonymization as validated for this
|
|
165
|
+
Mark the anonymization as validated for this report processing state.
|
|
127
166
|
|
|
128
167
|
Parameters:
|
|
129
168
|
save (bool): If True, immediately saves the updated state to the database.
|
|
@@ -134,18 +173,18 @@ class RawPdfState(models.Model):
|
|
|
134
173
|
|
|
135
174
|
def mark_anonymized(self, *, save: bool = True) -> None:
|
|
136
175
|
"""
|
|
137
|
-
Mark the
|
|
176
|
+
Mark the report as anonymized and optionally save the updated state.
|
|
138
177
|
|
|
139
178
|
Parameters:
|
|
140
179
|
save (bool): If True, persist the change to the database immediately. Defaults to True.
|
|
141
180
|
"""
|
|
142
|
-
|
|
143
|
-
|
|
181
|
+
with transaction.atomic():
|
|
182
|
+
self.anonymized = True
|
|
144
183
|
self.save(update_fields=["anonymized", "date_modified"])
|
|
145
184
|
|
|
146
185
|
def mark_initial_prediction_completed(self, *, save: bool = True) -> None:
|
|
147
186
|
"""
|
|
148
|
-
Mark the initial AI prediction step as completed for this
|
|
187
|
+
Mark the initial AI prediction step as completed for this report processing state.
|
|
149
188
|
|
|
150
189
|
Parameters:
|
|
151
190
|
save (bool): If True, immediately saves the updated state to the database.
|
|
@@ -156,7 +195,7 @@ class RawPdfState(models.Model):
|
|
|
156
195
|
|
|
157
196
|
def mark_pdf_meta_extracted(self, *, save: bool = True) -> None:
|
|
158
197
|
"""
|
|
159
|
-
Mark the
|
|
198
|
+
Mark the report metadata extraction step as completed for this state.
|
|
160
199
|
|
|
161
200
|
Parameters:
|
|
162
201
|
save (bool): If True, immediately saves the updated state to the database.
|
|
@@ -167,7 +206,7 @@ class RawPdfState(models.Model):
|
|
|
167
206
|
|
|
168
207
|
def mark_text_meta_extracted(self, *, save: bool = True) -> None:
|
|
169
208
|
"""
|
|
170
|
-
Mark the text metadata extraction step as completed for this
|
|
209
|
+
Mark the text metadata extraction step as completed for this report processing state.
|
|
171
210
|
|
|
172
211
|
Parameters:
|
|
173
212
|
save (bool): If True, immediately saves the updated state to the database.
|
|
@@ -177,5 +216,5 @@ class RawPdfState(models.Model):
|
|
|
177
216
|
self.save(update_fields=["text_meta_extracted", "date_modified"])
|
|
178
217
|
|
|
179
218
|
class Meta:
|
|
180
|
-
verbose_name = "Raw
|
|
181
|
-
verbose_name_plural = "Raw
|
|
219
|
+
verbose_name = "Raw report Processing State"
|
|
220
|
+
verbose_name_plural = "Raw report Processing States"
|
endoreg_db/models/state/video.py
CHANGED
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
from enum import Enum
|
|
7
7
|
from typing import TYPE_CHECKING, Optional
|
|
8
8
|
|
|
9
|
-
from django.db import models
|
|
9
|
+
from django.db import models, transaction
|
|
10
10
|
|
|
11
11
|
from endoreg_db.models.state.anonymization import AnonymizationState
|
|
12
12
|
|
|
@@ -22,14 +22,19 @@ class VideoState(models.Model):
|
|
|
22
22
|
Uses BooleanFields for clear, distinct states.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
# Frame related states
|
|
27
26
|
if TYPE_CHECKING:
|
|
28
27
|
video_file: models.OneToOneField["VideoFile"]
|
|
29
28
|
|
|
30
|
-
frames_extracted = models.BooleanField(
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
frames_extracted = models.BooleanField(
|
|
30
|
+
default=False, help_text="True if raw frames have been extracted to files."
|
|
31
|
+
)
|
|
32
|
+
frames_initialized = models.BooleanField(
|
|
33
|
+
default=False, help_text="True if Frame DB objects have been created."
|
|
34
|
+
)
|
|
35
|
+
frame_count = models.PositiveIntegerField(
|
|
36
|
+
null=True, blank=True, help_text="Number of frames extracted/initialized."
|
|
37
|
+
)
|
|
33
38
|
|
|
34
39
|
# Metadata related states
|
|
35
40
|
video_meta_extracted = models.BooleanField(
|
|
@@ -41,63 +46,57 @@ class VideoState(models.Model):
|
|
|
41
46
|
)
|
|
42
47
|
|
|
43
48
|
# AI / Annotation related states
|
|
44
|
-
initial_prediction_completed = models.BooleanField(
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
initial_prediction_completed = models.BooleanField(
|
|
50
|
+
default=False, help_text="True if initial AI prediction has run."
|
|
51
|
+
)
|
|
52
|
+
lvs_created = models.BooleanField(
|
|
53
|
+
default=False,
|
|
54
|
+
help_text="True if LabelVideoSegments have been created from predictions.",
|
|
55
|
+
)
|
|
56
|
+
frame_annotations_generated = models.BooleanField(
|
|
57
|
+
default=False,
|
|
58
|
+
help_text="True if frame-level annotations have been generated from segments.",
|
|
59
|
+
)
|
|
47
60
|
|
|
48
61
|
# Processing state
|
|
49
62
|
sensitive_meta_processed = models.BooleanField(
|
|
50
|
-
default=False,
|
|
63
|
+
default=False,
|
|
64
|
+
help_text="True if the video has been fully processed, meaning a anonymized person was created.",
|
|
51
65
|
)
|
|
52
66
|
|
|
53
67
|
# Anonymization state
|
|
54
|
-
anonymized = models.BooleanField(
|
|
55
|
-
|
|
68
|
+
anonymized = models.BooleanField(
|
|
69
|
+
default=False, help_text="True if the anonymized video file has been created."
|
|
70
|
+
)
|
|
71
|
+
anonymization_validated = models.BooleanField(
|
|
72
|
+
default=False,
|
|
73
|
+
help_text="True if the anonymization process has been validated and confirmed.",
|
|
74
|
+
)
|
|
56
75
|
|
|
57
|
-
processing_started = models.BooleanField(
|
|
76
|
+
processing_started = models.BooleanField(
|
|
77
|
+
default=False,
|
|
78
|
+
help_text="True if the processing has started, but not yet completed.",
|
|
79
|
+
)
|
|
58
80
|
|
|
59
81
|
# Timestamps
|
|
60
82
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
61
83
|
date_modified = models.DateTimeField(auto_now=True)
|
|
62
84
|
|
|
63
85
|
# Segment Annotation State
|
|
64
|
-
segment_annotations_created = models.BooleanField(
|
|
65
|
-
|
|
86
|
+
segment_annotations_created = models.BooleanField(
|
|
87
|
+
default=False,
|
|
88
|
+
help_text="True if segment annotations have been created from LabelVideoSegments.",
|
|
89
|
+
)
|
|
90
|
+
segment_annotations_validated = models.BooleanField(
|
|
91
|
+
default=False, help_text="True if segment annotations have been validated."
|
|
92
|
+
)
|
|
66
93
|
|
|
67
|
-
was_created = models.BooleanField(
|
|
94
|
+
was_created = models.BooleanField(
|
|
95
|
+
default=True, help_text="True if this state was created for the first time."
|
|
96
|
+
)
|
|
68
97
|
|
|
69
98
|
objects = models.Manager()
|
|
70
99
|
|
|
71
|
-
def __str__(self):
|
|
72
|
-
# Find the related VideoFile's UUID if possible
|
|
73
|
-
video_uuid = "Unknown"
|
|
74
|
-
try:
|
|
75
|
-
# Access the related VideoFile via the reverse relation 'video_file'
|
|
76
|
-
if hasattr(self, "video_file") and self.video_file:
|
|
77
|
-
video_uuid = self.video_file.uuid
|
|
78
|
-
except Exception:
|
|
79
|
-
pass # Ignore errors if relation doesn't exist or causes issues
|
|
80
|
-
pass # Ignore errors if relation doesn't exist or causes issues
|
|
81
|
-
|
|
82
|
-
states = [
|
|
83
|
-
f"FramesExtracted={self.frames_extracted}",
|
|
84
|
-
f"FramesInit={self.frames_initialized}",
|
|
85
|
-
f"VideoMetaExtracted={self.video_meta_extracted}",
|
|
86
|
-
f"TextMetaExtracted={self.text_meta_extracted}",
|
|
87
|
-
f"PredictionDone={self.initial_prediction_completed}",
|
|
88
|
-
f"LvsCreated={self.lvs_created}",
|
|
89
|
-
f"Anonymized={self.anonymized}",
|
|
90
|
-
f"AnonymizationValidated={self.anonymization_validated}",
|
|
91
|
-
f"SensitiveMetaProcessed={self.sensitive_meta_processed}",
|
|
92
|
-
f"FrameCount={self.frame_count}"
|
|
93
|
-
if self.frame_count is not None
|
|
94
|
-
else "FrameCount=None",
|
|
95
|
-
f"SegmentAnnotationsCreated={self.segment_annotations_created}",
|
|
96
|
-
f"SegmentAnnotationsValidated={self.segment_annotations_validated}",
|
|
97
|
-
f"DateCreated={self.date_created.isoformat()}",
|
|
98
|
-
f"DateModified={self.date_modified.isoformat()}",
|
|
99
|
-
]
|
|
100
|
-
return f"VideoState(Video:{video_uuid}): {', '.join(states)}"
|
|
101
100
|
|
|
102
101
|
@property
|
|
103
102
|
def anonymization_status(self) -> AnonymizationState:
|
|
@@ -105,9 +104,9 @@ class VideoState(models.Model):
|
|
|
105
104
|
Fast, side‑effect‑free status resolution used by API & UI.
|
|
106
105
|
"""
|
|
107
106
|
if self.anonymization_validated:
|
|
108
|
-
return AnonymizationState.VALIDATED
|
|
107
|
+
return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
|
|
109
108
|
if self.sensitive_meta_processed:
|
|
110
|
-
return AnonymizationState.DONE_PROCESSING_ANONYMIZATION
|
|
109
|
+
return AnonymizationState.DONE_PROCESSING_ANONYMIZATION # /home/admin/endoreg-db/endoreg_db/services/video_import.py /home/admin/endoreg-db/endoreg_db/views/video/reimport.py
|
|
111
110
|
if self.frames_extracted and not self.anonymized:
|
|
112
111
|
return AnonymizationState.PROCESSING_ANONYMIZING
|
|
113
112
|
if self.was_created and not self.frames_extracted:
|
|
@@ -120,6 +119,22 @@ class VideoState(models.Model):
|
|
|
120
119
|
return AnonymizationState.ANONYMIZED
|
|
121
120
|
return AnonymizationState.NOT_STARTED
|
|
122
121
|
|
|
122
|
+
def mark_processing_not_started(self) -> None:
|
|
123
|
+
"""
|
|
124
|
+
Mark the processing as not started and optionally save the updated state.
|
|
125
|
+
|
|
126
|
+
Parameters:
|
|
127
|
+
save (bool): If True, persist the change to the database immediately. Defaults to True.
|
|
128
|
+
"""
|
|
129
|
+
with transaction.atomic():
|
|
130
|
+
self.processing_started = False
|
|
131
|
+
self.anonymized = False
|
|
132
|
+
self.was_created = False
|
|
133
|
+
self.sensitive_meta_processed = False
|
|
134
|
+
self.anonymization_validated = False
|
|
135
|
+
self.frames_extracted = False
|
|
136
|
+
self.save()
|
|
137
|
+
|
|
123
138
|
# ---- Single‑responsibility mutators ---------------------------------
|
|
124
139
|
def mark_sensitive_meta_processed(self, *, save: bool = True) -> None:
|
|
125
140
|
self.sensitive_meta_processed = True
|
|
@@ -165,8 +180,8 @@ class VideoState(models.Model):
|
|
|
165
180
|
Parameters:
|
|
166
181
|
save (bool): If True, immediately saves the updated state to the database.
|
|
167
182
|
"""
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
with transaction.atomic():
|
|
184
|
+
self.anonymized = True
|
|
170
185
|
self.save(update_fields=["anonymized", "date_modified"])
|
|
171
186
|
|
|
172
187
|
def mark_initial_prediction_completed(self, *, save: bool = True) -> None:
|