endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.0__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/authz/auth.py +74 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +18 -0
- endoreg_db/authz/middleware.py +83 -0
- endoreg_db/authz/permissions.py +127 -0
- endoreg_db/authz/policy.py +218 -0
- endoreg_db/authz/views_auth.py +66 -0
- endoreg_db/config/env.py +13 -8
- endoreg_db/data/__init__.py +8 -31
- endoreg_db/data/_examples/disease.yaml +55 -0
- endoreg_db/data/_examples/disease_classification.yaml +13 -0
- endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
- endoreg_db/data/_examples/event.yaml +64 -0
- endoreg_db/data/_examples/examination.yaml +72 -0
- endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/_examples/finding/complication.yaml +16 -0
- endoreg_db/data/_examples/finding/data.yaml +105 -0
- endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
- endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
- endoreg_db/data/_examples/finding/outcome.yaml +12 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/_examples/finding_type/data.yaml +43 -0
- endoreg_db/data/_examples/requirement/age.yaml +26 -0
- endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/_examples/requirement/gender.yaml +25 -0
- endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
- endoreg_db/data/_examples/requirement/medication.yaml +93 -0
- endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
- endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
- endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
- endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
- endoreg_db/data/requirement_set/90_coloreg.yaml +178 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set_type/data.yaml +21 -0
- endoreg_db/data/setup_config.yaml +4 -4
- endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
- endoreg_db/exceptions.py +5 -2
- endoreg_db/helpers/data_loader.py +1 -1
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
- endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +1 -1
- endoreg_db/management/commands/init_default_ai_model.py +1 -1
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_requirement_data.py +60 -31
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/migrations/0001_initial.py +1799 -1300
- endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
- endoreg_db/migrations/_old/0001_initial.py +1857 -0
- endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
- endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
- endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
- endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
- endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
- endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
- endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
- endoreg_db/models/__init__.py +78 -123
- endoreg_db/models/administration/__init__.py +21 -42
- endoreg_db/models/administration/ai/active_model.py +2 -2
- endoreg_db/models/administration/ai/ai_model.py +7 -6
- endoreg_db/models/administration/case/__init__.py +1 -15
- endoreg_db/models/administration/case/case.py +3 -3
- endoreg_db/models/administration/case/case_template/__init__.py +2 -14
- endoreg_db/models/administration/case/case_template/case_template.py +2 -124
- endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
- endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
- endoreg_db/models/administration/center/center.py +33 -19
- endoreg_db/models/administration/center/center_product.py +12 -9
- endoreg_db/models/administration/center/center_resource.py +25 -19
- endoreg_db/models/administration/center/center_shift.py +21 -17
- endoreg_db/models/administration/center/center_waste.py +16 -8
- endoreg_db/models/administration/person/__init__.py +2 -0
- endoreg_db/models/administration/person/employee/employee.py +10 -5
- endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
- endoreg_db/models/administration/person/employee/employee_type.py +12 -6
- endoreg_db/models/administration/person/examiner/examiner.py +13 -11
- endoreg_db/models/administration/person/patient/__init__.py +2 -0
- endoreg_db/models/administration/person/patient/patient.py +103 -100
- endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
- endoreg_db/models/administration/person/person.py +4 -0
- endoreg_db/models/administration/person/profession/__init__.py +8 -4
- endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
- endoreg_db/models/administration/product/product.py +20 -15
- endoreg_db/models/administration/product/product_material.py +17 -18
- endoreg_db/models/administration/product/product_weight.py +12 -8
- endoreg_db/models/administration/product/reference_product.py +23 -55
- endoreg_db/models/administration/qualification/qualification.py +7 -3
- endoreg_db/models/administration/qualification/qualification_type.py +7 -3
- endoreg_db/models/administration/shift/scheduled_days.py +8 -5
- endoreg_db/models/administration/shift/shift.py +16 -12
- endoreg_db/models/administration/shift/shift_type.py +23 -31
- endoreg_db/models/label/__init__.py +7 -8
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
- endoreg_db/models/label/label.py +15 -15
- endoreg_db/models/label/label_set.py +19 -6
- endoreg_db/models/label/label_type.py +1 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
- endoreg_db/models/label/label_video_segment/label_video_segment.py +76 -102
- endoreg_db/models/label/video_segmentation_label.py +4 -0
- endoreg_db/models/label/video_segmentation_labelset.py +4 -3
- endoreg_db/models/media/frame/frame.py +22 -22
- endoreg_db/models/media/pdf/raw_pdf.py +110 -182
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +48 -56
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +150 -108
- endoreg_db/models/media/video/video_file_ai.py +288 -74
- endoreg_db/models/media/video/video_file_anonymize.py +38 -38
- endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
- endoreg_db/models/media/video/video_file_io.py +109 -62
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
- endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
- endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
- endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
- endoreg_db/models/media/video/video_file_segments.py +24 -17
- endoreg_db/models/media/video/video_metadata.py +19 -35
- endoreg_db/models/media/video/video_processing.py +96 -95
- endoreg_db/models/medical/contraindication/__init__.py +13 -3
- endoreg_db/models/medical/disease.py +22 -16
- endoreg_db/models/medical/event.py +31 -18
- endoreg_db/models/medical/examination/__init__.py +13 -6
- endoreg_db/models/medical/examination/examination.py +17 -18
- endoreg_db/models/medical/examination/examination_indication.py +26 -25
- endoreg_db/models/medical/examination/examination_time.py +16 -6
- endoreg_db/models/medical/examination/examination_time_type.py +9 -6
- endoreg_db/models/medical/examination/examination_type.py +3 -4
- endoreg_db/models/medical/finding/finding.py +38 -39
- endoreg_db/models/medical/finding/finding_classification.py +37 -48
- endoreg_db/models/medical/finding/finding_intervention.py +27 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +20 -26
- endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
- endoreg_db/models/medical/laboratory/lab_value.py +62 -91
- endoreg_db/models/medical/medication/medication.py +22 -10
- endoreg_db/models/medical/medication/medication_indication.py +29 -3
- endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
- endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
- endoreg_db/models/medical/medication/medication_schedule.py +27 -16
- endoreg_db/models/medical/organ/__init__.py +15 -12
- endoreg_db/models/medical/patient/medication_examples.py +1 -5
- endoreg_db/models/medical/patient/patient_disease.py +20 -23
- endoreg_db/models/medical/patient/patient_event.py +19 -22
- endoreg_db/models/medical/patient/patient_examination.py +48 -54
- endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
- endoreg_db/models/medical/patient/patient_finding.py +122 -139
- endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
- endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
- endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
- endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
- endoreg_db/models/medical/patient/patient_medication.py +27 -38
- endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
- endoreg_db/models/medical/risk/risk.py +7 -6
- endoreg_db/models/medical/risk/risk_type.py +8 -5
- endoreg_db/models/metadata/model_meta.py +60 -29
- endoreg_db/models/metadata/model_meta_logic.py +125 -18
- endoreg_db/models/metadata/pdf_meta.py +19 -24
- endoreg_db/models/metadata/sensitive_meta.py +102 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +192 -173
- endoreg_db/models/metadata/video_meta.py +51 -31
- endoreg_db/models/metadata/video_prediction_logic.py +16 -23
- endoreg_db/models/metadata/video_prediction_meta.py +29 -33
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
- endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
- endoreg_db/models/other/emission/emission_factor.py +18 -8
- endoreg_db/models/other/gender.py +10 -5
- endoreg_db/models/other/information_source.py +25 -25
- endoreg_db/models/other/material.py +9 -5
- endoreg_db/models/other/resource.py +6 -4
- endoreg_db/models/other/tag.py +10 -5
- endoreg_db/models/other/transport_route.py +13 -8
- endoreg_db/models/other/unit.py +10 -6
- endoreg_db/models/other/waste.py +6 -5
- endoreg_db/models/requirement/requirement.py +580 -272
- endoreg_db/models/requirement/requirement_error.py +85 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
- endoreg_db/models/requirement/requirement_operator.py +36 -33
- endoreg_db/models/requirement/requirement_set.py +74 -57
- endoreg_db/models/state/__init__.py +4 -4
- endoreg_db/models/state/abstract.py +2 -2
- endoreg_db/models/state/anonymization.py +12 -0
- endoreg_db/models/state/audit_ledger.py +46 -47
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +40 -46
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +58 -53
- endoreg_db/models/upload_job.py +32 -55
- endoreg_db/models/utils.py +1 -2
- endoreg_db/root_urls.py +21 -2
- endoreg_db/serializers/__init__.py +0 -2
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/meta/report_meta.py +1 -1
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/anonymization.py +75 -73
- endoreg_db/services/lookup_service.py +37 -24
- endoreg_db/services/pdf_import.py +166 -68
- endoreg_db/services/storage_aware_video_processor.py +140 -114
- endoreg_db/services/video_import.py +193 -283
- endoreg_db/urls/__init__.py +7 -20
- endoreg_db/urls/media.py +108 -67
- endoreg_db/urls/root_urls.py +29 -0
- endoreg_db/utils/__init__.py +15 -5
- endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/dataloader.py +88 -16
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
- endoreg_db/utils/setup_config.py +8 -5
- endoreg_db/utils/storage.py +115 -0
- endoreg_db/utils/validate_endo_roi.py +8 -2
- endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
- endoreg_db/views/__init__.py +0 -10
- endoreg_db/views/anonymization/media_management.py +198 -163
- endoreg_db/views/anonymization/overview.py +4 -1
- endoreg_db/views/anonymization/validate.py +174 -40
- endoreg_db/views/media/__init__.py +2 -0
- endoreg_db/views/media/pdf_media.py +131 -152
- endoreg_db/views/media/sensitive_metadata.py +46 -6
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/media/video_segments.py +2 -3
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/pdf/pdf_stream.py +20 -21
- endoreg_db/views/pdf/reimport.py +11 -32
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +0 -2
- endoreg_db/views/video/correction.py +2 -2
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +341 -245
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/rule/__init__.py +0 -13
- endoreg_db/models/rule/rule.py +0 -27
- endoreg_db/models/rule/rule_applicator.py +0 -224
- endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
- endoreg_db/models/rule/rule_type.py +0 -20
- endoreg_db/models/rule/ruleset.py +0 -17
- endoreg_db/serializers/video/video_metadata.py +0 -105
- endoreg_db/urls/report.py +0 -48
- endoreg_db/urls/video.py +0 -61
- endoreg_db/utils/case_generator/case_generator.py +0 -159
- endoreg_db/utils/case_generator/utils.py +0 -30
- endoreg_db/views/report/__init__.py +0 -9
- endoreg_db/views/report/report_list.py +0 -112
- endoreg_db/views/report/report_with_secure_url.py +0 -28
- endoreg_db/views/report/start_examination.py +0 -7
- endoreg_db/views.py +0 -0
- /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
- /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
- /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → views/pdf/pdf_stream_views.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
# endoreg_db/services/anonymization.py
|
|
2
|
+
import logging
|
|
2
3
|
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
3
6
|
from django.db import transaction
|
|
4
|
-
|
|
5
|
-
from endoreg_db.models import
|
|
6
|
-
from endoreg_db.services.video_import import VideoImportService
|
|
7
|
+
|
|
8
|
+
from endoreg_db.models import RawPdfFile, VideoFile
|
|
7
9
|
from endoreg_db.services.pdf_import import PdfImportService
|
|
10
|
+
from endoreg_db.services.video_import import VideoImportService
|
|
8
11
|
from endoreg_db.utils.paths import STORAGE_DIR
|
|
9
|
-
import
|
|
12
|
+
from endoreg_db.utils.storage import ensure_local_file, file_exists
|
|
10
13
|
|
|
11
14
|
logger = logging.getLogger(__name__)
|
|
12
15
|
|
|
16
|
+
|
|
13
17
|
class AnonymizationService:
|
|
14
18
|
"""
|
|
15
19
|
Orchestrates long‑running anonymization tasks so the view only
|
|
16
20
|
does HTTP <-> Service translation.
|
|
17
21
|
"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, project_root: Path = None):
|
|
22
|
+
|
|
23
|
+
def __init__(self, project_root: Optional[Path] = None):
|
|
20
24
|
"""
|
|
21
25
|
Initialize the AnonymizationService with service instances.
|
|
22
|
-
|
|
26
|
+
|
|
23
27
|
Args:
|
|
24
28
|
project_root: Path to the project root. If None, uses settings.BASE_DIR
|
|
25
29
|
"""
|
|
26
|
-
|
|
27
|
-
project_root = STORAGE_DIR
|
|
28
|
-
|
|
30
|
+
self.project_root: Path = project_root or STORAGE_DIR
|
|
29
31
|
self.video_service = VideoImportService()
|
|
30
32
|
self.pdf_service = PdfImportService()
|
|
31
33
|
|
|
@@ -34,7 +36,7 @@ class AnonymizationService:
|
|
|
34
36
|
def get_status(file_id: int):
|
|
35
37
|
"""
|
|
36
38
|
Retrieve the anonymization status and media type for a file by its ID.
|
|
37
|
-
|
|
39
|
+
|
|
38
40
|
Returns:
|
|
39
41
|
dict or None: A dictionary containing the file's media type and anonymization status if found, or None if no matching file exists.
|
|
40
42
|
"""
|
|
@@ -43,7 +45,7 @@ class AnonymizationService:
|
|
|
43
45
|
return {
|
|
44
46
|
"mediaType": "video",
|
|
45
47
|
"anonymizationStatus": vf.state.anonymization_status if vf.state else "not_started",
|
|
46
|
-
"fileExists":
|
|
48
|
+
"fileExists": file_exists(vf.raw_file),
|
|
47
49
|
"uuid": str(vf.uuid) if vf.uuid else None,
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -52,7 +54,7 @@ class AnonymizationService:
|
|
|
52
54
|
return {
|
|
53
55
|
"mediaType": "pdf",
|
|
54
56
|
"anonymizationStatus": pdf.state.anonymization_status if pdf.state else "not_started",
|
|
55
|
-
"fileExists":
|
|
57
|
+
"fileExists": file_exists(pdf.file),
|
|
56
58
|
"hash": pdf.pdf_hash,
|
|
57
59
|
}
|
|
58
60
|
return None
|
|
@@ -62,10 +64,10 @@ class AnonymizationService:
|
|
|
62
64
|
def start(self, file_id: int):
|
|
63
65
|
"""
|
|
64
66
|
Start anonymization process for a file by its ID.
|
|
65
|
-
|
|
67
|
+
|
|
66
68
|
Args:
|
|
67
69
|
file_id: The ID of the file to anonymize
|
|
68
|
-
|
|
70
|
+
|
|
69
71
|
Returns:
|
|
70
72
|
str or None: Media type if successful, None if file not found
|
|
71
73
|
"""
|
|
@@ -74,45 +76,42 @@ class AnonymizationService:
|
|
|
74
76
|
if vf:
|
|
75
77
|
try:
|
|
76
78
|
logger.info(f"Starting video anonymization for VideoFile ID: {file_id}")
|
|
77
|
-
|
|
79
|
+
|
|
78
80
|
# Check if already processed
|
|
79
81
|
if vf.state and vf.state.anonymized:
|
|
80
82
|
logger.info(f"VideoFile {file_id} already anonymized, skipping")
|
|
81
83
|
return "video"
|
|
82
|
-
|
|
84
|
+
|
|
83
85
|
# Get file path
|
|
84
86
|
file_path = vf.get_raw_file_path()
|
|
85
87
|
if not file_path or not Path(file_path).exists():
|
|
86
88
|
logger.error(f"Raw file not found for VideoFile {file_id}: {file_path}")
|
|
87
89
|
return None
|
|
88
|
-
|
|
90
|
+
|
|
89
91
|
# Get processor name
|
|
90
92
|
processor_name = None
|
|
91
93
|
if vf.video_meta and vf.video_meta.processor:
|
|
92
94
|
processor_name = vf.video_meta.processor.name
|
|
93
|
-
elif hasattr(vf,
|
|
95
|
+
elif hasattr(vf, "processor") and vf.processor:
|
|
94
96
|
processor_name = vf.processor.name
|
|
95
|
-
|
|
97
|
+
|
|
96
98
|
# Get center name
|
|
97
99
|
center_name = vf.center.name if vf.center else "unknown_center"
|
|
98
|
-
|
|
100
|
+
|
|
99
101
|
# Mark as started
|
|
100
102
|
if vf.state:
|
|
101
103
|
vf.state.processing_started = True
|
|
102
104
|
vf.state.save(update_fields=["processing_started"])
|
|
103
|
-
|
|
105
|
+
|
|
104
106
|
# Use VideoImportService for anonymization
|
|
107
|
+
safe_processor_name = processor_name or "unknown_processor"
|
|
105
108
|
self.video_service.import_and_anonymize(
|
|
106
|
-
file_path=file_path,
|
|
107
|
-
center_name=center_name,
|
|
108
|
-
processor_name=processor_name,
|
|
109
|
-
save_video=True,
|
|
110
|
-
delete_source=False
|
|
109
|
+
file_path=file_path, center_name=center_name, processor_name=safe_processor_name, save_video=True, delete_source=False
|
|
111
110
|
)
|
|
112
|
-
|
|
111
|
+
|
|
113
112
|
logger.info(f"Video anonymization completed for VideoFile ID: {file_id}")
|
|
114
113
|
return "video"
|
|
115
|
-
|
|
114
|
+
|
|
116
115
|
except Exception as e:
|
|
117
116
|
logger.error(f"Failed to anonymize VideoFile {file_id}: {e}")
|
|
118
117
|
# Mark as failed if state exists
|
|
@@ -126,51 +125,48 @@ class AnonymizationService:
|
|
|
126
125
|
if pdf:
|
|
127
126
|
try:
|
|
128
127
|
logger.info(f"Starting PDF processing for RawPdfFile ID: {file_id}")
|
|
129
|
-
|
|
128
|
+
|
|
130
129
|
# Check if already processed
|
|
131
|
-
if pdf.state and getattr(pdf.state,
|
|
130
|
+
if pdf.state and getattr(pdf.state, "anonymized", False):
|
|
132
131
|
logger.info(f"RawPdfFile {file_id} already processed, skipping")
|
|
133
132
|
return "pdf"
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if not
|
|
133
|
+
|
|
134
|
+
file_field = pdf.file
|
|
135
|
+
if not file_field or not file_field.name:
|
|
137
136
|
logger.error(f"PDF file not found for RawPdfFile {file_id}")
|
|
138
137
|
return None
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
logger.error(f"PDF file does not exist: {file_path}")
|
|
138
|
+
|
|
139
|
+
if not file_exists(file_field):
|
|
140
|
+
logger.error("PDF file missing from storage for RawPdfFile %s", file_id)
|
|
143
141
|
return None
|
|
144
|
-
|
|
142
|
+
|
|
145
143
|
# Get center name
|
|
146
144
|
center_name = pdf.center.name if pdf.center else "unknown_center"
|
|
147
|
-
|
|
145
|
+
|
|
148
146
|
# Mark as started
|
|
149
147
|
if pdf.state:
|
|
150
148
|
pdf.state.processing_started = True
|
|
151
149
|
pdf.state.save(update_fields=["processing_started"])
|
|
152
|
-
elif pdf.sensitive_meta:
|
|
150
|
+
elif pdf.sensitive_meta and hasattr(pdf.sensitive_meta, "anonymization_started"):
|
|
153
151
|
pdf.sensitive_meta.anonymization_started = True
|
|
154
152
|
pdf.sensitive_meta.save(update_fields=["anonymization_started"])
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
163
|
-
|
|
153
|
+
|
|
154
|
+
with ensure_local_file(file_field) as local_path:
|
|
155
|
+
self.pdf_service.import_and_anonymize(
|
|
156
|
+
file_path=local_path,
|
|
157
|
+
center_name=center_name,
|
|
158
|
+
)
|
|
159
|
+
|
|
164
160
|
logger.info(f"PDF processing completed for RawPdfFile ID: {file_id}")
|
|
165
161
|
return "pdf"
|
|
166
|
-
|
|
162
|
+
|
|
167
163
|
except Exception as e:
|
|
168
164
|
logger.error(f"Failed to process RawPdfFile {file_id}: {e}")
|
|
169
165
|
# Mark as failed if state exists
|
|
170
|
-
if pdf.state:
|
|
166
|
+
if pdf.state and hasattr(pdf.state, "processing_failed"):
|
|
171
167
|
pdf.state.processing_failed = True
|
|
172
168
|
pdf.state.save(update_fields=["processing_failed"])
|
|
173
|
-
elif pdf.sensitive_meta:
|
|
169
|
+
elif pdf.sensitive_meta and hasattr(pdf.sensitive_meta, "processing_failed"):
|
|
174
170
|
pdf.sensitive_meta.processing_failed = True
|
|
175
171
|
pdf.sensitive_meta.save(update_fields=["processing_failed"])
|
|
176
172
|
raise
|
|
@@ -183,41 +179,47 @@ class AnonymizationService:
|
|
|
183
179
|
def validate(file_id: int):
|
|
184
180
|
vf = VideoFile.objects.select_related("state").filter(pk=file_id).first()
|
|
185
181
|
if vf:
|
|
186
|
-
vf.state.
|
|
182
|
+
state = vf.state or vf.get_or_create_state()
|
|
183
|
+
if hasattr(state, "mark_anonymization_validated"):
|
|
184
|
+
state.mark_anonymization_validated()
|
|
187
185
|
return "video"
|
|
188
186
|
|
|
189
187
|
pdf = RawPdfFile.objects.select_related("state").filter(pk=file_id).first()
|
|
190
188
|
if pdf:
|
|
191
|
-
pdf.state.
|
|
189
|
+
state = pdf.state or pdf.get_or_create_state()
|
|
190
|
+
if hasattr(state, "mark_anonymization_validated"):
|
|
191
|
+
state.mark_anonymization_validated()
|
|
192
192
|
return "pdf"
|
|
193
193
|
|
|
194
194
|
return None
|
|
195
|
-
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
196
197
|
def list_items():
|
|
197
198
|
video_files = VideoFile.objects.select_related("state").all()
|
|
198
199
|
pdf_files = RawPdfFile.objects.select_related("state").all() # was sensitive_meta
|
|
199
200
|
|
|
200
201
|
data = []
|
|
201
202
|
for vf in video_files:
|
|
202
|
-
data.append(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
203
|
+
data.append(
|
|
204
|
+
{
|
|
205
|
+
"id": vf.pk,
|
|
206
|
+
"mediaType": "video",
|
|
207
|
+
"anonymizationStatus": vf.state.anonymization_status if vf.state else "not_started",
|
|
208
|
+
"createdAt": vf.date_created,
|
|
209
|
+
"updatedAt": vf.date_modified,
|
|
210
|
+
}
|
|
211
|
+
)
|
|
211
212
|
|
|
212
213
|
for pdf in pdf_files:
|
|
213
|
-
data.append(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
data.append(
|
|
215
|
+
{
|
|
216
|
+
"id": pdf.pk,
|
|
217
|
+
"mediaType": "pdf",
|
|
218
|
+
"anonymizationStatus": pdf.state.anonymization_status if pdf.state else "not_started",
|
|
219
|
+
"createdAt": pdf.date_created,
|
|
220
|
+
"updatedAt": pdf.date_modified,
|
|
221
|
+
}
|
|
222
|
+
)
|
|
220
223
|
return data
|
|
221
224
|
|
|
222
|
-
|
|
223
225
|
return data
|
|
@@ -24,9 +24,10 @@ Architecture:
|
|
|
24
24
|
# services/lookup_service.py
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
import logging
|
|
28
|
+
from typing import Any, Dict, List, Optional
|
|
28
29
|
|
|
29
|
-
from django.db.models import Prefetch
|
|
30
|
+
from django.db.models import Prefetch, QuerySet
|
|
30
31
|
|
|
31
32
|
from endoreg_db.models.medical.examination import ExaminationRequirementSet
|
|
32
33
|
from endoreg_db.models.medical.patient.patient_examination import PatientExamination
|
|
@@ -88,31 +89,43 @@ def load_patient_exam_for_eval(pk: int) -> PatientExamination:
|
|
|
88
89
|
)
|
|
89
90
|
|
|
90
91
|
|
|
91
|
-
def requirement_sets_for_patient_exam(
|
|
92
|
+
def requirement_sets_for_patient_exam(
|
|
93
|
+
pe: PatientExamination, user_tags: Optional[List[str]] = None
|
|
94
|
+
) -> QuerySet:
|
|
92
95
|
"""
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
This function resolves requirement sets through the examination's requirement set links.
|
|
96
|
-
It follows the relationship: PatientExamination → Examination → ExaminationRequirementSet → RequirementSet
|
|
96
|
+
Retrieve all RequirementSets linked to a PatientExamination's examination.
|
|
97
97
|
|
|
98
98
|
Args:
|
|
99
|
-
pe: PatientExamination instance
|
|
99
|
+
pe: PatientExamination instance
|
|
100
|
+
user_tags: Optional list of tag names to filter requirement sets
|
|
100
101
|
|
|
101
102
|
Returns:
|
|
102
|
-
|
|
103
|
+
QuerySet of RequirementSet instances
|
|
103
104
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
105
|
+
if not pe or not pe.examination:
|
|
106
|
+
from endoreg_db.models import RequirementSet
|
|
107
|
+
|
|
108
|
+
return RequirementSet.objects.none()
|
|
109
|
+
|
|
110
|
+
# Start with examination-linked requirement sets
|
|
111
|
+
req_sets = pe.examination.exam_reqset_links.select_related(
|
|
112
|
+
"requirement_set"
|
|
113
|
+
).values_list("requirement_set", flat=True)
|
|
114
|
+
|
|
115
|
+
from endoreg_db.models import RequirementSet
|
|
113
116
|
|
|
117
|
+
qs = RequirementSet.objects.filter(pk__in=req_sets)
|
|
114
118
|
|
|
115
|
-
|
|
119
|
+
# Apply tag filtering if provided
|
|
120
|
+
if user_tags:
|
|
121
|
+
qs = qs.filter(tags__name__in=user_tags).distinct()
|
|
122
|
+
|
|
123
|
+
return qs
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def build_initial_lookup(
|
|
127
|
+
pe: PatientExamination, user_tags: Optional[List[str]] = None
|
|
128
|
+
) -> Dict[str, Any]:
|
|
116
129
|
"""
|
|
117
130
|
Build the initial lookup dictionary for a patient examination.
|
|
118
131
|
|
|
@@ -153,7 +166,7 @@ def build_initial_lookup(pe: PatientExamination) -> Dict[str, Any]:
|
|
|
153
166
|
required_findings: List[int] = [] # fill by scanning requirements below
|
|
154
167
|
|
|
155
168
|
# Requirement sets: ids + meta
|
|
156
|
-
rs_objs = requirement_sets_for_patient_exam(pe)
|
|
169
|
+
rs_objs = requirement_sets_for_patient_exam(pe, user_tags=user_tags)
|
|
157
170
|
requirement_sets = [
|
|
158
171
|
{
|
|
159
172
|
"id": rs.id,
|
|
@@ -202,7 +215,9 @@ def build_initial_lookup(pe: PatientExamination) -> Dict[str, Any]:
|
|
|
202
215
|
}
|
|
203
216
|
|
|
204
217
|
|
|
205
|
-
def create_lookup_token_for_pe(
|
|
218
|
+
def create_lookup_token_for_pe(
|
|
219
|
+
pe_id: int, user_tags: Optional[List[str]] = None
|
|
220
|
+
) -> str:
|
|
206
221
|
"""
|
|
207
222
|
Create a lookup token for a patient examination.
|
|
208
223
|
|
|
@@ -220,7 +235,7 @@ def create_lookup_token_for_pe(pe_id: int) -> str:
|
|
|
220
235
|
Exception: For any other errors during initialization
|
|
221
236
|
"""
|
|
222
237
|
pe = load_patient_exam_for_eval(pe_id)
|
|
223
|
-
token = LookupStore().init(build_initial_lookup(pe))
|
|
238
|
+
token = LookupStore().init(build_initial_lookup(pe, user_tags=user_tags))
|
|
224
239
|
return token
|
|
225
240
|
|
|
226
241
|
|
|
@@ -255,8 +270,6 @@ def recompute_lookup(token: str) -> Dict[str, Any]:
|
|
|
255
270
|
Raises:
|
|
256
271
|
ValueError: If lookup data is invalid or patient examination not found
|
|
257
272
|
"""
|
|
258
|
-
import logging
|
|
259
|
-
|
|
260
273
|
logger = logging.getLogger(__name__)
|
|
261
274
|
|
|
262
275
|
store = LookupStore(token=token)
|