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
|
@@ -4,20 +4,24 @@ including versioning, configuration, and associated weights files.
|
|
|
4
4
|
Logic is primarily handled in model_meta_logic.py.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import
|
|
8
|
-
# Removed shutil import, now in logic
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Type, cast
|
|
9
8
|
|
|
10
|
-
from django.db import models
|
|
11
9
|
from django.core.validators import FileExtensionValidator
|
|
10
|
+
|
|
11
|
+
# Removed shutil import, now in logic
|
|
12
|
+
from django.db import models
|
|
13
|
+
|
|
12
14
|
# Removed torch import, now in logic
|
|
13
15
|
# from torch import nn
|
|
16
|
+
from ..utils import WEIGHTS_DIR
|
|
14
17
|
|
|
15
|
-
from ..utils import WEIGHTS_DIR, STORAGE_DIR
|
|
16
18
|
# Import logic functions
|
|
17
19
|
from . import model_meta_logic as logic
|
|
18
20
|
|
|
19
21
|
if TYPE_CHECKING:
|
|
20
|
-
from
|
|
22
|
+
from django.db.models.fields.files import FieldFile
|
|
23
|
+
|
|
24
|
+
from endoreg_db.models import AiModel, LabelSet # pylint: disable=import-outside-toplevel
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
class ModelMetaManager(models.Manager):
|
|
@@ -26,7 +30,24 @@ class ModelMetaManager(models.Manager):
|
|
|
26
30
|
|
|
27
31
|
Provides methods for retrieving ModelMeta instances using natural keys.
|
|
28
32
|
"""
|
|
29
|
-
|
|
33
|
+
|
|
34
|
+
def get_by_natural_key(self, name: str, version: str, model_name: str) -> "ModelMeta":
|
|
35
|
+
"""
|
|
36
|
+
Retrieves a ModelMeta instance using its natural key.
|
|
37
|
+
|
|
38
|
+
This method returns the ModelMeta whose name, version, and associated model's name
|
|
39
|
+
match the provided natural key. It is primarily used to support Django's natural key
|
|
40
|
+
serialization during data import/export and deserialization processes.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
name: The name of the ModelMeta.
|
|
44
|
+
version: The version identifier of the ModelMeta.
|
|
45
|
+
model_name: The name of the associated AiModel.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
The ModelMeta object corresponding to the given natural key.
|
|
49
|
+
"""
|
|
50
|
+
return self.get(name=name, version=version, model__name=model_name)
|
|
30
51
|
|
|
31
52
|
|
|
32
53
|
class ModelMeta(models.Model):
|
|
@@ -50,7 +71,6 @@ class ModelMeta(models.Model):
|
|
|
50
71
|
on_delete=models.CASCADE,
|
|
51
72
|
related_name="metadata_versions",
|
|
52
73
|
help_text="The base AI model architecture this metadata belongs to.",
|
|
53
|
-
|
|
54
74
|
)
|
|
55
75
|
|
|
56
76
|
# --- Model Configuration ---
|
|
@@ -60,15 +80,13 @@ class ModelMeta(models.Model):
|
|
|
60
80
|
related_name="model_metadata",
|
|
61
81
|
help_text="The set of labels this model version predicts.",
|
|
62
82
|
)
|
|
63
|
-
activation = models.CharField(
|
|
64
|
-
max_length=50, default="sigmoid", help_text="Output activation function (e.g., 'sigmoid', 'softmax', 'none')."
|
|
65
|
-
)
|
|
83
|
+
activation = models.CharField(max_length=50, default="sigmoid", help_text="Output activation function (e.g., 'sigmoid', 'softmax', 'none').")
|
|
66
84
|
weights = models.FileField(
|
|
67
85
|
upload_to=WEIGHTS_DIR.name, # Use .name for relative path
|
|
68
|
-
validators=[FileExtensionValidator(allowed_extensions=["
|
|
86
|
+
validators=[FileExtensionValidator(allowed_extensions=["safetensors", "pth", "pt"])],
|
|
69
87
|
null=True,
|
|
70
88
|
blank=True,
|
|
71
|
-
help_text="Path to the model weights file (.
|
|
89
|
+
help_text="Path to the model weights file (.safetensors), relative to MEDIA_ROOT.",
|
|
72
90
|
)
|
|
73
91
|
|
|
74
92
|
# --- Normalization and Input Shape ---
|
|
@@ -84,9 +102,7 @@ class ModelMeta(models.Model):
|
|
|
84
102
|
)
|
|
85
103
|
size_x = models.IntegerField(default=716, help_text="Expected input image width.")
|
|
86
104
|
size_y = models.IntegerField(default=716, help_text="Expected input image height.")
|
|
87
|
-
axes = models.CharField(
|
|
88
|
-
max_length=10, default="2,0,1", help_text="Comma-separated target axis order (e.g., '2,0,1' for CHW)."
|
|
89
|
-
)
|
|
105
|
+
axes = models.CharField(max_length=10, default="2,0,1", help_text="Comma-separated target axis order (e.g., '2,0,1' for CHW).")
|
|
90
106
|
|
|
91
107
|
# --- Inference Parameters ---
|
|
92
108
|
batchsize = models.IntegerField(default=16, help_text="Default batch size for inference.")
|
|
@@ -96,17 +112,21 @@ class ModelMeta(models.Model):
|
|
|
96
112
|
description = models.TextField(blank=True, null=True, help_text="Optional description.")
|
|
97
113
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
98
114
|
|
|
99
|
-
|
|
100
115
|
objects = ModelMetaManager()
|
|
101
116
|
|
|
102
117
|
# --- Type Hinting for Related Fields ---
|
|
103
118
|
if TYPE_CHECKING:
|
|
104
|
-
labelset: "LabelSet"
|
|
105
|
-
model: "AiModel" # Corrected from ai_model to match field name
|
|
119
|
+
labelset: models.ForeignKey["LabelSet"]
|
|
120
|
+
model: models.ForeignKey["AiModel"] # Corrected from ai_model to match field name
|
|
121
|
+
weights = cast(FieldFile, weights)
|
|
106
122
|
|
|
107
123
|
class Meta:
|
|
108
124
|
"""Metadata options for the ModelMeta model."""
|
|
109
|
-
|
|
125
|
+
|
|
126
|
+
unique_together = (("name", "version", "model"),)
|
|
127
|
+
ordering = ["-date_created"]
|
|
128
|
+
verbose_name = "Model Metadata"
|
|
129
|
+
verbose_name_plural = "Model Metadata"
|
|
110
130
|
|
|
111
131
|
@classmethod
|
|
112
132
|
def create_from_file(
|
|
@@ -115,6 +135,7 @@ class ModelMeta(models.Model):
|
|
|
115
135
|
model_name: str,
|
|
116
136
|
labelset_name: str,
|
|
117
137
|
weights_file: str,
|
|
138
|
+
labelset_version: Optional[int | str] = None,
|
|
118
139
|
requested_version: Optional[str] = None,
|
|
119
140
|
bump_if_exists: bool = False,
|
|
120
141
|
**kwargs: Any,
|
|
@@ -124,23 +145,34 @@ class ModelMeta(models.Model):
|
|
|
124
145
|
"""
|
|
125
146
|
# Delegate to logic function, passing the class (cls)
|
|
126
147
|
return logic.create_from_file_logic(
|
|
127
|
-
cls,
|
|
128
|
-
|
|
148
|
+
cls,
|
|
149
|
+
meta_name,
|
|
150
|
+
model_name,
|
|
151
|
+
labelset_name,
|
|
152
|
+
weights_file,
|
|
153
|
+
labelset_version=labelset_version,
|
|
154
|
+
requested_version=requested_version,
|
|
155
|
+
bump_if_exists=bump_if_exists,
|
|
156
|
+
**kwargs,
|
|
129
157
|
)
|
|
130
|
-
|
|
158
|
+
|
|
131
159
|
@classmethod
|
|
132
160
|
def setup_default_from_huggingface(
|
|
133
161
|
cls: Type["ModelMeta"],
|
|
134
162
|
model_id: str = "wg-lux/colo_segmentation_RegNetX800MF_base",
|
|
135
163
|
labelset_name: Optional[str] = None,
|
|
164
|
+
labelset_version: Optional[int | str] = None,
|
|
136
165
|
) -> "ModelMeta":
|
|
137
166
|
"""
|
|
138
167
|
Downloads a pretrained model from Hugging Face and initializes ModelMeta automatically.
|
|
139
168
|
"""
|
|
140
169
|
# If labelset_name is not provided, handle default logic here if needed
|
|
141
|
-
return logic.setup_default_from_huggingface_logic(
|
|
142
|
-
|
|
143
|
-
|
|
170
|
+
return logic.setup_default_from_huggingface_logic(
|
|
171
|
+
cls,
|
|
172
|
+
model_id=model_id,
|
|
173
|
+
labelset_name=labelset_name,
|
|
174
|
+
labelset_version=labelset_version,
|
|
175
|
+
)
|
|
144
176
|
|
|
145
177
|
@classmethod
|
|
146
178
|
def get_latest_version_number(cls: Type["ModelMeta"], meta_name: str, model_name: str) -> int:
|
|
@@ -150,9 +182,8 @@ class ModelMeta(models.Model):
|
|
|
150
182
|
# Delegate to logic function
|
|
151
183
|
return logic.get_latest_version_number_logic(cls, meta_name, model_name)
|
|
152
184
|
|
|
153
|
-
|
|
154
185
|
@staticmethod
|
|
155
|
-
def get_activation_function(activation_name: str)
|
|
186
|
+
def get_activation_function(activation_name: str):
|
|
156
187
|
"""
|
|
157
188
|
Retrieves a PyTorch activation function using external logic.
|
|
158
189
|
"""
|
|
@@ -166,12 +197,12 @@ class ModelMeta(models.Model):
|
|
|
166
197
|
# Delegate to logic function
|
|
167
198
|
return logic.get_inference_dataset_config_logic(self)
|
|
168
199
|
|
|
169
|
-
def natural_key(self) -> Tuple[str, str]:
|
|
200
|
+
def natural_key(self) -> Tuple[str, str, str]:
|
|
170
201
|
"""
|
|
171
202
|
Returns the natural key for serialization.
|
|
172
203
|
"""
|
|
173
204
|
# Assuming natural key is based on name and version, linked to model name
|
|
174
|
-
return (self.name, self.version, self.model.natural_key())
|
|
205
|
+
return (self.name, self.version, self.model.natural_key()[0])
|
|
175
206
|
|
|
176
207
|
def __str__(self) -> str:
|
|
177
208
|
"""String representation of the ModelMeta instance."""
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import shutil
|
|
2
2
|
from logging import getLogger
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Optional, Type
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Iterable, Optional, Type
|
|
5
5
|
|
|
6
|
-
from django.core.files import File
|
|
7
6
|
from django.db import transaction
|
|
8
7
|
from huggingface_hub import hf_hub_download
|
|
9
8
|
|
|
@@ -62,6 +61,7 @@ def create_from_file_logic(
|
|
|
62
61
|
model_name: str,
|
|
63
62
|
labelset_name: str,
|
|
64
63
|
weights_file: str,
|
|
64
|
+
labelset_version: Optional[int | str] = None,
|
|
65
65
|
requested_version: Optional[str] = None,
|
|
66
66
|
bump_if_exists: bool = False,
|
|
67
67
|
**kwargs: Any,
|
|
@@ -77,10 +77,23 @@ def create_from_file_logic(
|
|
|
77
77
|
except AiModel.DoesNotExist as exc:
|
|
78
78
|
raise ValueError(f"AiModel with name '{model_name}' not found.") from exc
|
|
79
79
|
|
|
80
|
+
labelset_qs = LabelSet.objects.filter(name=labelset_name)
|
|
81
|
+
if labelset_version not in (None, "", -1):
|
|
82
|
+
try:
|
|
83
|
+
version_value = int(labelset_version)
|
|
84
|
+
except (TypeError, ValueError):
|
|
85
|
+
version_value = labelset_version
|
|
86
|
+
labelset_qs = labelset_qs.filter(version=version_value)
|
|
87
|
+
|
|
80
88
|
try:
|
|
81
|
-
label_set =
|
|
89
|
+
label_set = labelset_qs.get()
|
|
82
90
|
except LabelSet.DoesNotExist as exc:
|
|
83
|
-
raise ValueError(f"LabelSet with
|
|
91
|
+
raise ValueError(f"LabelSet '{labelset_name}' with version '{labelset_version}' not found.") from exc
|
|
92
|
+
except LabelSet.MultipleObjectsReturned:
|
|
93
|
+
# Prefer the highest version when duplicates remain and no explicit version requested
|
|
94
|
+
label_set = labelset_qs.order_by("-version").first()
|
|
95
|
+
if not label_set:
|
|
96
|
+
raise ValueError(f"LabelSet '{labelset_name}' could not be resolved.")
|
|
84
97
|
|
|
85
98
|
# --- Determine Version ---
|
|
86
99
|
target_version: str
|
|
@@ -172,16 +185,92 @@ def get_activation_function_logic(activation_name: str):
|
|
|
172
185
|
|
|
173
186
|
|
|
174
187
|
# Placeholder for get_inference_dataset_config_logic
|
|
188
|
+
def _normalise_scalar_sequence(value: Any) -> str | None:
|
|
189
|
+
"""Serialise sequence-like values into the canonical comma-separated form."""
|
|
190
|
+
|
|
191
|
+
if value in (None, ""):
|
|
192
|
+
return None
|
|
193
|
+
if isinstance(value, str):
|
|
194
|
+
return value
|
|
195
|
+
if isinstance(value, (list, tuple)):
|
|
196
|
+
return ",".join(str(item) for item in value)
|
|
197
|
+
return str(value)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _parse_float_sequence(value: Any, *, fallback: Iterable[float]) -> list[float]:
|
|
201
|
+
"""Coerce stored normalisation strings/iterables to float lists."""
|
|
202
|
+
|
|
203
|
+
if value in (None, ""):
|
|
204
|
+
return list(fallback)
|
|
205
|
+
|
|
206
|
+
tokens: Iterable[Any]
|
|
207
|
+
if isinstance(value, str):
|
|
208
|
+
tokens = [tok.strip() for tok in value.split(",") if tok.strip()]
|
|
209
|
+
elif isinstance(value, (list, tuple)):
|
|
210
|
+
tokens = value
|
|
211
|
+
else:
|
|
212
|
+
tokens = [value]
|
|
213
|
+
|
|
214
|
+
parsed: list[float] = []
|
|
215
|
+
for token in tokens:
|
|
216
|
+
try:
|
|
217
|
+
parsed.append(float(token))
|
|
218
|
+
except (TypeError, ValueError):
|
|
219
|
+
logger.warning("Failed to parse normalisation value %r; using fallback", token)
|
|
220
|
+
return list(fallback)
|
|
221
|
+
|
|
222
|
+
return parsed or list(fallback)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _parse_axes(axes_value: str | Iterable[Any]) -> list[int]:
|
|
226
|
+
"""Normalise stored axis notation to integer indices.
|
|
227
|
+
|
|
228
|
+
Historic metadata mixes numeric strings ("2,0,1") with symbolic tokens
|
|
229
|
+
("CHW", "HWC"). The inference code ultimately expects a list of integers,
|
|
230
|
+
so we coerce common symbolic forms to their numeric equivalents and fall
|
|
231
|
+
back to sequential indices when the format is unknown.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
if not axes_value:
|
|
235
|
+
return [0, 1, 2]
|
|
236
|
+
|
|
237
|
+
if isinstance(axes_value, str):
|
|
238
|
+
token_source = axes_value.strip()
|
|
239
|
+
if "," in token_source:
|
|
240
|
+
tokens = [token.strip() for token in token_source.split(",") if token.strip()]
|
|
241
|
+
else:
|
|
242
|
+
tokens = [char for char in token_source if char.strip()]
|
|
243
|
+
else:
|
|
244
|
+
tokens = [str(token).strip() for token in axes_value if str(token).strip()]
|
|
245
|
+
|
|
246
|
+
symbol_map = {"C": 0, "H": 1, "W": 2}
|
|
247
|
+
parsed_axes: list[int] = []
|
|
248
|
+
|
|
249
|
+
for idx, token in enumerate(tokens):
|
|
250
|
+
normalised = token.upper()
|
|
251
|
+
if normalised.lstrip("+-").isdigit():
|
|
252
|
+
parsed_axes.append(int(normalised))
|
|
253
|
+
elif normalised in symbol_map:
|
|
254
|
+
parsed_axes.append(symbol_map[normalised])
|
|
255
|
+
else:
|
|
256
|
+
logger.warning("Unknown axes token '%s'; defaulting to index order", token)
|
|
257
|
+
parsed_axes.append(idx)
|
|
258
|
+
|
|
259
|
+
return parsed_axes or [0, 1, 2]
|
|
260
|
+
|
|
261
|
+
|
|
175
262
|
def get_inference_dataset_config_logic(model_meta: "ModelMeta") -> dict:
|
|
176
263
|
# This would typically extract relevant fields from model_meta
|
|
177
264
|
# for configuring a dataset during inference
|
|
265
|
+
DEFAULT_MEAN = (0.45211223, 0.27139644, 0.19264949)
|
|
266
|
+
DEFAULT_STD = (0.31418097, 0.21088019, 0.16059452)
|
|
267
|
+
|
|
178
268
|
return {
|
|
179
|
-
"mean":
|
|
180
|
-
"std":
|
|
181
|
-
"size_y": model_meta.size_y
|
|
182
|
-
"size_x": model_meta.size_x
|
|
183
|
-
"axes":
|
|
184
|
-
# Add other relevant config like normalization type, etc.
|
|
269
|
+
"mean": _parse_float_sequence(model_meta.mean, fallback=DEFAULT_MEAN),
|
|
270
|
+
"std": _parse_float_sequence(model_meta.std, fallback=DEFAULT_STD),
|
|
271
|
+
"size_y": int(model_meta.size_y) if model_meta.size_y else 716,
|
|
272
|
+
"size_x": int(model_meta.size_x) if model_meta.size_x else 716,
|
|
273
|
+
"axes": _parse_axes(model_meta.axes),
|
|
185
274
|
}
|
|
186
275
|
|
|
187
276
|
|
|
@@ -301,18 +390,26 @@ def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
|
|
|
301
390
|
}
|
|
302
391
|
|
|
303
392
|
|
|
304
|
-
def setup_default_from_huggingface_logic(
|
|
393
|
+
def setup_default_from_huggingface_logic(
|
|
394
|
+
cls,
|
|
395
|
+
model_id: str,
|
|
396
|
+
labelset_name: str | None = None,
|
|
397
|
+
labelset_version: Optional[int | str] = None,
|
|
398
|
+
):
|
|
305
399
|
"""
|
|
306
400
|
Downloads model weights from Hugging Face and auto-fills ModelMeta fields.
|
|
307
401
|
"""
|
|
308
402
|
meta = infer_default_model_meta_from_hf(model_id)
|
|
309
403
|
|
|
310
|
-
# Download weights
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
404
|
+
# Download safetensor weights; raise a clear error if unavailable
|
|
405
|
+
try:
|
|
406
|
+
weights_path = hf_hub_download(
|
|
407
|
+
repo_id=model_id,
|
|
408
|
+
filename="colo_segmentation_RegNetX800MF_base.safetensors",
|
|
409
|
+
local_dir=WEIGHTS_DIR,
|
|
410
|
+
)
|
|
411
|
+
except Exception as exc: # pragma: no cover - network errors
|
|
412
|
+
raise RuntimeError("Failed to download safetensor weights from Hugging Face; ensure the repository provides a .safetensors artifact.") from exc
|
|
316
413
|
|
|
317
414
|
ai_model, _ = AiModel.objects.get_or_create(name=meta["name"])
|
|
318
415
|
if not labelset_name:
|
|
@@ -320,7 +417,16 @@ def setup_default_from_huggingface_logic(cls, model_id: str, labelset_name: str
|
|
|
320
417
|
if not labelset:
|
|
321
418
|
raise ValueError("No labelset found and no labelset_name provided")
|
|
322
419
|
else:
|
|
323
|
-
|
|
420
|
+
labelset_qs = LabelSet.objects.filter(name=labelset_name)
|
|
421
|
+
if labelset_version not in (None, "", -1):
|
|
422
|
+
try:
|
|
423
|
+
version_value = int(labelset_version)
|
|
424
|
+
except (TypeError, ValueError):
|
|
425
|
+
version_value = labelset_version
|
|
426
|
+
labelset_qs = labelset_qs.filter(version=version_value)
|
|
427
|
+
labelset = labelset_qs.order_by("-version").first()
|
|
428
|
+
if not labelset:
|
|
429
|
+
raise ValueError(f"LabelSet '{labelset_name}' with version '{labelset_version}' not found.")
|
|
324
430
|
|
|
325
431
|
ModelMeta = _get_model_meta_class()
|
|
326
432
|
model_meta = ModelMeta.objects.filter(name=meta["name"], model=ai_model).first()
|
|
@@ -333,6 +439,7 @@ def setup_default_from_huggingface_logic(cls, model_id: str, labelset_name: str
|
|
|
333
439
|
meta_name=meta["name"],
|
|
334
440
|
model_name=ai_model.name,
|
|
335
441
|
labelset_name=labelset.name,
|
|
442
|
+
labelset_version=labelset.version,
|
|
336
443
|
weights_file=weights_path,
|
|
337
444
|
activation=meta["activation"],
|
|
338
445
|
mean=meta["mean"],
|
|
@@ -1,51 +1,59 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import TYPE_CHECKING, cast
|
|
2
|
+
|
|
2
3
|
from django.core.files import File
|
|
3
|
-
from
|
|
4
|
+
from django.db import models
|
|
4
5
|
|
|
5
6
|
if TYPE_CHECKING:
|
|
6
7
|
from ..media.pdf.report_reader.report_reader_flag import ReportReaderFlag
|
|
7
8
|
|
|
9
|
+
|
|
8
10
|
class PdfType(models.Model):
|
|
9
11
|
"""
|
|
10
|
-
Defines a specific type or format of
|
|
12
|
+
Defines a specific type or format of report report, linking to flags used for parsing.
|
|
11
13
|
|
|
12
|
-
Used to configure how different
|
|
14
|
+
Used to configure how different report report layouts are processed.
|
|
13
15
|
"""
|
|
16
|
+
|
|
14
17
|
name = models.CharField(max_length=255)
|
|
15
18
|
|
|
16
19
|
patient_info_line = models.ForeignKey(
|
|
17
20
|
"ReportReaderFlag",
|
|
18
|
-
related_name="pdf_type_patient_info_line",
|
|
19
|
-
on_delete=models.CASCADE
|
|
21
|
+
related_name="pdf_type_patient_info_line",
|
|
22
|
+
on_delete=models.CASCADE,
|
|
20
23
|
)
|
|
21
24
|
endoscope_info_line = models.ForeignKey(
|
|
22
25
|
"ReportReaderFlag",
|
|
23
|
-
related_name="pdf_type_endoscopy_info_line",
|
|
26
|
+
related_name="pdf_type_endoscopy_info_line",
|
|
24
27
|
on_delete=models.CASCADE,
|
|
25
28
|
)
|
|
26
29
|
examiner_info_line = models.ForeignKey(
|
|
27
30
|
"ReportReaderFlag",
|
|
28
|
-
related_name="pdf_type_examiner_info_line",
|
|
29
|
-
on_delete=models.CASCADE
|
|
31
|
+
related_name="pdf_type_examiner_info_line",
|
|
32
|
+
on_delete=models.CASCADE,
|
|
30
33
|
)
|
|
31
34
|
cut_off_above_lines = models.ManyToManyField(
|
|
32
35
|
"ReportReaderFlag",
|
|
33
|
-
related_name="pdf_type_cut_off_above_lines",
|
|
36
|
+
related_name="pdf_type_cut_off_above_lines",
|
|
34
37
|
)
|
|
35
38
|
cut_off_below_lines = models.ManyToManyField(
|
|
36
39
|
"ReportReaderFlag",
|
|
37
|
-
related_name="pdf_type_cut_off_below_lines",
|
|
40
|
+
related_name="pdf_type_cut_off_below_lines",
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
if TYPE_CHECKING:
|
|
41
|
-
patient_info_line: "ReportReaderFlag"
|
|
42
|
-
endoscope_info_line: "ReportReaderFlag"
|
|
43
|
-
examiner_info_line: "ReportReaderFlag"
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
patient_info_line: models.ForeignKey["ReportReaderFlag"]
|
|
45
|
+
endoscope_info_line: models.ForeignKey["ReportReaderFlag"]
|
|
46
|
+
examiner_info_line: models.ForeignKey["ReportReaderFlag"]
|
|
47
|
+
|
|
48
|
+
cut_off_above_lines = cast(
|
|
49
|
+
models.manager.RelatedManager["ReportReaderFlag"], cut_off_above_lines
|
|
50
|
+
)
|
|
51
|
+
cut_off_below_lines = cast(
|
|
52
|
+
models.manager.RelatedManager["ReportReaderFlag"], cut_off_below_lines
|
|
53
|
+
)
|
|
46
54
|
|
|
47
55
|
def __str__(self):
|
|
48
|
-
"""Returns a string summary of the
|
|
56
|
+
"""Returns a string summary of the report type and its associated flags."""
|
|
49
57
|
summary = f"{self.name}"
|
|
50
58
|
# add lines to summary
|
|
51
59
|
summary += f"\nPatient Info Line: {self.patient_info_line.value}"
|
|
@@ -53,7 +61,7 @@ class PdfType(models.Model):
|
|
|
53
61
|
summary += f"\nExaminer Info Line: {self.examiner_info_line.value}"
|
|
54
62
|
summary += f"\nCut Off Above Lines: {[_.value for _ in self.cut_off_above_lines.all()]}"
|
|
55
63
|
summary += f"\nCut Off Below Lines: {[_.value for _ in self.cut_off_below_lines.all()]}"
|
|
56
|
-
|
|
64
|
+
|
|
57
65
|
return summary
|
|
58
66
|
|
|
59
67
|
@classmethod
|
|
@@ -61,26 +69,25 @@ class PdfType(models.Model):
|
|
|
61
69
|
"""Returns a default PdfType instance, typically used as a fallback."""
|
|
62
70
|
return PdfType.objects.get(name="ukw-endoscopy-examination-report-generic")
|
|
63
71
|
|
|
72
|
+
|
|
64
73
|
class PdfMeta(models.Model):
|
|
65
74
|
"""
|
|
66
|
-
Stores metadata associated with a specific
|
|
75
|
+
Stores metadata associated with a specific report document file.
|
|
67
76
|
"""
|
|
77
|
+
|
|
68
78
|
pdf_type = models.ForeignKey(PdfType, on_delete=models.CASCADE)
|
|
69
79
|
date = models.DateField()
|
|
70
80
|
time = models.TimeField()
|
|
71
81
|
pdf_hash = models.CharField(max_length=255, unique=True)
|
|
72
82
|
|
|
73
|
-
if TYPE_CHECKING:
|
|
74
|
-
pdf_type: "PdfType"
|
|
75
|
-
|
|
76
83
|
def __str__(self):
|
|
77
|
-
"""Returns the
|
|
84
|
+
"""Returns the report hash as its string representation."""
|
|
78
85
|
return str(self.pdf_hash)
|
|
79
86
|
|
|
80
87
|
@classmethod
|
|
81
88
|
def create_from_file(cls, pdf_file):
|
|
82
89
|
"""
|
|
83
|
-
Creates a PdfMeta instance from a
|
|
90
|
+
Creates a PdfMeta instance from a report file object.
|
|
84
91
|
Note: This implementation seems incomplete; it doesn't extract hash, date, time, or type.
|
|
85
92
|
"""
|
|
86
93
|
pdf_file = File(pdf_file)
|