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,179 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from rest_framework import serializers
|
|
3
|
-
from django.conf import settings
|
|
4
|
-
from ...models import VideoFile, SensitiveMeta
|
|
5
|
-
import cv2
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class VideoFileForMetaSerializer(serializers.ModelSerializer):
|
|
9
|
-
"""
|
|
10
|
-
Serializer to fetch video metadata along with linked `SensitiveMeta` details.
|
|
11
|
-
Ensures that Vue.js can properly access and play videos.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
# Fetch patient name and DOB from `SensitiveMeta` table
|
|
15
|
-
patient_first_name = serializers.CharField(source="sensitive_meta.patient_first_name", read_only=True)
|
|
16
|
-
patient_last_name = serializers.CharField(source="sensitive_meta.patient_last_name", read_only=True)
|
|
17
|
-
patient_dob = serializers.CharField(source="sensitive_meta.patient_dob", read_only=True)
|
|
18
|
-
examination_date = serializers.CharField(source="sensitive_meta.examination_date", read_only=True)
|
|
19
|
-
|
|
20
|
-
duration = serializers.SerializerMethodField()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# `video_url` generates the full URL where Vue.js can fetch & play the video
|
|
24
|
-
video_url = serializers.SerializerMethodField()
|
|
25
|
-
|
|
26
|
-
# `full_video_path` dynamically constructs the absolute path using MEDIA_ROOT
|
|
27
|
-
full_video_path = serializers.SerializerMethodField()
|
|
28
|
-
|
|
29
|
-
file = serializers.SerializerMethodField()
|
|
30
|
-
|
|
31
|
-
class Meta:
|
|
32
|
-
model = VideoFile
|
|
33
|
-
fields = ['id', 'original_file_name', 'file', 'video_url', 'full_video_path',
|
|
34
|
-
'sensitive_meta_id', 'patient_first_name', 'patient_last_name', 'patient_dob', 'examination_date','duration']
|
|
35
|
-
|
|
36
|
-
@staticmethod
|
|
37
|
-
def get_next_video(last_id=None):
|
|
38
|
-
"""
|
|
39
|
-
Fetches the first or next available video.
|
|
40
|
-
Returns a model instance if found, else returns None.
|
|
41
|
-
"""
|
|
42
|
-
query_filter = {} if last_id is None else {"id__gt": int(last_id)}
|
|
43
|
-
|
|
44
|
-
# Get next available video
|
|
45
|
-
video_entry = VideoFile.objects.select_related("sensitive_meta").filter(**query_filter).order_by('id').first()
|
|
46
|
-
|
|
47
|
-
return video_entry # Always return model instance or None
|
|
48
|
-
|
|
49
|
-
def get_video_url(self, obj):
|
|
50
|
-
"""
|
|
51
|
-
Returns the absolute URL for streaming the processed video file, or None if unavailable.
|
|
52
|
-
|
|
53
|
-
The URL includes an "api/" prefix and is constructed only if a request context and a processed video file are present.
|
|
54
|
-
"""
|
|
55
|
-
request = self.context.get('request')
|
|
56
|
-
if request and obj.processed_file:
|
|
57
|
-
print("---------------------------:",obj.processed_file)
|
|
58
|
-
return request.build_absolute_uri(f"/api/video/{obj.id}/") # Added api/ prefix
|
|
59
|
-
return None # Return None instead of an error dictionary
|
|
60
|
-
|
|
61
|
-
def get_file(self, obj):
|
|
62
|
-
"""
|
|
63
|
-
Returns the relative file path of the processed video, excluding the `/media/` prefix.
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
The relative file path as a string if available, otherwise None.
|
|
67
|
-
"""
|
|
68
|
-
if not obj.processed_file:
|
|
69
|
-
return None # No file associated
|
|
70
|
-
|
|
71
|
-
video_relative_path = str(obj.processed_file.name).strip()
|
|
72
|
-
return video_relative_path if video_relative_path else None # Avoids errors if the file path is empty
|
|
73
|
-
|
|
74
|
-
def get_full_video_path(self, obj):
|
|
75
|
-
"""
|
|
76
|
-
Constructs the full absolute file path using `settings.MEDIA_ROOT`
|
|
77
|
-
and the `file` field from the database.
|
|
78
|
-
"""
|
|
79
|
-
if not obj.processed_file:
|
|
80
|
-
return None # No file associated
|
|
81
|
-
|
|
82
|
-
video_relative_path = str(obj.processed_file.name).strip()
|
|
83
|
-
full_path = Path(settings.MEDIA_ROOT) / video_relative_path
|
|
84
|
-
|
|
85
|
-
return str(full_path) if full_path.exists() else None # Return path or None if not found
|
|
86
|
-
|
|
87
|
-
def get_duration(self, obj):
|
|
88
|
-
"""
|
|
89
|
-
Returns the total duration of the video in seconds.
|
|
90
|
-
- If stored in the database, use it.
|
|
91
|
-
- Otherwise, calculate dynamically using OpenCV.
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
# Step 1: Check if the `duration` field is already stored in the database.
|
|
95
|
-
if hasattr(obj, "duration") and obj.duration:
|
|
96
|
-
return obj.duration # If duration exists in the database, return it immediately.
|
|
97
|
-
|
|
98
|
-
# Step 2: Get the actual video file path
|
|
99
|
-
video_path = obj.processed_file.path if obj.processed_file else None # Extracts the file path if it exists
|
|
100
|
-
|
|
101
|
-
# Step 3: Validate if the file exists
|
|
102
|
-
if not video_path or not Path(video_path).exists():
|
|
103
|
-
return None # Return None if the file path is invalid or missing
|
|
104
|
-
|
|
105
|
-
# Step 4: Open the video file using OpenCV
|
|
106
|
-
cap = cv2.VideoCapture(video_path) # Load the video file
|
|
107
|
-
|
|
108
|
-
if not cap.isOpened():
|
|
109
|
-
return None # If OpenCV fails to open the video, return None (invalid or corrupted file)
|
|
110
|
-
|
|
111
|
-
# Step 5: Extract FPS (Frames Per Second)
|
|
112
|
-
fps = cap.get(cv2.CAP_PROP_FPS) # Get the number of frames per second
|
|
113
|
-
print("here is the fps------------", fps) # Debugging print to check FPS value
|
|
114
|
-
|
|
115
|
-
# Step 6: Get Total Number of Frames
|
|
116
|
-
total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # Get the total number of frames in the video
|
|
117
|
-
|
|
118
|
-
# Step 7: Release the video file from OpenCV memory
|
|
119
|
-
cap.release() # Free up system memory
|
|
120
|
-
|
|
121
|
-
# Step 8: Calculate and Return Video Duration
|
|
122
|
-
return round(total_frames / fps, 2) if fps > 0 else None # Divide frames by FPS to get duration (seconds)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
128
|
-
"""
|
|
129
|
-
Serializer to update patient information in the `SensitiveMeta` table.
|
|
130
|
-
Handles validation and saves the data directly in the serializer.
|
|
131
|
-
"""
|
|
132
|
-
|
|
133
|
-
sensitive_meta_id = serializers.IntegerField(write_only=True) # Needed for lookup but not included in response
|
|
134
|
-
|
|
135
|
-
class Meta:
|
|
136
|
-
model = SensitiveMeta
|
|
137
|
-
fields = ['sensitive_meta_id', 'patient_first_name', 'patient_last_name', 'patient_dob', 'examination_date']
|
|
138
|
-
|
|
139
|
-
def validate(self, data):
|
|
140
|
-
"""
|
|
141
|
-
Validate input data before updating.
|
|
142
|
-
"""
|
|
143
|
-
errors = {}
|
|
144
|
-
|
|
145
|
-
# Ensure the SensitiveMeta ID exists
|
|
146
|
-
sensitive_meta_id = data.get("sensitive_meta_id")
|
|
147
|
-
if not SensitiveMeta.objects.filter(id=sensitive_meta_id).exists():
|
|
148
|
-
raise serializers.ValidationError({"sensitive_meta_id": "SensitiveMeta entry not found."})
|
|
149
|
-
|
|
150
|
-
# Validate each field separately
|
|
151
|
-
if 'patient_first_name' in data and (data['patient_first_name'] is None or data['patient_first_name'].strip() == ""):
|
|
152
|
-
errors['patient_first_name'] = "First name cannot be empty."
|
|
153
|
-
|
|
154
|
-
if 'patient_last_name' in data and (data['patient_last_name'] is None or data['patient_last_name'].strip() == ""):
|
|
155
|
-
errors['patient_last_name'] = "Last name cannot be empty."
|
|
156
|
-
|
|
157
|
-
if 'patient_dob' in data and not data['patient_dob']:
|
|
158
|
-
errors['patient_dob'] = "Date of birth is required."
|
|
159
|
-
|
|
160
|
-
if 'examination_date' in data and not data['examination_date']:
|
|
161
|
-
errors['examination_date'] = "Examination date is required."
|
|
162
|
-
|
|
163
|
-
if errors:
|
|
164
|
-
raise serializers.ValidationError(errors) # Raise errors before saving
|
|
165
|
-
|
|
166
|
-
return data
|
|
167
|
-
|
|
168
|
-
def update(self, instance, validated_data):
|
|
169
|
-
"""
|
|
170
|
-
Update the SensitiveMeta entry directly inside the serializer.
|
|
171
|
-
"""
|
|
172
|
-
# Remove `sensitive_meta_id` before updating
|
|
173
|
-
validated_data.pop("sensitive_meta_id", None)
|
|
174
|
-
|
|
175
|
-
for attr, value in validated_data.items():
|
|
176
|
-
setattr(instance, attr, value) # Set attributes dynamically
|
|
177
|
-
|
|
178
|
-
instance.save() # Save changes
|
|
179
|
-
return instance # Return updated instance
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
from rest_framework import serializers
|
|
2
|
-
from endoreg_db.models import VideoFile, VideoImportMeta, LabelVideoSegment, VideoMeta, SensitiveMeta
|
|
3
|
-
# serializers/video.py
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from rest_framework import serializers
|
|
6
|
-
from django.conf import settings
|
|
7
|
-
|
|
8
|
-
from .utils import calc_duration_seconds # wrap your OpenCV helper
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class VideoBriefSer(serializers.ModelSerializer):
|
|
12
|
-
class Meta:
|
|
13
|
-
model = VideoFile
|
|
14
|
-
fields = ["id", "original_file_name", "sensitive_meta_id"]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class VideoDetailSer(VideoBriefSer):
|
|
18
|
-
patient_first_name = serializers.CharField(source="sensitive_meta.patient_first_name", read_only=True)
|
|
19
|
-
patient_last_name = serializers.CharField(source="sensitive_meta.patient_last_name", read_only=True)
|
|
20
|
-
patient_dob = serializers.DateField (source="sensitive_meta.patient_dob", read_only=True)
|
|
21
|
-
examination_date = serializers.DateField (source="sensitive_meta.examination_date", read_only=True)
|
|
22
|
-
|
|
23
|
-
file = serializers.SerializerMethodField()
|
|
24
|
-
full_path = serializers.SerializerMethodField()
|
|
25
|
-
duration = serializers.SerializerMethodField()
|
|
26
|
-
video_url = serializers.SerializerMethodField()
|
|
27
|
-
|
|
28
|
-
class Meta(VideoBriefSer.Meta):
|
|
29
|
-
fields = VideoBriefSer.Meta.fields + [
|
|
30
|
-
"file", "full_path", "video_url",
|
|
31
|
-
"patient_first_name", "patient_last_name",
|
|
32
|
-
"patient_dob", "examination_date",
|
|
33
|
-
"duration",
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
# helpers ----------------------------------------------------------
|
|
37
|
-
def get_file(self, obj):
|
|
38
|
-
f = obj.processed_file or obj.raw_file
|
|
39
|
-
return f.name if f else None
|
|
40
|
-
|
|
41
|
-
def get_full_path(self, obj):
|
|
42
|
-
f = obj.processed_file or obj.raw_file
|
|
43
|
-
return str(Path(settings.MEDIA_ROOT) / f.name) if f else None
|
|
44
|
-
|
|
45
|
-
def get_video_url(self, obj):
|
|
46
|
-
req = self.context.get("request")
|
|
47
|
-
return req.build_absolute_uri(f"/api/media/videos/{obj.pk}/") if req else None
|
|
48
|
-
|
|
49
|
-
def get_duration(self, obj):
|
|
50
|
-
return obj.duration or calc_duration_seconds(obj)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class SensitiveMetaUpdateSer(serializers.ModelSerializer):
|
|
54
|
-
sensitive_meta_id = serializers.IntegerField(write_only=True)
|
|
55
|
-
|
|
56
|
-
class Meta:
|
|
57
|
-
model = SensitiveMeta
|
|
58
|
-
fields = ["sensitive_meta_id", "patient_first_name",
|
|
59
|
-
"patient_last_name", "patient_dob", "examination_date"]
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class VideoImportMetaSerializer(serializers.ModelSerializer):
|
|
63
|
-
class Meta:
|
|
64
|
-
model = VideoImportMeta
|
|
65
|
-
fields = "__all__"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class LabelVideoSegmentSerializer(serializers.ModelSerializer):
|
|
69
|
-
class Meta:
|
|
70
|
-
model = LabelVideoSegment
|
|
71
|
-
fields = "__all__"
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from rest_framework import serializers
|
|
3
|
-
from django.conf import settings
|
|
4
|
-
from ...models import RawPdfFile, SensitiveMeta
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class PDFFileForMetaSerializer(serializers.ModelSerializer):
|
|
8
|
-
"""
|
|
9
|
-
Serializer to fetch PDF metadata along with linked `SensitiveMeta` details.
|
|
10
|
-
Implements validation and ensures Vue.js can process errors easily.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
# Fetch patient details from `SensitiveMeta`
|
|
14
|
-
patient_first_name = serializers.CharField(source="sensitive_meta.patient_first_name", read_only=True)
|
|
15
|
-
patient_last_name = serializers.CharField(source="sensitive_meta.patient_last_name", read_only=True)
|
|
16
|
-
patient_dob = serializers.CharField(source="sensitive_meta.patient_dob", read_only=True)
|
|
17
|
-
examination_date = serializers.CharField(source="sensitive_meta.examination_date", read_only=True)
|
|
18
|
-
|
|
19
|
-
# PDF file URL where Vue.js can fetch the document
|
|
20
|
-
pdf_url = serializers.SerializerMethodField()
|
|
21
|
-
|
|
22
|
-
# Full absolute path of the PDF file
|
|
23
|
-
full_pdf_path = serializers.SerializerMethodField()
|
|
24
|
-
|
|
25
|
-
# Direct file path from the database
|
|
26
|
-
file = serializers.SerializerMethodField()
|
|
27
|
-
|
|
28
|
-
class Meta:
|
|
29
|
-
model = RawPdfFile
|
|
30
|
-
fields = ['id', 'file', 'pdf_url', 'full_pdf_path',
|
|
31
|
-
'sensitive_meta_id', 'patient_first_name',
|
|
32
|
-
'patient_last_name', 'patient_dob', 'examination_date']
|
|
33
|
-
|
|
34
|
-
@staticmethod
|
|
35
|
-
def get_next_pdf(last_id=None):
|
|
36
|
-
"""
|
|
37
|
-
Retrieves the first available PDF if `last_id` is NOT provided.
|
|
38
|
-
Otherwise, fetches the next available PDF where `id > last_id`.
|
|
39
|
-
"""
|
|
40
|
-
query_filter = {}
|
|
41
|
-
if last_id is not None:
|
|
42
|
-
try:
|
|
43
|
-
query_filter = {"id__gt": int(last_id)}
|
|
44
|
-
except ValueError:
|
|
45
|
-
# If last_id is not a valid integer, treat it as if no ID was provided.
|
|
46
|
-
# This prevents a crash and safely defaults to fetching the first PDF.
|
|
47
|
-
query_filter = {}
|
|
48
|
-
|
|
49
|
-
# Get the next available PDF
|
|
50
|
-
pdf_entry = RawPdfFile.objects.select_related("sensitive_meta").filter(**query_filter).order_by('id').first()
|
|
51
|
-
|
|
52
|
-
return pdf_entry # Returns a model instance or None
|
|
53
|
-
|
|
54
|
-
def get_pdf_url(self, obj):
|
|
55
|
-
"""
|
|
56
|
-
Generates an absolute URL for accessing the PDF associated with the given object.
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
The full URL as a string if the file exists; otherwise, None.
|
|
60
|
-
"""
|
|
61
|
-
request = self.context.get('request')
|
|
62
|
-
print("---------------------here :",obj.file)
|
|
63
|
-
if request and obj.file:
|
|
64
|
-
return request.build_absolute_uri(f"/pdf/sensitivemeta/?id={obj.id}") # Constructs full API endpoint
|
|
65
|
-
return None # Return None if file is missing
|
|
66
|
-
|
|
67
|
-
def get_file(self, obj):
|
|
68
|
-
"""
|
|
69
|
-
Retrieves the relative file path of the PDF from the database.
|
|
70
|
-
|
|
71
|
-
Returns:
|
|
72
|
-
The relative file path as a string, or None if no file is linked.
|
|
73
|
-
"""
|
|
74
|
-
if not obj.file:
|
|
75
|
-
return None # No file linked
|
|
76
|
-
return str(obj.file.name).strip() # Ensures clean output
|
|
77
|
-
|
|
78
|
-
def get_full_pdf_path(self, obj):
|
|
79
|
-
"""
|
|
80
|
-
Constructs the full absolute file path using `settings.MEDIA_ROOT`.
|
|
81
|
-
"""
|
|
82
|
-
if not obj.file:
|
|
83
|
-
return None # No file linked
|
|
84
|
-
|
|
85
|
-
pdf_relative_path = str(obj.file.name)
|
|
86
|
-
|
|
87
|
-
full_path = Path(settings.MEDIA_ROOT) / pdf_relative_path
|
|
88
|
-
|
|
89
|
-
return str(full_path) if full_path.exists() else None # Returns path or None if file is missing
|
|
90
|
-
|
|
91
|
-
def validate(self, data):
|
|
92
|
-
"""
|
|
93
|
-
Validate input data to ensure a PDF file is provided and the referenced sensitive_meta_id exists.
|
|
94
|
-
|
|
95
|
-
Raises:
|
|
96
|
-
serializers.ValidationError: If the PDF file is missing or the sensitive_meta_id does not correspond to an existing SensitiveMeta record.
|
|
97
|
-
|
|
98
|
-
Returns:
|
|
99
|
-
dict: The validated input data if all checks pass.
|
|
100
|
-
"""
|
|
101
|
-
errors = {}
|
|
102
|
-
|
|
103
|
-
if 'file' in data and not data['file']:
|
|
104
|
-
errors['file'] = "A valid PDF file is required."
|
|
105
|
-
|
|
106
|
-
if 'sensitive_meta_id' in data and not SensitiveMeta.objects.filter(id=data['sensitive_meta_id']).exists():
|
|
107
|
-
errors['sensitive_meta_id'] = "The provided sensitive_meta_id does not exist."
|
|
108
|
-
|
|
109
|
-
if errors:
|
|
110
|
-
raise serializers.ValidationError(errors) # Returns structured error response
|
|
111
|
-
|
|
112
|
-
return data # Returns validated data
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import SensitiveMeta
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from django.utils import timezone
|
|
5
|
-
from rest_framework import serializers
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ReportMetaSerializer(serializers.ModelSerializer):
|
|
9
|
-
"""
|
|
10
|
-
Serializer für Report-Metadaten basierend auf SensitiveMeta
|
|
11
|
-
"""
|
|
12
|
-
# Füge fehlende Zeitstempel-Felder hinzu
|
|
13
|
-
created_at = serializers.SerializerMethodField()
|
|
14
|
-
updated_at = serializers.SerializerMethodField()
|
|
15
|
-
casenumber = serializers.CharField(source='case_number', allow_blank=True, allow_null=True)
|
|
16
|
-
|
|
17
|
-
class Meta:
|
|
18
|
-
model = SensitiveMeta
|
|
19
|
-
fields = [
|
|
20
|
-
'id', 'patient_first_name', 'patient_last_name',
|
|
21
|
-
'patient_gender', 'patient_dob', 'examination_date',
|
|
22
|
-
'casenumber', 'created_at', 'updated_at'
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
def get_created_at(self, obj):
|
|
26
|
-
"""
|
|
27
|
-
Retrieve the `created_at` timestamp from the SensitiveMeta instance, or return the current time if unavailable.
|
|
28
|
-
|
|
29
|
-
Parameters:
|
|
30
|
-
obj: The SensitiveMeta instance being serialized.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
datetime: The `created_at` timestamp, or the current time as a fallback.
|
|
34
|
-
"""
|
|
35
|
-
if hasattr(obj, 'created_at') and obj.created_at:
|
|
36
|
-
return obj.created_at
|
|
37
|
-
# Fallback wenn SensitiveMeta kein created_at hat
|
|
38
|
-
return timezone.now()
|
|
39
|
-
|
|
40
|
-
def get_updated_at(self, obj):
|
|
41
|
-
"""
|
|
42
|
-
Return the `updated_at` timestamp from the SensitiveMeta instance, or fall back to the `created_at` timestamp if `updated_at` is missing or null.
|
|
43
|
-
|
|
44
|
-
Parameters:
|
|
45
|
-
obj: The SensitiveMeta instance being serialized.
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
A datetime representing when the instance was last updated, or created if no update timestamp is available.
|
|
49
|
-
"""
|
|
50
|
-
if hasattr(obj, 'updated_at') and obj.updated_at:
|
|
51
|
-
return obj.updated_at
|
|
52
|
-
# Fallback wenn SensitiveMeta kein updated_at hat
|
|
53
|
-
return self.get_created_at(obj)
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import TYPE_CHECKING, Literal
|
|
3
|
-
from django.utils import timezone
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
from endoreg_db.models import RawPdfFile
|
|
7
|
-
|
|
8
|
-
class ReportStatusMixin:
|
|
9
|
-
"""
|
|
10
|
-
Mixin class for report serializers to provide status, updated_at, and file_type fields.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
def get_status(self, obj:"RawPdfFile") -> Literal['approved'] | Literal['pending']:
|
|
14
|
-
"""
|
|
15
|
-
Return the report status as 'approved' if the report has been processed, otherwise 'pending'.
|
|
16
|
-
|
|
17
|
-
Parameters:
|
|
18
|
-
obj (RawPdfFile): The report file instance to check.
|
|
19
|
-
|
|
20
|
-
Returns:
|
|
21
|
-
Literal['approved'] | Literal['pending']: The status of the report based on its processing state.
|
|
22
|
-
"""
|
|
23
|
-
if obj.state_report_processed:
|
|
24
|
-
return 'approved'
|
|
25
|
-
if obj.state_report_processing_required:
|
|
26
|
-
return 'pending'
|
|
27
|
-
return 'pending'
|
|
28
|
-
|
|
29
|
-
def get_updated_at(self, obj:"RawPdfFile") -> "timezone.datetime":
|
|
30
|
-
"""
|
|
31
|
-
Return the last update time for the given RawPdfFile object.
|
|
32
|
-
|
|
33
|
-
If the object's creation date is available, it is returned; otherwise, the current time is used.
|
|
34
|
-
"""
|
|
35
|
-
return obj.date_created if obj.date_created else timezone.now()
|
|
36
|
-
|
|
37
|
-
def get_file_type(self, obj:"RawPdfFile" ) -> "str":
|
|
38
|
-
"""
|
|
39
|
-
Return the file type of the associated file as a lowercase string without the leading dot.
|
|
40
|
-
|
|
41
|
-
If the object has no file, returns 'unknown'.
|
|
42
|
-
"""
|
|
43
|
-
if obj.file:
|
|
44
|
-
return Path(obj.file.name).suffix.lower().lstrip('.')
|
|
45
|
-
return 'unknown'
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
from endoreg_db.serializers.meta.report_meta import ReportMetaSerializer
|
|
3
|
-
from endoreg_db.serializers.report.secure_file_url import SecureFileUrlSerializer
|
|
4
|
-
from endoreg_db.serializers.report.mixins import ReportStatusMixin
|
|
5
|
-
|
|
6
|
-
from django.utils import timezone
|
|
7
|
-
from rest_framework import serializers
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import uuid
|
|
11
|
-
from datetime import timedelta
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ReportDataSerializer(ReportStatusMixin, serializers.ModelSerializer):
|
|
16
|
-
"""
|
|
17
|
-
Hauptserializer für Report-Daten mit sicherer URL
|
|
18
|
-
"""
|
|
19
|
-
report_meta = ReportMetaSerializer(source='sensitive_meta', read_only=True)
|
|
20
|
-
secure_file_url = SecureFileUrlSerializer(read_only=True)
|
|
21
|
-
file_type = serializers.SerializerMethodField()
|
|
22
|
-
|
|
23
|
-
# Status und updated_at hinzufügen (da sie im RawPdfFile Model fehlen)
|
|
24
|
-
status = serializers.SerializerMethodField()
|
|
25
|
-
updated_at = serializers.SerializerMethodField()
|
|
26
|
-
|
|
27
|
-
class Meta:
|
|
28
|
-
model = RawPdfFile
|
|
29
|
-
fields = [
|
|
30
|
-
'id', 'anonymized_text', 'status', 'report_meta',
|
|
31
|
-
'secure_file_url', 'file_type', 'created_at', 'updated_at'
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
def get_updated_at(self, obj):
|
|
35
|
-
"""
|
|
36
|
-
Return the updated timestamp for the object, using `created_at` if available or the current time otherwise.
|
|
37
|
-
"""
|
|
38
|
-
return obj.created_at if obj.created_at else timezone.now()
|
|
39
|
-
|
|
40
|
-
def get_file_type(self, obj):
|
|
41
|
-
"""
|
|
42
|
-
Return the file extension of the associated file in lowercase, or 'unknown' if no file is present.
|
|
43
|
-
|
|
44
|
-
Parameters:
|
|
45
|
-
obj: The object instance containing the file.
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
str: The file extension without the leading dot, or 'unknown' if the file is missing.
|
|
49
|
-
"""
|
|
50
|
-
if obj.file:
|
|
51
|
-
return Path(obj.file.name).suffix.lower().lstrip('.')
|
|
52
|
-
return 'unknown'
|
|
53
|
-
|
|
54
|
-
def to_representation(self, instance):
|
|
55
|
-
"""
|
|
56
|
-
Returns the serialized representation of the instance, including a secure file URL if a file exists and a request context is available.
|
|
57
|
-
"""
|
|
58
|
-
data = super().to_representation(instance)
|
|
59
|
-
|
|
60
|
-
# Sichere URL generieren wenn file vorhanden
|
|
61
|
-
if instance.file and hasattr(instance.file, 'url'):
|
|
62
|
-
request = self.context.get('request')
|
|
63
|
-
if request:
|
|
64
|
-
# Sichere URL mit Token generieren
|
|
65
|
-
secure_url_data = self._generate_secure_url(instance, request)
|
|
66
|
-
data['secure_file_url'] = secure_url_data
|
|
67
|
-
|
|
68
|
-
return data
|
|
69
|
-
|
|
70
|
-
def _generate_secure_url(self, instance, request):
|
|
71
|
-
"""
|
|
72
|
-
Generate a secure URL for downloading the file associated with the given instance, including an expiration time and file metadata.
|
|
73
|
-
|
|
74
|
-
Parameters:
|
|
75
|
-
instance: The model instance containing the file.
|
|
76
|
-
request: The HTTP request object used to build the absolute URL.
|
|
77
|
-
|
|
78
|
-
Returns:
|
|
79
|
-
dict: A dictionary containing the secure URL, expiration timestamp, file type, original filename, and file size in bytes.
|
|
80
|
-
"""
|
|
81
|
-
# Token für sichere URL generieren
|
|
82
|
-
token = str(uuid.uuid4())
|
|
83
|
-
expires_at = timezone.now() + timedelta(hours=2) # 2 Stunden gültig
|
|
84
|
-
|
|
85
|
-
# URL zusammenbauen
|
|
86
|
-
secure_url = request.build_absolute_uri(
|
|
87
|
-
f"/api/reports/{instance.id}/secure-file/?token={token}"
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
# Dateigröße ermitteln
|
|
91
|
-
file_size = 0
|
|
92
|
-
try:
|
|
93
|
-
if instance.file:
|
|
94
|
-
file_size = instance.file.size
|
|
95
|
-
except OSError:
|
|
96
|
-
# Datei nicht verfügbar oder Berechtigung fehlt
|
|
97
|
-
file_size = 0
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
'url': secure_url,
|
|
101
|
-
'expires_at': expires_at,
|
|
102
|
-
'file_type': self.get_file_type(instance),
|
|
103
|
-
'original_filename': Path(instance.file.name).name if instance.file else 'unknown',
|
|
104
|
-
'file_size': file_size
|
|
105
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
from endoreg_db.serializers.meta import ReportMetaSerializer
|
|
3
|
-
from endoreg_db.serializers.report.mixins import ReportStatusMixin
|
|
4
|
-
|
|
5
|
-
from django.utils import timezone
|
|
6
|
-
from rest_framework import serializers
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ReportListSerializer(ReportStatusMixin, serializers.ModelSerializer):
|
|
13
|
-
"""
|
|
14
|
-
Vereinfachter Serializer für Report-Listen
|
|
15
|
-
"""
|
|
16
|
-
report_meta = ReportMetaSerializer(source='sensitive_meta', read_only=True)
|
|
17
|
-
file_type = serializers.SerializerMethodField()
|
|
18
|
-
updated_at = serializers.SerializerMethodField()
|
|
19
|
-
|
|
20
|
-
class Meta:
|
|
21
|
-
model = RawPdfFile
|
|
22
|
-
fields = ['id', 'status', 'report_meta', 'file_type', 'created_at', 'updated_at']
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from rest_framework import serializers
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class SecureFileUrlSerializer(serializers.Serializer):
|
|
5
|
-
"""
|
|
6
|
-
Serializer für sichere File-URLs mit Ablaufzeit
|
|
7
|
-
"""
|
|
8
|
-
url = serializers.URLField()
|
|
9
|
-
expires_at = serializers.DateTimeField()
|
|
10
|
-
file_type = serializers.CharField(max_length=20)
|
|
11
|
-
original_filename = serializers.CharField(max_length=255)
|
|
12
|
-
file_size = serializers.IntegerField()
|
|
13
|
-
|
|
14
|
-
def create(self, validated_data):
|
|
15
|
-
# Nicht implementiert, da nur für Ausgabe verwendet
|
|
16
|
-
"""
|
|
17
|
-
Raises NotImplementedError to indicate that instance creation is not supported for this serializer.
|
|
18
|
-
"""
|
|
19
|
-
raise NotImplementedError("SecureFileUrlSerializer ist nur für Ausgabe gedacht")
|
|
20
|
-
|
|
21
|
-
def update(self, instance, validated_data):
|
|
22
|
-
# Nicht implementiert, da nur für Ausgabe verwendet
|
|
23
|
-
"""
|
|
24
|
-
Raises NotImplementedError to indicate that updating is not supported, as this serializer is intended for output only.
|
|
25
|
-
"""
|
|
26
|
-
raise NotImplementedError("SecureFileUrlSerializer ist nur für Ausgabe gedacht")
|