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
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
from django.conf import settings
|
|
4
|
+
from rest_framework import serializers
|
|
5
|
+
|
|
4
6
|
from ...models import RawPdfFile
|
|
5
7
|
|
|
8
|
+
|
|
6
9
|
class RawPdfAnonyTextSerializer(serializers.ModelSerializer):
|
|
7
10
|
"""
|
|
8
|
-
Serializer to fetch
|
|
11
|
+
Serializer to fetch report metadata along with `anonymized_text` from `RawPdfFile`.
|
|
9
12
|
Ensures Vue.js can process JSON efficiently.
|
|
10
13
|
"""
|
|
11
14
|
|
|
@@ -15,36 +18,46 @@ class RawPdfAnonyTextSerializer(serializers.ModelSerializer):
|
|
|
15
18
|
|
|
16
19
|
class Meta:
|
|
17
20
|
model = RawPdfFile
|
|
18
|
-
fields = [
|
|
19
|
-
|
|
21
|
+
fields = [
|
|
22
|
+
"id",
|
|
23
|
+
"file",
|
|
24
|
+
"pdf_url",
|
|
25
|
+
"full_pdf_path",
|
|
26
|
+
"sensitive_meta_id",
|
|
27
|
+
"anonymized_text",
|
|
28
|
+
]
|
|
20
29
|
|
|
21
30
|
@staticmethod
|
|
22
31
|
def get_next_pdf(last_id=None):
|
|
23
32
|
"""
|
|
24
|
-
Retrieves the first available
|
|
25
|
-
Otherwise, fetches the next available
|
|
33
|
+
Retrieves the first available report if `last_id` is NOT provided.
|
|
34
|
+
Otherwise, fetches the next available report where `id > last_id`.
|
|
26
35
|
"""
|
|
27
36
|
query_filter = {} if last_id is None else {"id__gt": int(last_id)}
|
|
28
|
-
pdf_entry = RawPdfFile.objects.filter(**query_filter).order_by(
|
|
29
|
-
return pdf_entry
|
|
37
|
+
pdf_entry = RawPdfFile.objects.filter(**query_filter).order_by("id").first()
|
|
38
|
+
return pdf_entry
|
|
30
39
|
|
|
31
40
|
def get_pdf_url(self, obj):
|
|
32
41
|
"""
|
|
33
|
-
Returns the absolute URL for accessing the anonymized text
|
|
34
|
-
|
|
42
|
+
Returns the absolute URL for accessing the anonymized text report endpoint for the given object.
|
|
43
|
+
|
|
35
44
|
If the request context or file is missing, returns None.
|
|
36
45
|
"""
|
|
37
|
-
request = self.context.get(
|
|
38
|
-
return
|
|
46
|
+
request = self.context.get("request")
|
|
47
|
+
return (
|
|
48
|
+
request.build_absolute_uri(f"/pdf/anony_text/?id={obj.id}")
|
|
49
|
+
if request and obj.file
|
|
50
|
+
else None
|
|
51
|
+
)
|
|
39
52
|
|
|
40
53
|
def get_file(self, obj):
|
|
41
54
|
"""
|
|
42
|
-
Retrieves the relative file path of the
|
|
43
|
-
|
|
55
|
+
Retrieves the relative file path of the report from the model instance.
|
|
56
|
+
|
|
44
57
|
Returns:
|
|
45
58
|
The relative file path as a string, or None if no file is associated.
|
|
46
59
|
"""
|
|
47
|
-
return str(obj.file.name).strip() if obj.file else None
|
|
60
|
+
return str(obj.file.name).strip() if obj.file else None
|
|
48
61
|
|
|
49
62
|
def get_full_pdf_path(self, obj):
|
|
50
63
|
"""
|
|
@@ -54,32 +67,35 @@ class RawPdfAnonyTextSerializer(serializers.ModelSerializer):
|
|
|
54
67
|
return None
|
|
55
68
|
pdf_relative_path = str(obj.file.name)
|
|
56
69
|
full_path = Path(settings.MEDIA_ROOT) / pdf_relative_path
|
|
57
|
-
return str(full_path) if full_path.exists() else None
|
|
70
|
+
return str(full_path) if full_path.exists() else None
|
|
58
71
|
|
|
59
72
|
def validate_anonymized_text(self, value):
|
|
60
73
|
"""
|
|
61
74
|
Validates that the anonymized text is non-empty and does not exceed 5000 characters.
|
|
62
|
-
|
|
75
|
+
|
|
63
76
|
Raises:
|
|
64
77
|
serializers.ValidationError: If the text is empty or exceeds the length limit.
|
|
65
78
|
"""
|
|
66
79
|
if not value.strip():
|
|
67
80
|
raise serializers.ValidationError("Anonymized text cannot be empty.")
|
|
68
|
-
#FIXME move this to a settings variable @Hamzaukw @maxhild
|
|
81
|
+
# FIXME move this to a settings variable @Hamzaukw @maxhild
|
|
69
82
|
if len(value) > 5000: # Arbitrary limit to prevent excessively long text
|
|
70
|
-
raise serializers.ValidationError(
|
|
83
|
+
raise serializers.ValidationError(
|
|
84
|
+
"Anonymized text exceeds the maximum length of 5000 characters."
|
|
85
|
+
)
|
|
71
86
|
return value
|
|
72
87
|
|
|
73
88
|
def update(self, instance, validated_data):
|
|
74
89
|
"""
|
|
75
90
|
Update the `anonymized_text` field of a RawPdfFile instance with validated data.
|
|
76
|
-
|
|
91
|
+
|
|
77
92
|
Only the `anonymized_text` field is modified; all other fields remain unchanged.
|
|
78
|
-
|
|
93
|
+
|
|
79
94
|
Returns:
|
|
80
95
|
The updated RawPdfFile instance.
|
|
81
96
|
"""
|
|
82
|
-
instance.anonymized_text = validated_data.get(
|
|
97
|
+
instance.anonymized_text = validated_data.get(
|
|
98
|
+
"anonymized_text", instance.anonymized_text
|
|
99
|
+
)
|
|
83
100
|
instance.save()
|
|
84
101
|
return instance
|
|
85
|
-
|
|
@@ -1,29 +1,99 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
|
|
3
|
+
from endoreg_db.models.requirement.requirement_set import RequirementSet
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RequirementSetSerializer(serializers.ModelSerializer):
|
|
7
|
+
"""
|
|
8
|
+
Serializer for RequirementSet model with optional tag field.
|
|
9
|
+
|
|
10
|
+
This serializer provides a flexible representation of requirement sets,
|
|
11
|
+
including role-based tags for filtering (e.g., "Gastroenterologist", "Student").
|
|
12
|
+
|
|
13
|
+
Fields:
|
|
14
|
+
id: Primary key
|
|
15
|
+
name: Display name of the requirement set
|
|
16
|
+
description: Optional description text
|
|
17
|
+
requirement_set_type: Type classification
|
|
18
|
+
tags: List of tag names (optional, read-only)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
tags = serializers.SlugRelatedField(
|
|
22
|
+
many=True, read_only=True, slug_field="name", required=False
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
requirement_set_type = serializers.CharField(
|
|
26
|
+
source="requirement_set_type.name", read_only=True, allow_null=True
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
class Meta:
|
|
30
|
+
model = RequirementSet
|
|
31
|
+
fields = ["id", "name", "description", "requirement_set_type", "tags"]
|
|
32
|
+
|
|
33
|
+
def to_representation(self, instance):
|
|
34
|
+
"""
|
|
35
|
+
Customize representation to exclude tags field if empty or not prefetched.
|
|
36
|
+
|
|
37
|
+
This prevents N+1 query issues and keeps the response clean when tags
|
|
38
|
+
aren't needed or weren't prefetched in the queryset.
|
|
39
|
+
"""
|
|
40
|
+
representation = super().to_representation(instance)
|
|
41
|
+
|
|
42
|
+
# Only include tags if they exist and were prefetched
|
|
43
|
+
if not representation.get("tags"):
|
|
44
|
+
representation.pop("tags", None)
|
|
45
|
+
|
|
46
|
+
return representation
|
|
47
|
+
|
|
3
48
|
|
|
4
49
|
def requirement_set_to_dict(requirement_set: RequirementSet) -> dict:
|
|
5
50
|
"""
|
|
6
51
|
Convert a RequirementSet instance to a dictionary representation.
|
|
7
|
-
|
|
52
|
+
|
|
53
|
+
This function performs additional queries to fetch related data including
|
|
54
|
+
requirements and linked sets. Use RequirementSetSerializer for simpler
|
|
55
|
+
representations without the overhead of additional queries.
|
|
56
|
+
|
|
8
57
|
Args:
|
|
9
|
-
requirement_set
|
|
10
|
-
|
|
58
|
+
requirement_set: The RequirementSet instance to convert.
|
|
59
|
+
|
|
11
60
|
Returns:
|
|
12
|
-
|
|
61
|
+
Dictionary representation of the RequirementSet with full nested details:
|
|
62
|
+
- id, name, description: Basic metadata
|
|
63
|
+
- requirements: List of requirement dictionaries
|
|
64
|
+
- links: List of linked requirement set data
|
|
65
|
+
- tags: List of tag names (if any exist)
|
|
13
66
|
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
67
|
+
# Fetch the requirement set with all related data to avoid N+1 queries
|
|
68
|
+
requirement_set_full = (
|
|
69
|
+
RequirementSet.objects.select_related("requirement_set_type")
|
|
70
|
+
.prefetch_related("requirements", "links_to_sets", "tags")
|
|
71
|
+
.get(pk=requirement_set.pk)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Get linked requirement sets
|
|
75
|
+
linked_sets = requirement_set_full.links_to_sets.all()
|
|
76
|
+
|
|
77
|
+
result = {
|
|
78
|
+
"id": requirement_set_full.pk,
|
|
79
|
+
"name": requirement_set_full.name,
|
|
80
|
+
"description": requirement_set_full.description or "",
|
|
81
|
+
"requirement_set_type": requirement_set_full.requirement_set_type.name
|
|
82
|
+
if requirement_set_full.requirement_set_type
|
|
83
|
+
else None,
|
|
84
|
+
"requirements": [
|
|
85
|
+
{"id": req.pk, "name": req.name, "description": req.description or ""}
|
|
86
|
+
for req in requirement_set_full.requirements.all()
|
|
87
|
+
],
|
|
88
|
+
"linked_sets": [
|
|
89
|
+
{"id": link.pk, "name": link.name, "description": link.description or ""}
|
|
90
|
+
for link in linked_sets
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Add tags if they exist
|
|
95
|
+
tags = list(requirement_set_full.tags.values_list("name", flat=True))
|
|
96
|
+
if tags:
|
|
97
|
+
result["tags"] = tags
|
|
98
|
+
|
|
99
|
+
return result
|
|
@@ -10,7 +10,8 @@ from django.conf import settings
|
|
|
10
10
|
from typing import TYPE_CHECKING
|
|
11
11
|
from rest_framework.exceptions import ValidationError
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
|
-
from endoreg_db.models import
|
|
13
|
+
from endoreg_db.models import VideoFile
|
|
14
|
+
|
|
14
15
|
class VideoFileSerializer(serializers.ModelSerializer):
|
|
15
16
|
"""
|
|
16
17
|
Serializer that dynamically handles video retrieval and streaming.
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
3
|
-
|
|
1
|
+
# endoreg_db/serializers/video/video_file_list.py
|
|
2
|
+
from typing import Literal, Optional
|
|
3
|
+
import logging
|
|
4
4
|
|
|
5
5
|
from rest_framework import serializers
|
|
6
6
|
|
|
7
|
+
from endoreg_db.models import VideoFile
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
class VideoFileListSerializer(serializers.ModelSerializer):
|
|
9
13
|
"""
|
|
10
14
|
Minimal serializer to return only basic video information
|
|
11
15
|
for the video selection dropdown in Vue.js.
|
|
16
|
+
|
|
17
|
+
Convention:
|
|
18
|
+
- Serializer methods must NOT raise if video state is missing or invalid.
|
|
19
|
+
- They return safe defaults and log what went wrong.
|
|
12
20
|
"""
|
|
13
21
|
|
|
14
22
|
# Add computed fields for video status
|
|
@@ -20,48 +28,71 @@ class VideoFileListSerializer(serializers.ModelSerializer):
|
|
|
20
28
|
model = VideoFile
|
|
21
29
|
fields = ["id", "original_file_name", "status", "assignedUser", "anonymized"]
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
# --- internal helper -------------------------------------------------
|
|
32
|
+
def _get_video_state(self, obj: VideoFile):
|
|
24
33
|
"""
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Raises:
|
|
31
|
-
ValueError: If the video's state cannot be accessed.
|
|
34
|
+
Best-effort accessor for obj.state.
|
|
35
|
+
|
|
36
|
+
Serializer layer must never raise here; it only logs and returns None
|
|
37
|
+
if the state cannot be loaded for any reason.
|
|
32
38
|
"""
|
|
33
39
|
try:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
return getattr(obj, "state", None)
|
|
41
|
+
except Exception as exc: # pragma: no cover - type of error is DB/backend-specific
|
|
42
|
+
logger.warning(
|
|
43
|
+
"VideoFileListSerializer: unable to access state for VideoFile(id=%s): %s",
|
|
44
|
+
getattr(obj, "id", "unknown"),
|
|
45
|
+
exc,
|
|
46
|
+
)
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
# --- public serializer fields ----------------------------------------
|
|
50
|
+
def get_status(
|
|
51
|
+
self, obj: VideoFile
|
|
52
|
+
) -> Literal["completed", "in_progress", "available"]:
|
|
53
|
+
"""
|
|
54
|
+
Determine the processing status of a video file as 'completed',
|
|
55
|
+
'in_progress', or 'available'.
|
|
56
|
+
|
|
57
|
+
Contract:
|
|
58
|
+
- Never raises.
|
|
59
|
+
- Missing or invalid state -> treated as 'available'.
|
|
60
|
+
"""
|
|
61
|
+
state = self._get_video_state(obj)
|
|
62
|
+
|
|
63
|
+
if not state:
|
|
64
|
+
return "available"
|
|
65
|
+
|
|
66
|
+
# Use getattr with defaults to tolerate partially populated state objects
|
|
67
|
+
anonymized = getattr(state, "anonymized", False)
|
|
68
|
+
frames_extracted = getattr(state, "frames_extracted", False)
|
|
69
|
+
|
|
70
|
+
if anonymized:
|
|
71
|
+
return "completed"
|
|
72
|
+
if frames_extracted:
|
|
73
|
+
return "in_progress"
|
|
74
|
+
return "available"
|
|
75
|
+
|
|
76
|
+
def get_assignedUser(self, obj: VideoFile):
|
|
46
77
|
"""
|
|
47
78
|
Returns the user assigned to the video, or None if no user is assigned.
|
|
48
|
-
|
|
79
|
+
|
|
49
80
|
Currently always returns None as user assignment is not implemented.
|
|
50
81
|
"""
|
|
51
82
|
# For now return None, can be extended when user assignment is implemented
|
|
52
83
|
return None
|
|
53
84
|
|
|
54
|
-
def get_anonymized(self, obj):
|
|
85
|
+
def get_anonymized(self, obj: VideoFile) -> bool:
|
|
55
86
|
"""
|
|
56
87
|
Determine whether the video has been anonymized.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
|
|
89
|
+
Contract:
|
|
90
|
+
- Never raises.
|
|
91
|
+
- Returns False if state does not exist or cannot be loaded.
|
|
60
92
|
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if state:
|
|
64
|
-
return getattr(state, 'anonymized', False)
|
|
93
|
+
state = self._get_video_state(obj)
|
|
94
|
+
if not state:
|
|
65
95
|
return False
|
|
66
|
-
|
|
67
|
-
|
|
96
|
+
|
|
97
|
+
# getattr to be robust against partially/populated state
|
|
98
|
+
return bool(getattr(state, "anonymized", False))
|
|
@@ -4,7 +4,10 @@ Video Processing History Serializer
|
|
|
4
4
|
Serializes VideoProcessingHistory model for API responses.
|
|
5
5
|
Created as part of Phase 1.1: Video Correction API Endpoints.
|
|
6
6
|
"""
|
|
7
|
+
from collections.abc import Mapping
|
|
8
|
+
|
|
7
9
|
from rest_framework import serializers
|
|
10
|
+
|
|
8
11
|
from endoreg_db.models import VideoProcessingHistory
|
|
9
12
|
|
|
10
13
|
|
|
@@ -16,8 +19,8 @@ class VideoProcessingHistorySerializer(serializers.ModelSerializer):
|
|
|
16
19
|
with download URLs for processed files.
|
|
17
20
|
"""
|
|
18
21
|
download_url = serializers.SerializerMethodField()
|
|
19
|
-
operation_display = serializers.
|
|
20
|
-
status_display = serializers.
|
|
22
|
+
operation_display = serializers.SerializerMethodField()
|
|
23
|
+
status_display = serializers.SerializerMethodField()
|
|
21
24
|
duration = serializers.ReadOnlyField()
|
|
22
25
|
is_complete = serializers.ReadOnlyField()
|
|
23
26
|
|
|
@@ -57,13 +60,24 @@ class VideoProcessingHistorySerializer(serializers.ModelSerializer):
|
|
|
57
60
|
|
|
58
61
|
# Build URL to download endpoint (to be implemented)
|
|
59
62
|
# Format: /api/media/processed-videos/{video_id}/{history_id}/
|
|
60
|
-
|
|
63
|
+
context = self.context if isinstance(self.context, Mapping) else None
|
|
64
|
+
request = context.get('request') if context else None
|
|
61
65
|
if request:
|
|
62
66
|
return request.build_absolute_uri(
|
|
63
67
|
f'/api/media/processed-videos/{obj.video.id}/{obj.id}/'
|
|
64
68
|
)
|
|
65
69
|
|
|
66
70
|
return f'/api/media/processed-videos/{obj.video.id}/{obj.id}/'
|
|
71
|
+
|
|
72
|
+
def get_operation_display(self, obj) -> str:
|
|
73
|
+
display = getattr(obj, "get_operation_display", None)
|
|
74
|
+
result = display() if callable(display) else obj.operation
|
|
75
|
+
return str(result)
|
|
76
|
+
|
|
77
|
+
def get_status_display(self, obj) -> str:
|
|
78
|
+
display = getattr(obj, "get_status_display", None)
|
|
79
|
+
result = display() if callable(display) else obj.status
|
|
80
|
+
return str(result)
|
|
67
81
|
|
|
68
82
|
def validate_operation(self, value):
|
|
69
83
|
"""
|
|
@@ -120,8 +134,9 @@ class VideoProcessingHistorySerializer(serializers.ModelSerializer):
|
|
|
120
134
|
"""
|
|
121
135
|
if not isinstance(value, dict):
|
|
122
136
|
raise serializers.ValidationError("config must be a dictionary")
|
|
123
|
-
|
|
124
|
-
|
|
137
|
+
|
|
138
|
+
initial = self.initial_data if isinstance(self.initial_data, Mapping) else {}
|
|
139
|
+
operation = initial.get('operation')
|
|
125
140
|
|
|
126
141
|
# Validate masking config
|
|
127
142
|
if operation == VideoProcessingHistory.OPERATION_MASKING:
|