endoreg-db 0.8.6.1__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/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 +2 -11
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- 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/02_colonoscopy_baseline.yaml +83 -0
- 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/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 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/finding_classification_choice/{colon_lesion_paris.yaml → 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/old/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -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 +4 -2
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +125 -53
- 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/create_model_meta_from_huggingface.py +21 -10
- endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
- endoreg_db/management/commands/import_report.py +130 -65
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +2 -2
- endoreg_db/management/commands/list_routes.py +18 -0
- 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_center_data.py +12 -12
- 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 +62 -39
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- 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/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +297 -250
- 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 +129 -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 +8 -9
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
- 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 +98 -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 +194 -194
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- 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/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +139 -77
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +174 -112
- 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 +113 -61
- 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/README.md +1 -0
- 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 +39 -20
- endoreg_db/models/medical/examination/examination_indication.py +30 -95
- endoreg_db/models/medical/examination/examination_time.py +23 -8
- 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 +32 -40
- endoreg_db/models/medical/finding/finding_classification.py +42 -72
- endoreg_db/models/medical/finding/finding_intervention.py +25 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +26 -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 +6 -6
- 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 +31 -24
- endoreg_db/models/metadata/sensitive_meta.py +105 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
- 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 +50 -29
- 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/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +329 -361
- 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 +103 -112
- 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 +49 -51
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +101 -68
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +110 -90
- endoreg_db/models/upload_job.py +35 -34
- endoreg_db/models/utils.py +28 -25
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/root_urls.py +21 -2
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -10
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- 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/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +128 -89
- endoreg_db/services/lookup_service.py +65 -52
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1382
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1255
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +5 -32
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +121 -83
- 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 +142 -40
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- 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 +85 -183
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +202 -166
- endoreg_db/views/anonymization/overview.py +99 -67
- endoreg_db/views/anonymization/validate.py +182 -44
- endoreg_db/views/media/__init__.py +7 -20
- endoreg_db/views/media/pdf_media.py +197 -174
- endoreg_db/views/media/sensitive_metadata.py +193 -138
- endoreg_db/views/media/video_media.py +89 -82
- 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/patient/patient.py +5 -4
- endoreg_db/views/report/__init__.py +5 -7
- endoreg_db/views/{pdf → report}/reimport.py +22 -22
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +23 -24
- 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} +77 -40
- 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.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
- 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_bowel_preparation.yaml +0 -95
- 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 -68
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
- 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 -51
- 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_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_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/gender.yaml +0 -25
- 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_add_video_correction_models.py +0 -52
- endoreg_db/migrations/0003_add_center_display_name.py +0 -30
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- 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/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/serializers/video/video_metadata.py +0 -105
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -344
- 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/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/utils/requirement_operator_logic/model_evaluators.py +0 -368
- 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 -148
- 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/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/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/views.py +0 -0
- /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
- /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
- /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
- /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
- /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
- /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
- /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
- /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
- /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
endoreg_db/utils/dataloader.py
CHANGED
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from datetime import UTC, datetime
|
|
3
|
+
|
|
2
4
|
import yaml
|
|
3
5
|
from django.core.exceptions import ObjectDoesNotExist
|
|
4
6
|
from django.db import OperationalError, transaction
|
|
5
7
|
|
|
8
|
+
from endoreg_db.utils.paths import STORAGE_DIR
|
|
9
|
+
|
|
10
|
+
_WARNING_LOG_PATH = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_warning_log_path():
|
|
14
|
+
"""Return the path used for warning logs, creating it on first access."""
|
|
15
|
+
global _WARNING_LOG_PATH
|
|
16
|
+
if _WARNING_LOG_PATH is None:
|
|
17
|
+
log_dir = STORAGE_DIR / "logs"
|
|
18
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
19
|
+
timestamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
|
20
|
+
_WARNING_LOG_PATH = log_dir / f"dataloader_warnings_{timestamp}.log"
|
|
21
|
+
return _WARNING_LOG_PATH
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _record_warning(command, message, verbose, context):
|
|
25
|
+
"""Write a warning to stdout (when verbose) and append it to the log file."""
|
|
26
|
+
prefix = f"[{context}] " if context else ""
|
|
27
|
+
full_message = f"{prefix}{message}"
|
|
28
|
+
|
|
29
|
+
if verbose:
|
|
30
|
+
command.stdout.write(command.style.WARNING(full_message))
|
|
31
|
+
|
|
32
|
+
log_path = _get_warning_log_path()
|
|
33
|
+
with open(log_path, "a", encoding="utf-8") as log_file:
|
|
34
|
+
log_file.write(f"{datetime.now(UTC).isoformat()}Z {full_message}\n")
|
|
35
|
+
|
|
6
36
|
|
|
7
37
|
def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
8
38
|
"""
|
|
@@ -16,10 +46,15 @@ def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
|
16
46
|
"""
|
|
17
47
|
if verbose:
|
|
18
48
|
command.stdout.write(f"Start loading {model_name}")
|
|
49
|
+
|
|
50
|
+
warning_log_path = _get_warning_log_path()
|
|
51
|
+
if verbose:
|
|
52
|
+
command.stdout.write(f"Warning log file: {warning_log_path}")
|
|
19
53
|
model = metadata["model"]
|
|
20
54
|
dir_path = metadata["dir"]
|
|
21
55
|
foreign_keys = metadata["foreign_keys"]
|
|
22
56
|
foreign_key_models = metadata["foreign_key_models"]
|
|
57
|
+
validators = metadata.get("validators", [])
|
|
23
58
|
|
|
24
59
|
_files = [f for f in os.listdir(dir_path) if f.endswith(".yaml")]
|
|
25
60
|
# sort
|
|
@@ -29,16 +64,30 @@ def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
|
29
64
|
yaml_data = yaml.safe_load(file)
|
|
30
65
|
|
|
31
66
|
load_data_with_foreign_keys(
|
|
32
|
-
command,
|
|
67
|
+
command,
|
|
68
|
+
model,
|
|
69
|
+
yaml_data,
|
|
70
|
+
foreign_keys,
|
|
71
|
+
foreign_key_models,
|
|
72
|
+
validators,
|
|
73
|
+
verbose,
|
|
74
|
+
log_context=model_name or model.__name__,
|
|
33
75
|
)
|
|
34
76
|
|
|
35
77
|
|
|
36
78
|
def load_data_with_foreign_keys(
|
|
37
|
-
command,
|
|
79
|
+
command,
|
|
80
|
+
model,
|
|
81
|
+
yaml_data,
|
|
82
|
+
foreign_keys,
|
|
83
|
+
foreign_key_models,
|
|
84
|
+
validators,
|
|
85
|
+
verbose,
|
|
86
|
+
log_context=None,
|
|
38
87
|
):
|
|
39
88
|
"""
|
|
40
89
|
Load YAML data into Django model instances with FK and M2M support.
|
|
41
|
-
|
|
90
|
+
|
|
42
91
|
Processes each YAML entry to create or update a model instance. For each entry, the
|
|
43
92
|
function extracts field data and uses the presence of a 'name' field to decide whether
|
|
44
93
|
to update an existing instance or create a new one. Foreign key fields listed in
|
|
@@ -46,34 +95,49 @@ def load_data_with_foreign_keys(
|
|
|
46
95
|
contains a list, it is treated as a many-to-many relationship and the corresponding
|
|
47
96
|
objects are set after the instance is saved. Missing or unresolved foreign keys trigger
|
|
48
97
|
warnings if verbose output is enabled.
|
|
49
|
-
|
|
98
|
+
|
|
50
99
|
Parameters:
|
|
51
100
|
model: The Django model class representing the data.
|
|
52
101
|
yaml_data: A list of dictionaries representing YAML entries.
|
|
53
102
|
foreign_keys: A list of foreign key field names to process from each entry.
|
|
54
103
|
foreign_key_models: The corresponding Django model classes for each foreign key.
|
|
104
|
+
validators: A sequence of callables invoked before persisting each entry. Each
|
|
105
|
+
validator receives a shallow copy of the entry's field dictionary along with
|
|
106
|
+
the original entry and model for context.
|
|
55
107
|
verbose: If True, prints detailed output and warnings during processing.
|
|
108
|
+
log_context: Label that identifies the source dataset inside the warning log.
|
|
56
109
|
"""
|
|
110
|
+
context_label = log_context or getattr(model, "__name__", "dataloader")
|
|
111
|
+
|
|
57
112
|
for entry in yaml_data:
|
|
58
|
-
|
|
113
|
+
raw_fields = entry.get("fields", {})
|
|
114
|
+
|
|
115
|
+
for validator in validators:
|
|
116
|
+
validator(dict(raw_fields), entry=entry, model=model)
|
|
117
|
+
|
|
118
|
+
fields = dict(raw_fields)
|
|
59
119
|
name = fields.pop("name", None)
|
|
60
120
|
|
|
121
|
+
if getattr(model, "_meta", None) and model._meta.model_name == "requirement":
|
|
122
|
+
requirement_types = fields.get("requirement_types", [])
|
|
123
|
+
|
|
124
|
+
if not requirement_types:
|
|
125
|
+
raise ValueError(f"Requirement '{name}' must define at least one requirement_types entry.")
|
|
61
126
|
|
|
62
127
|
####################
|
|
63
|
-
#TODO REMOVE AFTER TRANSLATION SUPPORT IS ADDED
|
|
64
|
-
SKIP_NAMES=[
|
|
128
|
+
# TODO REMOVE AFTER TRANSLATION SUPPORT IS ADDED
|
|
129
|
+
SKIP_NAMES = [
|
|
65
130
|
"name_de", # German name, not used
|
|
66
131
|
"name_en", # English name, not used
|
|
67
132
|
"description_de", # German description
|
|
68
133
|
"description_en", # English description
|
|
69
134
|
]
|
|
70
135
|
|
|
71
|
-
|
|
72
136
|
# Remove fields that are not needed
|
|
73
137
|
for skip_name in SKIP_NAMES:
|
|
74
138
|
if skip_name in fields:
|
|
75
139
|
fields.pop(skip_name)
|
|
76
|
-
########################
|
|
140
|
+
# ########################
|
|
77
141
|
|
|
78
142
|
m2m_relationships = {} # Store many-to-many relationships
|
|
79
143
|
# print(entry)
|
|
@@ -88,12 +152,12 @@ def load_data_with_foreign_keys(
|
|
|
88
152
|
|
|
89
153
|
# Ensure the foreign key exists
|
|
90
154
|
if target_keys is None:
|
|
91
|
-
|
|
92
|
-
command
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
155
|
+
_record_warning(
|
|
156
|
+
command,
|
|
157
|
+
f"Foreign key {fk_field} not found in fields",
|
|
158
|
+
verbose,
|
|
159
|
+
context_label,
|
|
160
|
+
)
|
|
97
161
|
continue # Skip if no foreign key provided
|
|
98
162
|
|
|
99
163
|
# Process many-to-many fields or foreign keys
|
|
@@ -103,29 +167,69 @@ def load_data_with_foreign_keys(
|
|
|
103
167
|
try:
|
|
104
168
|
obj = fk_model.objects.get_by_natural_key(key)
|
|
105
169
|
except ObjectDoesNotExist:
|
|
106
|
-
|
|
107
|
-
command
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
170
|
+
_record_warning(
|
|
171
|
+
command,
|
|
172
|
+
f"{fk_model.__name__} with key {key} not found",
|
|
173
|
+
verbose,
|
|
174
|
+
context_label,
|
|
175
|
+
)
|
|
112
176
|
continue
|
|
113
177
|
related_objects.append(obj)
|
|
114
178
|
m2m_relationships[fk_field] = related_objects
|
|
115
179
|
else: # Single foreign key relationship
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
180
|
+
if model.__name__ == "ModelMeta" and fk_field == "labelset":
|
|
181
|
+
labelset_version = fields.pop("labelset_version", None)
|
|
182
|
+
|
|
183
|
+
if isinstance(target_keys, (tuple, list)):
|
|
184
|
+
labelset_name = target_keys[0] if target_keys else None
|
|
185
|
+
if len(target_keys) > 1 and labelset_version in (None, ""):
|
|
186
|
+
labelset_version = target_keys[1]
|
|
187
|
+
else:
|
|
188
|
+
labelset_name = target_keys
|
|
189
|
+
|
|
190
|
+
if not labelset_name:
|
|
191
|
+
_record_warning(
|
|
192
|
+
command,
|
|
193
|
+
"LabelSet name missing for ModelMeta entry",
|
|
194
|
+
verbose,
|
|
195
|
+
context_label,
|
|
196
|
+
)
|
|
197
|
+
continue
|
|
198
|
+
|
|
199
|
+
queryset = fk_model.objects.filter(name=labelset_name)
|
|
200
|
+
if labelset_version not in (None, "", -1):
|
|
201
|
+
try:
|
|
202
|
+
version_value = int(labelset_version)
|
|
203
|
+
except (TypeError, ValueError):
|
|
204
|
+
version_value = labelset_version
|
|
205
|
+
queryset = queryset.filter(version=version_value)
|
|
206
|
+
|
|
207
|
+
obj = queryset.order_by("-version").first()
|
|
208
|
+
if obj is None:
|
|
209
|
+
_record_warning(
|
|
210
|
+
command,
|
|
211
|
+
f"LabelSet '{labelset_name}' (version={labelset_version}) not found",
|
|
212
|
+
verbose,
|
|
213
|
+
context_label,
|
|
124
214
|
)
|
|
125
|
-
|
|
126
|
-
|
|
215
|
+
continue
|
|
216
|
+
fields[fk_field] = obj
|
|
217
|
+
else:
|
|
218
|
+
try:
|
|
219
|
+
obj = fk_model.objects.get_by_natural_key(target_keys)
|
|
220
|
+
except ObjectDoesNotExist:
|
|
221
|
+
_record_warning(
|
|
222
|
+
command,
|
|
223
|
+
f"{fk_model.__name__} with key {target_keys} not found",
|
|
224
|
+
verbose,
|
|
225
|
+
context_label,
|
|
226
|
+
)
|
|
227
|
+
continue
|
|
228
|
+
fields[fk_field] = obj
|
|
127
229
|
|
|
128
230
|
# Create or update the main object (avoid update_or_create to prevent SQLite locks)
|
|
231
|
+
version_value = fields.get("version")
|
|
232
|
+
|
|
129
233
|
def _save_instance():
|
|
130
234
|
if name is None:
|
|
131
235
|
# Try to find an existing object by all provided fields
|
|
@@ -136,7 +240,11 @@ def load_data_with_foreign_keys(
|
|
|
136
240
|
else:
|
|
137
241
|
created = False
|
|
138
242
|
else:
|
|
139
|
-
|
|
243
|
+
lookup_kwargs = {"name": name}
|
|
244
|
+
if model.__name__ == "LabelSet" and version_value is not None:
|
|
245
|
+
lookup_kwargs["version"] = version_value
|
|
246
|
+
|
|
247
|
+
obj = model.objects.filter(**lookup_kwargs).first()
|
|
140
248
|
if obj is None:
|
|
141
249
|
obj = model.objects.create(name=name, **fields)
|
|
142
250
|
created = True
|
|
@@ -157,9 +265,7 @@ def load_data_with_foreign_keys(
|
|
|
157
265
|
obj, created = _save_instance()
|
|
158
266
|
|
|
159
267
|
if created and verbose:
|
|
160
|
-
command.stdout.write(
|
|
161
|
-
command.style.SUCCESS(f"Created {model.__name__} {name}")
|
|
162
|
-
)
|
|
268
|
+
command.stdout.write(command.style.SUCCESS(f"Created {model.__name__} {name}"))
|
|
163
269
|
elif verbose:
|
|
164
270
|
pass
|
|
165
271
|
|
|
@@ -168,8 +274,4 @@ def load_data_with_foreign_keys(
|
|
|
168
274
|
if related_objs: # Only set if there are objects to set
|
|
169
275
|
getattr(obj, field_name).set(related_objs)
|
|
170
276
|
if verbose:
|
|
171
|
-
command.stdout.write(
|
|
172
|
-
command.style.SUCCESS(
|
|
173
|
-
f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"
|
|
174
|
-
)
|
|
175
|
-
)
|
|
277
|
+
command.stdout.write(command.style.SUCCESS(f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"))
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from endoreg_db.models.administration.center import center
|
|
3
|
+
|
|
4
|
+
# Start process with interactive pipes
|
|
5
|
+
proc = subprocess.Popen(
|
|
6
|
+
["python3", "-i"], # or your target program
|
|
7
|
+
stdin=subprocess.PIPE,
|
|
8
|
+
stdout=subprocess.PIPE,
|
|
9
|
+
stderr=subprocess.STDOUT,
|
|
10
|
+
text=True,
|
|
11
|
+
bufsize=1
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
proc.stdin.write("print('Trying to extract...')\n")
|
|
15
|
+
proc.stdin.flush()
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
subprocess.run(["python", "manage.py", "load_center_data"], check=True)
|
|
19
|
+
proc.stdout.write("print('found center')")
|
|
20
|
+
except subprocess.CalledProcessError as e:
|
|
21
|
+
proc.stdout.write("print('Didn't find center. Please add it to endoreg_db luxnix or via export DEFAULT_CENTER")
|
|
22
|
+
# """
|
|
23
|
+
# Future Implementation using dialogue
|
|
24
|
+
#"""
|
|
25
|
+
# # Send commands as if from terminal
|
|
26
|
+
# proc.stdin.write("print('You dont have a default center set up yet. Please enter one here.')\n\nprint('Rule: use_this_format_and_connect_words_with_underscore')")
|
|
27
|
+
# proc.stdin.flush()
|
|
28
|
+
|
|
29
|
+
# # Read responses
|
|
30
|
+
# for _ in range(3):
|
|
31
|
+
# line = proc.stdout.readline()
|
|
32
|
+
# print("Selected >>", line.strip())
|
endoreg_db/utils/names.py
CHANGED
|
@@ -55,22 +55,28 @@ def create_mock_patient_name(gender: str) -> tuple[str, str]:
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def guess_name_gender(name: str) -> str:
|
|
58
|
-
"""
|
|
59
|
-
Guesses the gender for a given name by using a gender detector and retrieving the corresponding Gender model instance.
|
|
60
|
-
Parameters:
|
|
61
|
-
name (str): The name for which the gender is to be determined.
|
|
62
|
-
Returns:
|
|
63
|
-
Gender: The Gender object corresponding to the detected gender name.
|
|
64
|
-
Raises:
|
|
65
|
-
Gender.DoesNotExist: If no Gender object matching the detected gender is found.
|
|
66
|
-
Exception: For any other exceptions that occur during gender detection or database lookup.
|
|
67
|
-
"""
|
|
58
|
+
"""Return a normalized gender slug (male|female|unknown) for the given name.
|
|
68
59
|
|
|
69
|
-
|
|
60
|
+
Uses :mod:`gender_guesser` to infer gender without touching the database. All
|
|
61
|
+
detector outputs are mapped onto our canonical slugs so callers can perform
|
|
62
|
+
their own model lookups or fall back safely.
|
|
63
|
+
"""
|
|
70
64
|
|
|
71
65
|
detector = gender_detector.Detector(case_sensitive=False)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
try:
|
|
67
|
+
detected = detector.get_gender(name or "")
|
|
68
|
+
except Exception: # pragma: no cover - defensive, detector is pure-Python
|
|
69
|
+
detected = None
|
|
70
|
+
|
|
71
|
+
if not detected:
|
|
72
|
+
return "unknown"
|
|
73
|
+
|
|
74
|
+
normalized = detected.lower()
|
|
75
|
+
if normalized in {"male", "mostly_male"}:
|
|
76
|
+
return "male"
|
|
77
|
+
if normalized in {"female", "mostly_female"}:
|
|
78
|
+
return "female"
|
|
79
|
+
|
|
80
|
+
# gender-guesser returns "andy" for androgynous names and "unknown" for
|
|
81
|
+
# unrecognised inputs – both should map to our "unknown" slug.
|
|
82
|
+
return "unknown"
|
endoreg_db/utils/paths.py
CHANGED
|
@@ -7,89 +7,153 @@ It provides a unified dictionary 'data_paths' for accessing all path objects.
|
|
|
7
7
|
|
|
8
8
|
from logging import getLogger
|
|
9
9
|
|
|
10
|
-
from sphinx.search import no
|
|
11
10
|
logger = getLogger(__name__)
|
|
12
11
|
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
from typing import Dict
|
|
15
12
|
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Dict, Union
|
|
15
|
+
|
|
16
16
|
# Alternative approach using env_path helper, deprecated since monorepo setup. Alright for single install, env is always preferred.
|
|
17
|
-
#from endoreg_db.config.env import env_path
|
|
17
|
+
# from endoreg_db.config.env import env_path
|
|
18
18
|
|
|
19
|
-
STORAGE_DIR = Path(os.getenv("STORAGE_DIR", "
|
|
19
|
+
STORAGE_DIR = Path(os.getenv("STORAGE_DIR", "internal_storage"))
|
|
20
20
|
|
|
21
21
|
storage_dir_env = os.getenv("STORAGE_DIR")
|
|
22
22
|
if storage_dir_env is None:
|
|
23
23
|
raise RuntimeError("STORAGE_DIR environment variable is not set.")
|
|
24
|
-
|
|
25
|
-
STORAGE_DIR =
|
|
24
|
+
storage_dir = Path(storage_dir_env)
|
|
25
|
+
STORAGE_DIR = storage_dir
|
|
26
26
|
if not STORAGE_DIR.exists():
|
|
27
27
|
STORAGE_DIR.mkdir(parents=True, exist_ok=True)
|
|
28
28
|
|
|
29
|
+
|
|
29
30
|
PREFIX_RAW = "raw_"
|
|
31
|
+
io_dir_env = Path(os.getenv("IO_DIR", "data"))
|
|
32
|
+
io_dir = Path(io_dir_env)
|
|
33
|
+
IO_DIR = io_dir
|
|
34
|
+
if not STORAGE_DIR.exists():
|
|
35
|
+
STORAGE_DIR.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Data dropoff folders - These can be external, determined by IO_DIR (Default: set to desktop root folder of OS)
|
|
39
|
+
|
|
30
40
|
IMPORT_DIR_NAME = "import"
|
|
31
41
|
EXPORT_DIR_NAME = "export"
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
IMPORT_DIR = IO_DIR / IMPORT_DIR_NAME # data/import
|
|
44
|
+
EXPORT_DIR = IO_DIR / EXPORT_DIR_NAME # data/export
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
IMPORT_VIDEO_DIR_NAME = "video_import"
|
|
48
|
+
REPORT_IMPORT_DIR_NAME = "report_import"
|
|
49
|
+
|
|
50
|
+
VIDEO_EXPORT_DIR_NAME = "video_export"
|
|
51
|
+
REPORT_EXPORT_DIR_NAME = "report_export"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
IMPORT_VIDEO_DIR = IMPORT_DIR / IMPORT_VIDEO_DIR_NAME
|
|
55
|
+
IMPORT_REPORT_DIR = IMPORT_DIR / REPORT_IMPORT_DIR_NAME
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
VIDEO_EXPORT_DIR = EXPORT_DIR / VIDEO_EXPORT_DIR_NAME
|
|
59
|
+
REPORT_EXPORT_DIR = EXPORT_DIR / REPORT_EXPORT_DIR_NAME
|
|
60
|
+
|
|
61
|
+
# Document Dir
|
|
62
|
+
|
|
63
|
+
DOCUMENT_DIR = STORAGE_DIR / "documents"
|
|
64
|
+
|
|
65
|
+
# After initial import, files will remain here.
|
|
66
|
+
|
|
67
|
+
TRANSCODING_DIR = STORAGE_DIR /"temp"
|
|
68
|
+
|
|
69
|
+
SENSITIVE_VIDEO_DIR_NAME = "sensitive_videos"
|
|
70
|
+
SENSITIVE_REPORT_DIR_NAME = "sensitive_reports"
|
|
71
|
+
ANONYM_VIDEO_DIR_NAME = "processed_videos_final"
|
|
72
|
+
ANONYM_REPORT_DIR_NAME = "processed_reports_final"
|
|
73
|
+
|
|
74
|
+
RAW_FRAME_DIR_NAME = f"{PREFIX_RAW}frames"
|
|
35
75
|
FRAME_DIR_NAME = "frames"
|
|
36
|
-
PDF_DIR_NAME = "pdfs" # Changed from reports
|
|
37
76
|
WEIGHTS_DIR_NAME = "model_weights"
|
|
38
77
|
EXAMINATION_DIR_NAME = "examinations"
|
|
39
78
|
|
|
40
|
-
RAW_VIDEO_DIR_NAME = f"{PREFIX_RAW}videos"
|
|
41
|
-
RAW_FRAME_DIR_NAME = f"{PREFIX_RAW}frames"
|
|
42
|
-
RAW_PDF_DIR_NAME = f"{PREFIX_RAW}pdfs" # Changed from reports
|
|
43
|
-
|
|
44
79
|
# Define data subdirectories under STORAGE_DIR
|
|
45
|
-
|
|
46
|
-
|
|
80
|
+
ANONYM_VIDEO_DIR = STORAGE_DIR / ANONYM_VIDEO_DIR_NAME
|
|
81
|
+
SENSITIVE_VIDEO_DIR = STORAGE_DIR / SENSITIVE_VIDEO_DIR_NAME
|
|
82
|
+
ANONYM_REPORT_DIR = STORAGE_DIR / ANONYM_REPORT_DIR_NAME
|
|
83
|
+
SENSITIVE_REPORT_DIR = STORAGE_DIR / SENSITIVE_REPORT_DIR_NAME
|
|
84
|
+
|
|
47
85
|
FRAME_DIR = STORAGE_DIR / FRAME_DIR_NAME
|
|
48
|
-
|
|
86
|
+
|
|
87
|
+
|
|
49
88
|
WEIGHTS_DIR = STORAGE_DIR / WEIGHTS_DIR_NAME
|
|
50
|
-
RAW_VIDEO_DIR = STORAGE_DIR / RAW_VIDEO_DIR_NAME
|
|
51
89
|
RAW_FRAME_DIR = STORAGE_DIR / RAW_FRAME_DIR_NAME
|
|
52
|
-
RAW_PDF_DIR = STORAGE_DIR / RAW_PDF_DIR_NAME # Changed
|
|
53
90
|
|
|
54
|
-
IMPORT_DIR = STORAGE_DIR / IMPORT_DIR_NAME
|
|
55
|
-
VIDEO_IMPORT_DIR = IMPORT_DIR / VIDEO_DIR_NAME
|
|
56
|
-
FRAME_IMPORT_DIR = IMPORT_DIR / FRAME_DIR_NAME
|
|
57
|
-
PDF_IMPORT_DIR = IMPORT_DIR / PDF_DIR_NAME # Changed
|
|
58
91
|
WEIGHTS_IMPORT_DIR = IMPORT_DIR / WEIGHTS_DIR_NAME
|
|
92
|
+
WEIGHTS_EXPORT_DIR = EXPORT_DIR / WEIGHTS_DIR_NAME
|
|
93
|
+
|
|
94
|
+
FRAME_IMPORT_DIR = IMPORT_DIR / FRAME_DIR_NAME
|
|
59
95
|
|
|
60
|
-
|
|
96
|
+
FRAME_EXPORT_DIR = EXPORT_DIR / FRAME_DIR_NAME
|
|
61
97
|
|
|
62
|
-
|
|
98
|
+
|
|
99
|
+
data_paths: Dict[str, Path] = {
|
|
63
100
|
"storage": STORAGE_DIR,
|
|
64
|
-
"video": VIDEO_DIR,
|
|
65
|
-
"anonym_video": ANONYM_VIDEO_DIR, # Added
|
|
66
|
-
"frame": FRAME_DIR,
|
|
67
|
-
"pdf": PDF_DIR, # Changed
|
|
68
101
|
"import": IMPORT_DIR,
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
102
|
+
"import_video": IMPORT_VIDEO_DIR,
|
|
103
|
+
"sensitive_video": SENSITIVE_VIDEO_DIR,
|
|
104
|
+
"sensitive_report": SENSITIVE_REPORT_DIR,
|
|
105
|
+
"anonym_video": ANONYM_VIDEO_DIR,
|
|
106
|
+
"anonym_report": ANONYM_REPORT_DIR,
|
|
107
|
+
"import_frame": FRAME_IMPORT_DIR,
|
|
108
|
+
"import_report": IMPORT_REPORT_DIR,
|
|
73
109
|
"raw_frame": RAW_FRAME_DIR,
|
|
74
|
-
"raw_pdf": RAW_PDF_DIR, # Changed
|
|
75
110
|
"weights": WEIGHTS_DIR,
|
|
76
111
|
"weights_import": WEIGHTS_IMPORT_DIR,
|
|
77
112
|
"export": EXPORT_DIR,
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"frame_export":
|
|
81
|
-
"pdf_export": EXPORT_DIR / PDF_DIR_NAME, # Changed
|
|
113
|
+
"report_export": REPORT_EXPORT_DIR,
|
|
114
|
+
"video_export": VIDEO_EXPORT_DIR,
|
|
115
|
+
"frame_export": FRAME_EXPORT_DIR,
|
|
82
116
|
"weights_export": EXPORT_DIR / WEIGHTS_DIR_NAME,
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"raw_pdf_export": EXPORT_DIR / RAW_PDF_DIR_NAME, # Changed
|
|
117
|
+
"transcoding": TRANSCODING_DIR,
|
|
118
|
+
"frame": FRAME_DIR,
|
|
119
|
+
"documents": DOCUMENT_DIR
|
|
87
120
|
}
|
|
88
121
|
|
|
89
122
|
logger.info(f"Storage directory: {STORAGE_DIR.resolve()}")
|
|
90
123
|
logger.info(f"Export directory: {EXPORT_DIR.resolve()}")
|
|
91
124
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
for key, path in data_paths.items():
|
|
126
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
127
|
+
|
|
128
|
+
logger.info(f"{key.capitalize()} directory: {path.resolve()}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def to_storage_relative(path: Union[str, Path]) -> str:
|
|
132
|
+
"""
|
|
133
|
+
Return a path string relative to STORAGE_DIR, suitable for Django FileField.name.
|
|
134
|
+
|
|
135
|
+
- If `path` is inside STORAGE_DIR (absolute or contains STORAGE_DIR as prefix),
|
|
136
|
+
we strip the STORAGE_DIR prefix and return the relative part.
|
|
137
|
+
- If `path` is outside STORAGE_DIR, we return it as a string unchanged
|
|
138
|
+
(caller can decide what to do).
|
|
139
|
+
"""
|
|
140
|
+
# Normalize input to Path
|
|
141
|
+
p = Path(path)
|
|
142
|
+
|
|
143
|
+
# Resolve absolute path for comparison
|
|
144
|
+
storage_root = STORAGE_DIR.resolve()
|
|
145
|
+
|
|
146
|
+
if not p.is_absolute():
|
|
147
|
+
# Resolve relative path against current working directory
|
|
148
|
+
# (in tests, cwd should be project root, so this still lands under STORAGE_DIR)
|
|
149
|
+
p = p.resolve()
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
rel = p.relative_to(storage_root)
|
|
153
|
+
except ValueError:
|
|
154
|
+
# Not under STORAGE_DIR – probably already a relative name or external.
|
|
155
|
+
# In that case, just return the string representation as-is.
|
|
156
|
+
return str(path)
|
|
157
|
+
|
|
158
|
+
# Use POSIX-style separators for Django FileField
|
|
159
|
+
return rel.as_posix()
|
endoreg_db/utils/permissions.py
CHANGED
|
@@ -7,7 +7,7 @@ the DEBUG setting and other environment configurations.
|
|
|
7
7
|
|
|
8
8
|
from django.conf import settings
|
|
9
9
|
from rest_framework.permissions import IsAuthenticated, AllowAny, BasePermission
|
|
10
|
-
from rest_framework.decorators import permission_classes as drf_permission_classes
|
|
10
|
+
#from rest_framework.decorators import permission_classes as drf_permission_classes
|
|
11
11
|
from functools import wraps
|
|
12
12
|
import logging
|
|
13
13
|
import os
|
|
@@ -50,6 +50,7 @@ def dynamic_permission_classes(force_auth=None):
|
|
|
50
50
|
- None: Use environment-based logic (default)
|
|
51
51
|
"""
|
|
52
52
|
def decorator(view_func):
|
|
53
|
+
from rest_framework.decorators import permission_classes as drf_permission_classes
|
|
53
54
|
@wraps(view_func)
|
|
54
55
|
def wrapper(*args, **kwargs):
|
|
55
56
|
return view_func(*args, **kwargs)
|
|
@@ -154,7 +154,7 @@ At this point in the pipeline:
|
|
|
154
154
|
`VideoFile.processed_file`
|
|
155
155
|
- Video hash is calculated and saved in:
|
|
156
156
|
`VideoFile.processed_video_hash`
|
|
157
|
-
- `VideoState.
|
|
157
|
+
- `VideoState.state.anonymization_status.mark_anonymized()`
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
@@ -20,7 +20,7 @@ DEFAULT_DIR = Path(__file__).resolve().parent.parent.parent.parent / "data/study
|
|
|
20
20
|
CENTER_NAME = os.environ.get("CENTER_NAME", "university_hospital_wuerzburg")
|
|
21
21
|
ENDOSCOPY_PROCESSOR_NAME = os.environ.get("ENDOSCOPY_PROCESSOR_NAME", "olympus_cv_1500")
|
|
22
22
|
MODEL_NAME = "image_multilabel_classification_colonoscopy_default"
|
|
23
|
-
MODEL_WEIGHTS_PATH = "./tests/assets/colo_segmentation_RegNetX800MF_6.
|
|
23
|
+
MODEL_WEIGHTS_PATH = "./tests/assets/colo_segmentation_RegNetX800MF_6.safetensors"
|
|
24
24
|
ic(DEFAULT_DIR)
|
|
25
25
|
|
|
26
26
|
|