endoreg-db 0.8.8.9__py3-none-any.whl → 0.8.9.10__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/admin.py +10 -5
- endoreg_db/apps.py +4 -7
- endoreg_db/authz/auth.py +1 -0
- endoreg_db/authz/backends.py +1 -1
- endoreg_db/authz/management/commands/list_routes.py +2 -0
- endoreg_db/authz/middleware.py +8 -7
- endoreg_db/authz/permissions.py +21 -10
- endoreg_db/authz/policy.py +14 -19
- endoreg_db/authz/views_auth.py +14 -10
- endoreg_db/codemods/rename_datetime_fields.py +8 -1
- endoreg_db/exceptions.py +5 -2
- endoreg_db/forms/__init__.py +0 -1
- endoreg_db/forms/examination_form.py +4 -3
- endoreg_db/forms/patient_finding_intervention_form.py +30 -8
- endoreg_db/forms/patient_form.py +9 -13
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/settings/__init__.py +4 -1
- endoreg_db/forms/unit.py +2 -1
- endoreg_db/helpers/count_db.py +17 -14
- endoreg_db/helpers/default_objects.py +2 -1
- endoreg_db/helpers/download_segmentation_model.py +4 -3
- endoreg_db/helpers/interact.py +0 -5
- endoreg_db/helpers/test_video_helper.py +33 -25
- endoreg_db/import_files/__init__.py +1 -1
- endoreg_db/import_files/context/__init__.py +1 -1
- endoreg_db/import_files/context/default_sensitive_meta.py +11 -9
- endoreg_db/import_files/context/ensure_center.py +4 -4
- endoreg_db/import_files/context/file_lock.py +3 -3
- endoreg_db/import_files/context/import_context.py +11 -12
- endoreg_db/import_files/context/validate_directories.py +1 -0
- endoreg_db/import_files/file_storage/create_report_file.py +57 -34
- endoreg_db/import_files/file_storage/create_video_file.py +64 -35
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +5 -2
- endoreg_db/import_files/file_storage/state_management.py +146 -83
- endoreg_db/import_files/file_storage/storage.py +5 -1
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +24 -19
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +3 -3
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +18 -18
- endoreg_db/import_files/pseudonymization/k_anonymity.py +8 -9
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +16 -5
- endoreg_db/import_files/report_import_service.py +36 -30
- endoreg_db/import_files/video_import_service.py +27 -23
- endoreg_db/logger_conf.py +56 -40
- endoreg_db/management/__init__.py +1 -1
- endoreg_db/management/commands/__init__.py +1 -1
- endoreg_db/management/commands/check_auth.py +45 -38
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +53 -2
- endoreg_db/management/commands/create_multilabel_model_meta.py +54 -19
- endoreg_db/management/commands/fix_missing_patient_data.py +105 -71
- endoreg_db/management/commands/fix_video_paths.py +75 -54
- endoreg_db/management/commands/import_report.py +1 -3
- endoreg_db/management/commands/list_routes.py +2 -0
- endoreg_db/management/commands/load_ai_model_data.py +8 -2
- endoreg_db/management/commands/load_ai_model_label_data.py +0 -1
- endoreg_db/management/commands/load_center_data.py +3 -3
- endoreg_db/management/commands/load_distribution_data.py +35 -38
- endoreg_db/management/commands/load_endoscope_data.py +0 -3
- endoreg_db/management/commands/load_examination_data.py +20 -4
- endoreg_db/management/commands/load_finding_data.py +18 -3
- endoreg_db/management/commands/load_gender_data.py +17 -24
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +95 -85
- endoreg_db/management/commands/load_information_source.py +0 -3
- endoreg_db/management/commands/load_lab_value_data.py +14 -3
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_name_data.py +1 -2
- endoreg_db/management/commands/load_pdf_type_data.py +4 -8
- endoreg_db/management/commands/load_profession_data.py +0 -1
- endoreg_db/management/commands/load_report_reader_flag_data.py +0 -4
- endoreg_db/management/commands/load_requirement_data.py +6 -2
- endoreg_db/management/commands/load_unit_data.py +0 -4
- endoreg_db/management/commands/load_user_groups.py +5 -7
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +22 -16
- endoreg_db/management/commands/setup_endoreg_db.py +110 -32
- endoreg_db/management/commands/storage_management.py +14 -8
- endoreg_db/management/commands/summarize_db_content.py +154 -63
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +82 -50
- endoreg_db/management/commands/video_validation.py +4 -6
- endoreg_db/migrations/0001_initial.py +112 -63
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +8 -0
- endoreg_db/models/administration/ai/active_model.py +5 -5
- endoreg_db/models/administration/ai/ai_model.py +41 -18
- endoreg_db/models/administration/ai/model_type.py +1 -0
- endoreg_db/models/administration/case/case.py +22 -22
- endoreg_db/models/administration/center/__init__.py +5 -5
- endoreg_db/models/administration/center/center.py +6 -2
- endoreg_db/models/administration/center/center_resource.py +18 -4
- endoreg_db/models/administration/center/center_shift.py +3 -1
- endoreg_db/models/administration/center/center_waste.py +6 -2
- endoreg_db/models/administration/person/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/employee_type.py +3 -1
- endoreg_db/models/administration/person/examiner/__init__.py +1 -1
- endoreg_db/models/administration/person/examiner/examiner.py +10 -2
- endoreg_db/models/administration/person/names/first_name.py +6 -4
- endoreg_db/models/administration/person/names/last_name.py +4 -3
- endoreg_db/models/administration/person/patient/__init__.py +1 -1
- endoreg_db/models/administration/person/patient/patient.py +0 -1
- endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
- endoreg_db/models/administration/person/person.py +1 -1
- endoreg_db/models/administration/product/__init__.py +7 -6
- endoreg_db/models/administration/product/product.py +6 -2
- endoreg_db/models/administration/product/product_group.py +9 -7
- endoreg_db/models/administration/product/product_material.py +9 -2
- endoreg_db/models/administration/product/reference_product.py +64 -15
- endoreg_db/models/administration/qualification/qualification.py +3 -1
- endoreg_db/models/administration/shift/shift.py +3 -1
- endoreg_db/models/administration/shift/shift_type.py +12 -4
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +1 -1
- endoreg_db/models/label/label.py +10 -2
- endoreg_db/models/label/label_set.py +3 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
- endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
- endoreg_db/models/media/__init__.py +12 -5
- endoreg_db/models/media/frame/__init__.py +1 -1
- endoreg_db/models/media/frame/frame.py +34 -8
- endoreg_db/models/media/pdf/__init__.py +2 -1
- endoreg_db/models/media/pdf/raw_pdf.py +11 -4
- endoreg_db/models/media/pdf/report_file.py +6 -2
- endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
- endoreg_db/models/media/video/create_from_file.py +20 -41
- endoreg_db/models/media/video/pipe_1.py +75 -30
- endoreg_db/models/media/video/pipe_2.py +37 -12
- endoreg_db/models/media/video/video_file.py +36 -24
- endoreg_db/models/media/video/video_file_ai.py +235 -70
- endoreg_db/models/media/video/video_file_anonymize.py +240 -65
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
- endoreg_db/models/media/video/video_file_io.py +85 -33
- endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
- endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
- endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
- endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
- endoreg_db/models/media/video/video_file_segments.py +118 -27
- endoreg_db/models/media/video/video_metadata.py +25 -6
- endoreg_db/models/media/video/video_processing.py +54 -15
- endoreg_db/models/medical/__init__.py +3 -13
- endoreg_db/models/medical/contraindication/__init__.py +3 -1
- endoreg_db/models/medical/disease.py +18 -6
- endoreg_db/models/medical/event.py +6 -2
- endoreg_db/models/medical/examination/__init__.py +5 -1
- endoreg_db/models/medical/examination/examination.py +22 -6
- endoreg_db/models/medical/examination/examination_indication.py +23 -7
- endoreg_db/models/medical/examination/examination_time.py +6 -2
- endoreg_db/models/medical/finding/__init__.py +3 -1
- endoreg_db/models/medical/finding/finding.py +37 -12
- endoreg_db/models/medical/finding/finding_classification.py +27 -8
- endoreg_db/models/medical/finding/finding_intervention.py +19 -6
- endoreg_db/models/medical/finding/finding_type.py +3 -1
- endoreg_db/models/medical/hardware/__init__.py +1 -1
- endoreg_db/models/medical/hardware/endoscope.py +14 -2
- endoreg_db/models/medical/laboratory/__init__.py +1 -1
- endoreg_db/models/medical/laboratory/lab_value.py +139 -39
- endoreg_db/models/medical/medication/__init__.py +7 -3
- endoreg_db/models/medical/medication/medication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
- endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
- endoreg_db/models/medical/medication/medication_schedule.py +3 -1
- endoreg_db/models/medical/patient/__init__.py +2 -10
- endoreg_db/models/medical/patient/medication_examples.py +3 -14
- endoreg_db/models/medical/patient/patient_disease.py +17 -5
- endoreg_db/models/medical/patient/patient_event.py +12 -4
- endoreg_db/models/medical/patient/patient_examination.py +52 -15
- endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
- endoreg_db/models/medical/patient/patient_finding.py +105 -29
- endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
- endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
- endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
- endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
- endoreg_db/models/medical/patient/patient_medication.py +25 -7
- endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
- endoreg_db/models/metadata/model_meta.py +40 -12
- endoreg_db/models/metadata/model_meta_logic.py +51 -16
- endoreg_db/models/metadata/sensitive_meta.py +65 -28
- endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
- endoreg_db/models/metadata/video_meta.py +146 -39
- endoreg_db/models/metadata/video_prediction_logic.py +70 -21
- endoreg_db/models/metadata/video_prediction_meta.py +80 -27
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +10 -10
- endoreg_db/models/other/distribution/__init__.py +9 -7
- endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
- endoreg_db/models/other/emission/__init__.py +1 -1
- endoreg_db/models/other/emission/emission_factor.py +9 -3
- endoreg_db/models/other/information_source.py +15 -5
- endoreg_db/models/other/material.py +3 -1
- endoreg_db/models/other/transport_route.py +3 -1
- endoreg_db/models/other/unit.py +6 -2
- endoreg_db/models/report/report.py +0 -1
- endoreg_db/models/requirement/requirement.py +84 -27
- endoreg_db/models/requirement/requirement_error.py +5 -6
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
- endoreg_db/models/requirement/requirement_operator.py +28 -8
- endoreg_db/models/requirement/requirement_set.py +34 -11
- endoreg_db/models/state/__init__.py +1 -0
- endoreg_db/models/state/audit_ledger.py +9 -2
- endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +0 -1
- endoreg_db/models/state/video.py +2 -3
- endoreg_db/models/utils.py +4 -2
- endoreg_db/queries/__init__.py +2 -6
- endoreg_db/queries/annotations/__init__.py +1 -3
- endoreg_db/queries/annotations/legacy.py +37 -26
- endoreg_db/root_urls.py +3 -4
- endoreg_db/schemas/examination_evaluation.py +3 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/administration/__init__.py +1 -2
- endoreg_db/serializers/administration/ai/__init__.py +0 -1
- endoreg_db/serializers/administration/ai/active_model.py +3 -1
- endoreg_db/serializers/administration/ai/ai_model.py +5 -3
- endoreg_db/serializers/administration/ai/model_type.py +3 -1
- endoreg_db/serializers/administration/center.py +7 -2
- endoreg_db/serializers/administration/gender.py +4 -2
- endoreg_db/serializers/anonymization.py +13 -13
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
- endoreg_db/serializers/examination/__init__.py +1 -1
- endoreg_db/serializers/examination/base.py +12 -13
- endoreg_db/serializers/examination/dropdown.py +6 -7
- endoreg_db/serializers/examination_serializer.py +3 -6
- endoreg_db/serializers/finding/__init__.py +1 -1
- endoreg_db/serializers/finding/finding.py +14 -7
- endoreg_db/serializers/finding_classification/__init__.py +3 -3
- endoreg_db/serializers/finding_classification/choice.py +3 -3
- endoreg_db/serializers/finding_classification/classification.py +2 -4
- endoreg_db/serializers/label_video_segment/__init__.py +5 -3
- endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
- endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
- endoreg_db/serializers/meta/__init__.py +1 -2
- endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
- endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
- endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
- endoreg_db/serializers/misc/__init__.py +2 -2
- endoreg_db/serializers/misc/file_overview.py +11 -7
- endoreg_db/serializers/misc/stats.py +10 -8
- endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
- endoreg_db/serializers/misc/upload_job.py +32 -29
- endoreg_db/serializers/patient/__init__.py +2 -1
- endoreg_db/serializers/patient/patient.py +32 -15
- endoreg_db/serializers/patient/patient_dropdown.py +11 -3
- endoreg_db/serializers/patient_examination/__init__.py +1 -1
- endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
- endoreg_db/serializers/patient_finding/__init__.py +1 -1
- endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
- endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
- endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
- endoreg_db/serializers/pdf/__init__.py +1 -3
- endoreg_db/serializers/requirements/requirement_schema.py +1 -6
- endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
- endoreg_db/serializers/video/__init__.py +2 -2
- endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
- endoreg_db/serializers/video/video_file_brief.py +6 -2
- endoreg_db/serializers/video/video_file_detail.py +36 -23
- endoreg_db/serializers/video/video_file_list.py +4 -2
- endoreg_db/serializers/video/video_processing_history.py +54 -50
- endoreg_db/services/__init__.py +1 -1
- endoreg_db/services/anonymization.py +2 -2
- endoreg_db/services/examination_evaluation.py +40 -17
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/polling_coordinator.py +101 -70
- endoreg_db/services/pseudonym_service.py +27 -22
- endoreg_db/services/report_import.py +6 -3
- endoreg_db/services/segment_sync.py +75 -59
- endoreg_db/services/video_import.py +6 -7
- endoreg_db/urls/__init__.py +2 -2
- endoreg_db/urls/ai.py +7 -25
- endoreg_db/urls/anonymization.py +61 -15
- endoreg_db/urls/auth.py +4 -4
- endoreg_db/urls/classification.py +4 -9
- endoreg_db/urls/examination.py +27 -18
- endoreg_db/urls/media.py +27 -34
- endoreg_db/urls/patient.py +11 -7
- endoreg_db/urls/requirements.py +3 -1
- endoreg_db/urls/root_urls.py +2 -3
- endoreg_db/urls/stats.py +24 -16
- endoreg_db/urls/upload.py +3 -11
- endoreg_db/utils/__init__.py +14 -15
- endoreg_db/utils/ai/__init__.py +1 -1
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +2 -1
- endoreg_db/utils/ai/inference_dataset.py +14 -15
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
- endoreg_db/utils/ai/predict.py +4 -4
- endoreg_db/utils/ai/preprocess.py +19 -11
- endoreg_db/utils/calc_duration_seconds.py +4 -4
- endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
- endoreg_db/utils/check_video_files.py +74 -47
- endoreg_db/utils/cropping.py +10 -9
- endoreg_db/utils/dataloader.py +11 -3
- endoreg_db/utils/dates.py +3 -4
- endoreg_db/utils/defaults/set_default_center.py +7 -6
- endoreg_db/utils/env.py +6 -2
- endoreg_db/utils/extract_specific_frames.py +24 -9
- endoreg_db/utils/file_operations.py +30 -18
- endoreg_db/utils/fix_video_path_direct.py +57 -41
- endoreg_db/utils/frame_anonymization_utils.py +157 -157
- endoreg_db/utils/hashs.py +3 -18
- endoreg_db/utils/links/requirement_link.py +96 -52
- endoreg_db/utils/ocr.py +30 -25
- endoreg_db/utils/operation_log.py +61 -0
- endoreg_db/utils/parse_and_generate_yaml.py +12 -13
- endoreg_db/utils/paths.py +6 -6
- endoreg_db/utils/permissions.py +40 -24
- endoreg_db/utils/pipelines/process_video_dir.py +50 -26
- endoreg_db/utils/product/sum_emissions.py +5 -3
- endoreg_db/utils/product/sum_weights.py +4 -2
- endoreg_db/utils/pydantic_models/__init__.py +3 -4
- endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
- endoreg_db/utils/setup_config.py +21 -5
- endoreg_db/utils/storage.py +3 -1
- endoreg_db/utils/translation.py +19 -15
- endoreg_db/utils/uuid.py +1 -0
- endoreg_db/utils/validate_endo_roi.py +12 -4
- endoreg_db/utils/validate_subcategory_dict.py +26 -24
- endoreg_db/utils/validate_video_detailed.py +207 -149
- endoreg_db/utils/video/__init__.py +7 -3
- endoreg_db/utils/video/extract_frames.py +30 -18
- endoreg_db/utils/video/ffmpeg_wrapper.py +217 -52
- endoreg_db/utils/video/names.py +11 -6
- endoreg_db/utils/video/streaming_processor.py +175 -101
- endoreg_db/utils/video/video_splitter.py +30 -19
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
- endoreg_db/views/__init__.py +0 -20
- endoreg_db/views/anonymization/__init__.py +6 -2
- endoreg_db/views/anonymization/media_management.py +2 -6
- endoreg_db/views/anonymization/overview.py +34 -1
- endoreg_db/views/anonymization/validate.py +79 -18
- endoreg_db/views/auth/__init__.py +1 -1
- endoreg_db/views/auth/keycloak.py +16 -14
- endoreg_db/views/examination/__init__.py +12 -15
- endoreg_db/views/examination/examination.py +5 -5
- endoreg_db/views/examination/examination_manifest_cache.py +5 -5
- endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
- endoreg_db/views/examination/get_finding_classifications.py +9 -7
- endoreg_db/views/examination/get_findings.py +8 -10
- endoreg_db/views/examination/get_instruments.py +3 -2
- endoreg_db/views/examination/get_interventions.py +1 -1
- endoreg_db/views/finding/__init__.py +2 -2
- endoreg_db/views/finding/finding.py +58 -54
- endoreg_db/views/finding/get_classifications.py +1 -1
- endoreg_db/views/finding/get_interventions.py +1 -1
- endoreg_db/views/finding_classification/__init__.py +5 -5
- endoreg_db/views/finding_classification/finding_classification.py +5 -6
- endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
- endoreg_db/views/media/__init__.py +13 -13
- endoreg_db/views/media/pdf_media.py +9 -9
- endoreg_db/views/media/sensitive_metadata.py +10 -7
- endoreg_db/views/media/video_media.py +4 -4
- endoreg_db/views/meta/__init__.py +1 -1
- endoreg_db/views/meta/sensitive_meta_list.py +20 -22
- endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
- endoreg_db/views/misc/__init__.py +6 -34
- endoreg_db/views/misc/center.py +2 -1
- endoreg_db/views/misc/csrf.py +2 -1
- endoreg_db/views/misc/gender.py +2 -1
- endoreg_db/views/misc/stats.py +141 -106
- endoreg_db/views/patient/__init__.py +1 -3
- endoreg_db/views/patient/patient.py +141 -99
- endoreg_db/views/patient_examination/__init__.py +5 -5
- endoreg_db/views/patient_examination/patient_examination.py +43 -42
- endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
- endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
- endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
- endoreg_db/views/patient_examination/video.py +114 -80
- endoreg_db/views/patient_finding/__init__.py +1 -1
- endoreg_db/views/patient_finding/patient_finding.py +17 -10
- endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
- endoreg_db/views/patient_finding_classification/__init__.py +1 -1
- endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
- endoreg_db/views/report/reimport.py +1 -1
- endoreg_db/views/report/report_stream.py +5 -8
- endoreg_db/views/requirement/__init__.py +2 -1
- endoreg_db/views/requirement/evaluate.py +7 -9
- endoreg_db/views/requirement/lookup.py +2 -3
- endoreg_db/views/requirement/lookup_store.py +0 -1
- endoreg_db/views/requirement/requirement_utils.py +2 -4
- endoreg_db/views/stats/__init__.py +4 -4
- endoreg_db/views/stats/stats_views.py +152 -115
- endoreg_db/views/video/__init__.py +18 -27
- endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
- endoreg_db/views/{ai → video/ai}/label.py +20 -16
- endoreg_db/views/video/correction.py +5 -6
- endoreg_db/views/video/reimport.py +134 -99
- endoreg_db/views/video/segments_crud.py +134 -44
- endoreg_db/views/video/video_apply_mask.py +13 -12
- endoreg_db/views/video/video_correction.py +2 -1
- endoreg_db/views/video/video_download_processed.py +15 -15
- endoreg_db/views/video/video_meta_stats.py +7 -6
- endoreg_db/views/video/video_processing_history.py +3 -2
- endoreg_db/views/video/video_remove_frames.py +13 -12
- endoreg_db/views/video/video_stream.py +110 -82
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +436 -433
- endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +0 -119
- endoreg_db/management/commands/import_fallback_video.py +0 -203
- endoreg_db/management/commands/import_video.py +0 -422
- endoreg_db/management/commands/import_video_with_classification.py +0 -367
- endoreg_db/models/media/processing_history/processing_history.py +0 -96
- endoreg_db/serializers/label/__init__.py +0 -7
- endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
- endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
- endoreg_db/services/__old/pdf_import.py +0 -1487
- endoreg_db/services/__old/video_import.py +0 -1306
- endoreg_db/tasks/upload_tasks.py +0 -216
- endoreg_db/tasks/video_ingest.py +0 -161
- endoreg_db/tasks/video_processing_tasks.py +0 -327
- endoreg_db/views/misc/translation.py +0 -182
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Django management command to validate video file existence and accessibility.
|
|
3
3
|
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
4
8
|
from django.core.management.base import BaseCommand
|
|
5
9
|
|
|
6
10
|
from endoreg_db.models import VideoFile
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
import logging
|
|
9
11
|
|
|
10
12
|
logger = logging.getLogger(__name__)
|
|
11
13
|
|
|
12
14
|
# TODO Review if this is still used. Delete if not.
|
|
13
15
|
|
|
16
|
+
|
|
14
17
|
class Command(BaseCommand):
|
|
15
|
-
help =
|
|
18
|
+
help = "Validate video file existence and accessibility"
|
|
16
19
|
|
|
17
20
|
def add_arguments(self, parser):
|
|
18
21
|
parser.add_argument(
|
|
19
|
-
|
|
22
|
+
"--video-id",
|
|
20
23
|
type=int,
|
|
21
|
-
help=
|
|
24
|
+
help="Check specific video ID",
|
|
22
25
|
)
|
|
23
26
|
parser.add_argument(
|
|
24
|
-
|
|
25
|
-
action=
|
|
26
|
-
help=
|
|
27
|
+
"--verbose",
|
|
28
|
+
action="store_true",
|
|
29
|
+
help="Enable verbose output",
|
|
27
30
|
)
|
|
28
31
|
|
|
29
32
|
def handle(self, *args, **options):
|
|
30
33
|
"""Validate video files and their accessibility."""
|
|
31
|
-
verbose = options[
|
|
32
|
-
video_id = options.get(
|
|
33
|
-
fix_missing = options[
|
|
34
|
+
verbose = options["verbose"]
|
|
35
|
+
video_id = options.get("video_id")
|
|
36
|
+
fix_missing = options["fix_missing", False]
|
|
34
37
|
|
|
35
38
|
if verbose:
|
|
36
39
|
self.stdout.write(self.style.SUCCESS("Starting video validation..."))
|
|
@@ -41,7 +44,9 @@ class Command(BaseCommand):
|
|
|
41
44
|
videos = [VideoFile.objects.get(pk=video_id)]
|
|
42
45
|
self.stdout.write(f"Checking specific video ID: {video_id}")
|
|
43
46
|
except VideoFile.DoesNotExist:
|
|
44
|
-
self.stdout.write(
|
|
47
|
+
self.stdout.write(
|
|
48
|
+
self.style.ERROR(f"Video with ID {video_id} not found")
|
|
49
|
+
)
|
|
45
50
|
return
|
|
46
51
|
else:
|
|
47
52
|
videos = VideoFile.objects.all()
|
|
@@ -53,19 +58,19 @@ class Command(BaseCommand):
|
|
|
53
58
|
|
|
54
59
|
for video in videos:
|
|
55
60
|
video_status = self.check_video_file(video, verbose)
|
|
56
|
-
|
|
57
|
-
if video_status[
|
|
61
|
+
|
|
62
|
+
if video_status["status"] == "missing":
|
|
58
63
|
missing_files.append(video_status)
|
|
59
|
-
elif video_status[
|
|
64
|
+
elif video_status["status"] == "corrupted":
|
|
60
65
|
corrupted_files.append(video_status)
|
|
61
66
|
else:
|
|
62
67
|
accessible_files.append(video_status)
|
|
63
68
|
|
|
64
69
|
# Report results
|
|
65
|
-
self.stdout.write("\n" + "="*60)
|
|
70
|
+
self.stdout.write("\n" + "=" * 60)
|
|
66
71
|
self.stdout.write(self.style.SUCCESS("VALIDATION COMPLETE"))
|
|
67
|
-
self.stdout.write("="*60)
|
|
68
|
-
|
|
72
|
+
self.stdout.write("=" * 60)
|
|
73
|
+
|
|
69
74
|
self.stdout.write(f"✅ Accessible videos: {len(accessible_files)}")
|
|
70
75
|
self.stdout.write(f"❌ Missing files: {len(missing_files)}")
|
|
71
76
|
self.stdout.write(f"⚠️ Potentially corrupted: {len(corrupted_files)}")
|
|
@@ -73,37 +78,43 @@ class Command(BaseCommand):
|
|
|
73
78
|
if missing_files:
|
|
74
79
|
self.stdout.write(self.style.WARNING("\nMISSING FILES:"))
|
|
75
80
|
for file_info in missing_files:
|
|
76
|
-
self.stdout.write(
|
|
81
|
+
self.stdout.write(
|
|
82
|
+
f" - Video ID {file_info['video_id']}: {file_info['error']}"
|
|
83
|
+
)
|
|
77
84
|
if fix_missing:
|
|
78
85
|
self.stdout.write(" → Marking as inactive (if applicable)")
|
|
79
86
|
|
|
80
87
|
if corrupted_files:
|
|
81
88
|
self.stdout.write(self.style.WARNING("\nPOTENTIALLY CORRUPTED FILES:"))
|
|
82
89
|
for file_info in corrupted_files:
|
|
83
|
-
self.stdout.write(
|
|
90
|
+
self.stdout.write(
|
|
91
|
+
f" - Video ID {file_info['video_id']}: {file_info['error']}"
|
|
92
|
+
)
|
|
84
93
|
|
|
85
94
|
if verbose and accessible_files:
|
|
86
95
|
self.stdout.write(self.style.SUCCESS("\nACCESSIBLE FILES:"))
|
|
87
96
|
for file_info in accessible_files[:10]: # Show first 10
|
|
88
|
-
self.stdout.write(
|
|
89
|
-
|
|
97
|
+
self.stdout.write(
|
|
98
|
+
f" ✅ Video ID {file_info['video_id']}: {file_info['path']} ({file_info['size_mb']:.1f} MB)"
|
|
99
|
+
)
|
|
100
|
+
|
|
90
101
|
if len(accessible_files) > 10:
|
|
91
102
|
self.stdout.write(f" ... and {len(accessible_files) - 10} more")
|
|
92
103
|
|
|
93
104
|
def check_video_file(self, video, verbose=False):
|
|
94
105
|
"""
|
|
95
106
|
Check a single video file for existence and basic accessibility.
|
|
96
|
-
|
|
107
|
+
|
|
97
108
|
Returns:
|
|
98
109
|
dict: Status information about the video file
|
|
99
110
|
"""
|
|
100
111
|
video_info = {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
"video_id": video.id,
|
|
113
|
+
"video_uuid": str(video.video_hash) if hasattr(video, "uuid") else "N/A",
|
|
114
|
+
"status": "unknown",
|
|
115
|
+
"path": None,
|
|
116
|
+
"size_mb": 0,
|
|
117
|
+
"error": None,
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
# Helper to check a file attribute
|
|
@@ -116,42 +127,63 @@ class Command(BaseCommand):
|
|
|
116
127
|
try:
|
|
117
128
|
file_path = Path(path_getter(file_field) if path_getter else file_field)
|
|
118
129
|
info = video_info.copy()
|
|
119
|
-
info[
|
|
130
|
+
info["path"] = str(file_path)
|
|
120
131
|
if not file_path.exists():
|
|
121
|
-
info[
|
|
122
|
-
info[
|
|
132
|
+
info["status"] = "missing"
|
|
133
|
+
info["error"] = (
|
|
134
|
+
f"{label or attr.replace('_', ' ').title()} does not exist: {file_path}"
|
|
135
|
+
)
|
|
123
136
|
return info
|
|
124
137
|
file_size = file_path.stat().st_size
|
|
125
|
-
info[
|
|
138
|
+
info["size_mb"] = file_size / (1024 * 1024)
|
|
126
139
|
if file_size == 0:
|
|
127
|
-
info[
|
|
128
|
-
info[
|
|
140
|
+
info["status"] = "corrupted"
|
|
141
|
+
info["error"] = (
|
|
142
|
+
f"{label or attr.replace('_', ' ').title()} exists but has zero size"
|
|
143
|
+
)
|
|
129
144
|
else:
|
|
130
|
-
info[
|
|
145
|
+
info["status"] = "accessible"
|
|
131
146
|
return info
|
|
132
147
|
except (ValueError, OSError) as e:
|
|
133
148
|
info = video_info.copy()
|
|
134
|
-
info[
|
|
135
|
-
info[
|
|
136
|
-
info[
|
|
149
|
+
info["path"] = str(getattr(file_field, "path", file_field))
|
|
150
|
+
info["status"] = "corrupted"
|
|
151
|
+
info["error"] = (
|
|
152
|
+
f"Cannot access {label or attr.replace('_', ' ').title()}: {e}"
|
|
153
|
+
)
|
|
137
154
|
return info
|
|
138
155
|
|
|
139
156
|
# Try each file attribute in order of preference
|
|
140
157
|
result = None
|
|
141
158
|
# active_file_path: direct path string
|
|
142
|
-
result = _check_file_attr(video,
|
|
143
|
-
if result:
|
|
159
|
+
result = _check_file_attr(video, "active_file_path", label="Active file path")
|
|
160
|
+
if result:
|
|
161
|
+
return result
|
|
144
162
|
# active_file: Django FileField
|
|
145
|
-
result = _check_file_attr(
|
|
146
|
-
|
|
163
|
+
result = _check_file_attr(
|
|
164
|
+
video, "active_file", path_getter=lambda f: f.path, label="Active file"
|
|
165
|
+
)
|
|
166
|
+
if result:
|
|
167
|
+
return result
|
|
147
168
|
# raw_file: Django FileField
|
|
148
|
-
result = _check_file_attr(
|
|
149
|
-
|
|
169
|
+
result = _check_file_attr(
|
|
170
|
+
video, "raw_file", path_getter=lambda f: f.path, label="Raw file"
|
|
171
|
+
)
|
|
172
|
+
if result:
|
|
173
|
+
return result
|
|
150
174
|
# processed_file: Django FileField
|
|
151
|
-
result = _check_file_attr(
|
|
152
|
-
|
|
175
|
+
result = _check_file_attr(
|
|
176
|
+
video,
|
|
177
|
+
"processed_file",
|
|
178
|
+
path_getter=lambda f: f.path,
|
|
179
|
+
label="Processed file",
|
|
180
|
+
)
|
|
181
|
+
if result:
|
|
182
|
+
return result
|
|
153
183
|
|
|
154
184
|
# If none found
|
|
155
|
-
video_info[
|
|
156
|
-
video_info[
|
|
157
|
-
|
|
185
|
+
video_info["status"] = "missing"
|
|
186
|
+
video_info["error"] = (
|
|
187
|
+
"No video file paths found (no active_file, raw_file, or processed_file)"
|
|
188
|
+
)
|
|
189
|
+
return video_info
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from endoreg_db.models import VideoPredictionMeta
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
3
2
|
from django.core.management.base import BaseCommand
|
|
4
3
|
|
|
@@ -7,16 +6,15 @@ This command handles the video validation as seen in tests _pipe_1
|
|
|
7
6
|
"""
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
12
|
class Command(BaseCommand):
|
|
13
13
|
help = "Data extraction and validation of video files in the database and updating their states accordingly."
|
|
14
14
|
|
|
15
15
|
def handle(self, *args, **options):
|
|
16
16
|
"""
|
|
17
17
|
Validates video files stored in the database and updates their states based on validation results.
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
This method is intended to be executed as a Django management command to ensure the integrity and correct status of video file records.
|
|
20
20
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated by Django
|
|
1
|
+
# Generated by Django 6.0 on 2025-12-20 13:34
|
|
2
2
|
|
|
3
3
|
import django.core.validators
|
|
4
4
|
import django.db.models.deletion
|
|
@@ -185,11 +185,7 @@ class Migration(migrations.Migration):
|
|
|
185
185
|
fields=[
|
|
186
186
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
187
187
|
('name', models.CharField(max_length=100, unique=True)),
|
|
188
|
-
('name_de', models.CharField(max_length=100, null=True, unique=True)),
|
|
189
|
-
('name_en', models.CharField(max_length=100, null=True, unique=True)),
|
|
190
188
|
('description', models.TextField(blank=True, null=True)),
|
|
191
|
-
('description_de', models.TextField(blank=True, null=True)),
|
|
192
|
-
('description_en', models.TextField(blank=True, null=True)),
|
|
193
189
|
],
|
|
194
190
|
),
|
|
195
191
|
migrations.CreateModel(
|
|
@@ -197,11 +193,7 @@ class Migration(migrations.Migration):
|
|
|
197
193
|
fields=[
|
|
198
194
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
199
195
|
('name', models.CharField(max_length=255, unique=True)),
|
|
200
|
-
('name_de', models.CharField(max_length=255, null=True, unique=True)),
|
|
201
|
-
('name_en', models.CharField(max_length=255, null=True, unique=True)),
|
|
202
196
|
('description', models.TextField(blank=True)),
|
|
203
|
-
('description_de', models.TextField(blank=True, null=True)),
|
|
204
|
-
('description_en', models.TextField(blank=True, null=True)),
|
|
205
197
|
],
|
|
206
198
|
),
|
|
207
199
|
migrations.CreateModel(
|
|
@@ -209,11 +201,7 @@ class Migration(migrations.Migration):
|
|
|
209
201
|
fields=[
|
|
210
202
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
211
203
|
('name', models.CharField(max_length=255, unique=True)),
|
|
212
|
-
('name_de', models.CharField(max_length=255, null=True, unique=True)),
|
|
213
|
-
('name_en', models.CharField(max_length=255, null=True, unique=True)),
|
|
214
204
|
('description', models.TextField(blank=True)),
|
|
215
|
-
('description_de', models.TextField(blank=True, null=True)),
|
|
216
|
-
('description_en', models.TextField(blank=True, null=True)),
|
|
217
205
|
('subcategories', models.JSONField(default=dict)),
|
|
218
206
|
('numerical_descriptors', models.JSONField(default=dict)),
|
|
219
207
|
],
|
|
@@ -231,11 +219,7 @@ class Migration(migrations.Migration):
|
|
|
231
219
|
fields=[
|
|
232
220
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
233
221
|
('name', models.CharField(max_length=100, unique=True)),
|
|
234
|
-
('name_de', models.CharField(max_length=100, null=True, unique=True)),
|
|
235
|
-
('name_en', models.CharField(max_length=100, null=True, unique=True)),
|
|
236
222
|
('description', models.TextField(blank=True, null=True)),
|
|
237
|
-
('description_de', models.TextField(blank=True, null=True)),
|
|
238
|
-
('description_en', models.TextField(blank=True, null=True)),
|
|
239
223
|
],
|
|
240
224
|
),
|
|
241
225
|
migrations.CreateModel(
|
|
@@ -261,6 +245,19 @@ class Migration(migrations.Migration):
|
|
|
261
245
|
('name', models.CharField(max_length=255, unique=True)),
|
|
262
246
|
],
|
|
263
247
|
),
|
|
248
|
+
migrations.CreateModel(
|
|
249
|
+
name='Frame',
|
|
250
|
+
fields=[
|
|
251
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
252
|
+
('frame_number', models.PositiveIntegerField()),
|
|
253
|
+
('relative_path', models.CharField(max_length=512)),
|
|
254
|
+
('timestamp', models.FloatField(blank=True, null=True)),
|
|
255
|
+
('is_extracted', models.BooleanField(default=False)),
|
|
256
|
+
],
|
|
257
|
+
options={
|
|
258
|
+
'ordering': ['video', 'frame_number'],
|
|
259
|
+
},
|
|
260
|
+
),
|
|
264
261
|
migrations.CreateModel(
|
|
265
262
|
name='Gender',
|
|
266
263
|
fields=[
|
|
@@ -387,6 +384,18 @@ class Migration(migrations.Migration):
|
|
|
387
384
|
('name', models.CharField(max_length=255)),
|
|
388
385
|
],
|
|
389
386
|
),
|
|
387
|
+
migrations.CreateModel(
|
|
388
|
+
name='ProcessingHistory',
|
|
389
|
+
fields=[
|
|
390
|
+
('file_hash', models.CharField(blank=True, help_text='Content hash of the original file (e.g. video_hash/pdf_hash).', max_length=64, primary_key=True, serialize=False)),
|
|
391
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
392
|
+
('success', models.BooleanField(blank=True, default=False)),
|
|
393
|
+
('object_id', models.PositiveBigIntegerField(blank=True, null=True)),
|
|
394
|
+
],
|
|
395
|
+
options={
|
|
396
|
+
'ordering': ['-created_at'],
|
|
397
|
+
},
|
|
398
|
+
),
|
|
390
399
|
migrations.CreateModel(
|
|
391
400
|
name='Product',
|
|
392
401
|
fields=[
|
|
@@ -441,11 +450,11 @@ class Migration(migrations.Migration):
|
|
|
441
450
|
('date_created', models.DateTimeField(auto_now_add=True)),
|
|
442
451
|
('date_modified', models.DateTimeField(auto_now=True)),
|
|
443
452
|
('was_created', models.BooleanField(default=True, help_text='True if this state was created for the first time.')),
|
|
444
|
-
('pdf_meta_extracted', models.BooleanField(default=False, help_text='True if
|
|
453
|
+
('pdf_meta_extracted', models.BooleanField(default=False, help_text='True if report metadata has been extracted.')),
|
|
445
454
|
],
|
|
446
455
|
options={
|
|
447
|
-
'verbose_name': 'Raw
|
|
448
|
-
'verbose_name_plural': 'Raw
|
|
456
|
+
'verbose_name': 'Raw report Processing State',
|
|
457
|
+
'verbose_name_plural': 'Raw report Processing States',
|
|
449
458
|
},
|
|
450
459
|
),
|
|
451
460
|
migrations.CreateModel(
|
|
@@ -700,11 +709,7 @@ class Migration(migrations.Migration):
|
|
|
700
709
|
fields=[
|
|
701
710
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
702
711
|
('name', models.CharField(max_length=100, unique=True)),
|
|
703
|
-
('name_de', models.CharField(max_length=100, null=True, unique=True)),
|
|
704
|
-
('name_en', models.CharField(max_length=100, null=True, unique=True)),
|
|
705
712
|
('description', models.TextField(blank=True, null=True)),
|
|
706
|
-
('description_de', models.TextField(blank=True, null=True)),
|
|
707
|
-
('description_en', models.TextField(blank=True, null=True)),
|
|
708
713
|
('indications', models.ManyToManyField(blank=True, related_name='examinations', to='endoreg_db.examinationindication')),
|
|
709
714
|
('examination_times', models.ManyToManyField(blank=True, related_name='examinations', to='endoreg_db.examinationtime')),
|
|
710
715
|
('examination_types', models.ManyToManyField(blank=True, to='endoreg_db.examinationtype')),
|
|
@@ -844,6 +849,32 @@ class Migration(migrations.Migration):
|
|
|
844
849
|
'abstract': False,
|
|
845
850
|
},
|
|
846
851
|
),
|
|
852
|
+
migrations.CreateModel(
|
|
853
|
+
name='ImageClassificationAnnotation',
|
|
854
|
+
fields=[
|
|
855
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
856
|
+
('value', models.BooleanField()),
|
|
857
|
+
('float_value', models.FloatField(blank=True, null=True)),
|
|
858
|
+
('annotator', models.CharField(blank=True, max_length=255, null=True)),
|
|
859
|
+
('date_created', models.DateTimeField(auto_now_add=True)),
|
|
860
|
+
('date_modified', models.DateTimeField(auto_now=True)),
|
|
861
|
+
('frame', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='image_classification_annotations', to='endoreg_db.frame')),
|
|
862
|
+
],
|
|
863
|
+
),
|
|
864
|
+
migrations.CreateModel(
|
|
865
|
+
name='AIDataSet',
|
|
866
|
+
fields=[
|
|
867
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
868
|
+
('name', models.CharField(blank=True, help_text='Human-readable identifier, e.g. "Legacy multilabel dataset v1".', max_length=255, null=True)),
|
|
869
|
+
('description', models.TextField(blank=True, help_text='Optional notes / explanation about this dataset.', null=True)),
|
|
870
|
+
('ai_model_type', models.CharField(default='image_multilabel_classification', help_text='AI model family this dataset is for, e.g. "image_multilabel_classification". Used to pick the correct architecture and output dimension logic.', max_length=255)),
|
|
871
|
+
('dataset_type', models.CharField(choices=[('image', 'Image')], default='image', help_text='Controls which annotation table will be used. Currently only "image" is implemented; later "video", "text", etc.', max_length=32)),
|
|
872
|
+
('created_at', models.DateTimeField(auto_now_add=True, help_text='When this AIDataSet was created.')),
|
|
873
|
+
('updated_at', models.DateTimeField(auto_now=True, help_text='When this AIDataSet was last modified.')),
|
|
874
|
+
('is_active', models.BooleanField(default=True, help_text='Soft toggle to enable/disable this dataset for training.')),
|
|
875
|
+
('image_annotations', models.ManyToManyField(blank=True, help_text="For dataset_type='image', this is the set of ImageClassificationAnnotation rows that define this AIDataSet. Each annotation has frame_id and label_id.", related_name='image_ai_datasets', to='endoreg_db.imageclassificationannotation')),
|
|
876
|
+
],
|
|
877
|
+
),
|
|
847
878
|
migrations.CreateModel(
|
|
848
879
|
name='InformationSource',
|
|
849
880
|
fields=[
|
|
@@ -862,6 +893,11 @@ class Migration(migrations.Migration):
|
|
|
862
893
|
'indexes': [models.Index(fields=['name'], name='endoreg_db__name_febac5_idx'), models.Index(fields=['abbreviation'], name='endoreg_db__abbrevi_5a07c4_idx')],
|
|
863
894
|
},
|
|
864
895
|
),
|
|
896
|
+
migrations.AddField(
|
|
897
|
+
model_name='imageclassificationannotation',
|
|
898
|
+
name='information_source',
|
|
899
|
+
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='image_classification_annotations', to='endoreg_db.informationsource'),
|
|
900
|
+
),
|
|
865
901
|
migrations.AddField(
|
|
866
902
|
model_name='findingintervention',
|
|
867
903
|
name='information_sources',
|
|
@@ -905,6 +941,11 @@ class Migration(migrations.Migration):
|
|
|
905
941
|
'verbose_name_plural': 'Information Source Types',
|
|
906
942
|
},
|
|
907
943
|
),
|
|
944
|
+
migrations.AddField(
|
|
945
|
+
model_name='imageclassificationannotation',
|
|
946
|
+
name='label',
|
|
947
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='image_classification_annotations', to='endoreg_db.label'),
|
|
948
|
+
),
|
|
908
949
|
migrations.CreateModel(
|
|
909
950
|
name='LabelSet',
|
|
910
951
|
fields=[
|
|
@@ -1013,6 +1054,11 @@ class Migration(migrations.Migration):
|
|
|
1013
1054
|
'unique_together': {('name', 'version', 'model')},
|
|
1014
1055
|
},
|
|
1015
1056
|
),
|
|
1057
|
+
migrations.AddField(
|
|
1058
|
+
model_name='imageclassificationannotation',
|
|
1059
|
+
name='model_meta',
|
|
1060
|
+
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='image_classification_annotations', to='endoreg_db.modelmeta'),
|
|
1061
|
+
),
|
|
1016
1062
|
migrations.AddField(
|
|
1017
1063
|
model_name='aimodel',
|
|
1018
1064
|
name='active_meta',
|
|
@@ -1050,6 +1096,30 @@ class Migration(migrations.Migration):
|
|
|
1050
1096
|
('default_unit', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.unit')),
|
|
1051
1097
|
],
|
|
1052
1098
|
),
|
|
1099
|
+
migrations.CreateModel(
|
|
1100
|
+
name='OperationLog',
|
|
1101
|
+
fields=[
|
|
1102
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
1103
|
+
('actor_username', models.CharField(blank=True, max_length=150)),
|
|
1104
|
+
('actor_email', models.EmailField(blank=True, max_length=254)),
|
|
1105
|
+
('actor_keycloak_id', models.CharField(blank=True, help_text='Keycloak subject/ID if you later want to store it.', max_length=255)),
|
|
1106
|
+
('action', models.CharField(help_text="e.g. 'anonymization.start', 'anonymization.validate'", max_length=100)),
|
|
1107
|
+
('http_method', models.CharField(blank=True, max_length=10)),
|
|
1108
|
+
('path', models.CharField(blank=True, max_length=512)),
|
|
1109
|
+
('resource_type', models.CharField(blank=True, help_text="e.g. 'video', 'pdf'", max_length=50)),
|
|
1110
|
+
('resource_id', models.IntegerField(blank=True, help_text='ID of VideoFile / RawPdfFile etc.', null=True)),
|
|
1111
|
+
('status_before', models.CharField(blank=True, max_length=50)),
|
|
1112
|
+
('status_after', models.CharField(blank=True, max_length=50)),
|
|
1113
|
+
('meta', models.JSONField(blank=True, null=True)),
|
|
1114
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
1115
|
+
('actor_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='operation_logs', to=settings.AUTH_USER_MODEL)),
|
|
1116
|
+
],
|
|
1117
|
+
options={
|
|
1118
|
+
'verbose_name': 'Operation Log',
|
|
1119
|
+
'verbose_name_plural': 'Operation Logs',
|
|
1120
|
+
'ordering': ['-created_at'],
|
|
1121
|
+
},
|
|
1122
|
+
),
|
|
1053
1123
|
migrations.CreateModel(
|
|
1054
1124
|
name='Patient',
|
|
1055
1125
|
fields=[
|
|
@@ -1149,7 +1219,7 @@ class Migration(migrations.Migration):
|
|
|
1149
1219
|
('text', models.TextField(blank=True, null=True)),
|
|
1150
1220
|
('date', models.DateField(blank=True, null=True)),
|
|
1151
1221
|
('time', models.TimeField(blank=True, null=True)),
|
|
1152
|
-
('file', models.FileField(blank=True, null=True, upload_to='
|
|
1222
|
+
('file', models.FileField(blank=True, null=True, upload_to='documents')),
|
|
1153
1223
|
('center', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='endoreg_db.center')),
|
|
1154
1224
|
('type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='endoreg_db.documenttype')),
|
|
1155
1225
|
('examiners', models.ManyToManyField(blank=True, to='endoreg_db.examiner')),
|
|
@@ -1457,9 +1527,8 @@ class Migration(migrations.Migration):
|
|
|
1457
1527
|
('text', models.TextField(blank=True, null=True)),
|
|
1458
1528
|
('date_created', models.DateTimeField(auto_now_add=True)),
|
|
1459
1529
|
('date_modified', models.DateTimeField(auto_now=True)),
|
|
1460
|
-
('
|
|
1461
|
-
('
|
|
1462
|
-
('anonymized_file', models.FileField(blank=True, null=True, upload_to='pdfs', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['pdf'])])),
|
|
1530
|
+
('file', models.FileField(upload_to='sensitive_reports', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['pdf'])])),
|
|
1531
|
+
('processed_file', models.FileField(blank=True, null=True, upload_to='processed_reports_final', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['pdf'])])),
|
|
1463
1532
|
('state_report_processing_required', models.BooleanField(default=True)),
|
|
1464
1533
|
('state_report_processed', models.BooleanField(default=False)),
|
|
1465
1534
|
('raw_meta', models.JSONField(blank=True, null=True)),
|
|
@@ -1482,7 +1551,7 @@ class Migration(migrations.Migration):
|
|
|
1482
1551
|
('text', models.TextField(blank=True, null=True)),
|
|
1483
1552
|
('date', models.DateField(blank=True, null=True)),
|
|
1484
1553
|
('time', models.TimeField(blank=True, null=True)),
|
|
1485
|
-
('file', models.FileField(blank=True, null=True, upload_to='
|
|
1554
|
+
('file', models.FileField(blank=True, null=True, upload_to='documents')),
|
|
1486
1555
|
('center', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='endoreg_db.center')),
|
|
1487
1556
|
('type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='endoreg_db.documenttype')),
|
|
1488
1557
|
('examiners', models.ManyToManyField(blank=True, to='endoreg_db.examiner')),
|
|
@@ -1634,7 +1703,7 @@ class Migration(migrations.Migration):
|
|
|
1634
1703
|
name='UploadJob',
|
|
1635
1704
|
fields=[
|
|
1636
1705
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for the upload job', primary_key=True, serialize=False)),
|
|
1637
|
-
('file', models.FileField(help_text='Uploaded file (
|
|
1706
|
+
('file', models.FileField(help_text='Uploaded file (report or video)', upload_to='uploads/%Y/%m/%d/')),
|
|
1638
1707
|
('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('anonymized', 'Anonymized'), ('error', 'Error')], default='pending', help_text='Current processing status of the upload', max_length=20)),
|
|
1639
1708
|
('content_type', models.CharField(blank=True, help_text='MIME type of the uploaded file', max_length=100)),
|
|
1640
1709
|
('error_detail', models.TextField(blank=True, help_text='Error message if processing failed')),
|
|
@@ -1652,9 +1721,8 @@ class Migration(migrations.Migration):
|
|
|
1652
1721
|
name='VideoFile',
|
|
1653
1722
|
fields=[
|
|
1654
1723
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
1655
|
-
('
|
|
1656
|
-
('
|
|
1657
|
-
('processed_file', models.FileField(blank=True, null=True, upload_to='videos', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['mp4'])])),
|
|
1724
|
+
('raw_file', models.FileField(blank=True, null=True, upload_to='sensitive_videos', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['mp4'])])),
|
|
1725
|
+
('processed_file', models.FileField(blank=True, null=True, upload_to='processed_videos_final', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['mp4'])])),
|
|
1658
1726
|
('video_hash', models.CharField(help_text='Hash of the raw video file.', max_length=255, unique=True)),
|
|
1659
1727
|
('processed_video_hash', models.CharField(blank=True, help_text='Hash of the processed video file, unique if not null.', max_length=255, null=True, unique=True)),
|
|
1660
1728
|
('original_file_name', models.CharField(blank=True, max_length=255, null=True)),
|
|
@@ -1690,19 +1758,10 @@ class Migration(migrations.Migration):
|
|
|
1690
1758
|
name='video_file',
|
|
1691
1759
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='label_video_segments', to='endoreg_db.videofile'),
|
|
1692
1760
|
),
|
|
1693
|
-
migrations.
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
('frame_number', models.PositiveIntegerField()),
|
|
1698
|
-
('relative_path', models.CharField(max_length=512)),
|
|
1699
|
-
('timestamp', models.FloatField(blank=True, null=True)),
|
|
1700
|
-
('is_extracted', models.BooleanField(default=False)),
|
|
1701
|
-
('video', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frames', to='endoreg_db.videofile')),
|
|
1702
|
-
],
|
|
1703
|
-
options={
|
|
1704
|
-
'ordering': ['video', 'frame_number'],
|
|
1705
|
-
},
|
|
1761
|
+
migrations.AddField(
|
|
1762
|
+
model_name='frame',
|
|
1763
|
+
name='video',
|
|
1764
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frames', to='endoreg_db.videofile'),
|
|
1706
1765
|
),
|
|
1707
1766
|
migrations.CreateModel(
|
|
1708
1767
|
name='VideoMeta',
|
|
@@ -1815,23 +1874,13 @@ class Migration(migrations.Migration):
|
|
|
1815
1874
|
('waste', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.waste')),
|
|
1816
1875
|
],
|
|
1817
1876
|
),
|
|
1818
|
-
migrations.
|
|
1819
|
-
|
|
1820
|
-
fields=[
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
('date_created', models.DateTimeField(auto_now_add=True)),
|
|
1826
|
-
('date_modified', models.DateTimeField(auto_now=True)),
|
|
1827
|
-
('frame', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='image_classification_annotations', to='endoreg_db.frame')),
|
|
1828
|
-
('information_source', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='image_classification_annotations', to='endoreg_db.informationsource')),
|
|
1829
|
-
('label', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='image_classification_annotations', to='endoreg_db.label')),
|
|
1830
|
-
('model_meta', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='image_classification_annotations', to='endoreg_db.modelmeta')),
|
|
1831
|
-
],
|
|
1832
|
-
options={
|
|
1833
|
-
'indexes': [models.Index(fields=['frame', 'label'], name='endoreg_db__frame_i_47f916_idx'), models.Index(fields=['frame'], name='endoreg_db__frame_i_92c75a_idx')],
|
|
1834
|
-
},
|
|
1877
|
+
migrations.AddIndex(
|
|
1878
|
+
model_name='imageclassificationannotation',
|
|
1879
|
+
index=models.Index(fields=['frame', 'label'], name='endoreg_db__frame_i_47f916_idx'),
|
|
1880
|
+
),
|
|
1881
|
+
migrations.AddIndex(
|
|
1882
|
+
model_name='imageclassificationannotation',
|
|
1883
|
+
index=models.Index(fields=['frame'], name='endoreg_db__frame_i_92c75a_idx'),
|
|
1835
1884
|
),
|
|
1836
1885
|
migrations.AddConstraint(
|
|
1837
1886
|
model_name='patientexternalid',
|
|
File without changes
|
endoreg_db/models/__init__.py
CHANGED
|
@@ -151,6 +151,12 @@ from .state import (
|
|
|
151
151
|
VideoState,
|
|
152
152
|
)
|
|
153
153
|
|
|
154
|
+
# AI dataset model
|
|
155
|
+
from .aidataset import (
|
|
156
|
+
AIDataSet,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
154
160
|
__all__ = [
|
|
155
161
|
####### Administration ########
|
|
156
162
|
# AI
|
|
@@ -311,4 +317,6 @@ __all__ = [
|
|
|
311
317
|
"LabelVideoSegmentState",
|
|
312
318
|
"AnonymizationState",
|
|
313
319
|
"RawPdfState",
|
|
320
|
+
###### AIDATASET ######
|
|
321
|
+
"AIDataSet",
|
|
314
322
|
]
|
|
@@ -8,7 +8,8 @@ if TYPE_CHECKING:
|
|
|
8
8
|
class ActiveModelManager(models.Manager):
|
|
9
9
|
def get_by_natural_key(self, name):
|
|
10
10
|
return self.get(name=name)
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
|
|
12
13
|
class ActiveModel(models.Model):
|
|
13
14
|
"""
|
|
14
15
|
ActiveModel represents an active instance of a model within the application.
|
|
@@ -26,10 +27,9 @@ class ActiveModel(models.Model):
|
|
|
26
27
|
"""
|
|
27
28
|
|
|
28
29
|
name = models.CharField(max_length=255, unique=True)
|
|
29
|
-
|
|
30
|
-
model_meta:models.ForeignKey["ModelMeta|None"] = models.ForeignKey(
|
|
31
|
-
|
|
32
|
-
blank=True, null=True
|
|
30
|
+
|
|
31
|
+
model_meta: models.ForeignKey["ModelMeta|None"] = models.ForeignKey(
|
|
32
|
+
"ModelMeta", on_delete=models.SET_NULL, blank=True, null=True
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
objects = ActiveModelManager()
|