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,112 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
from endoreg_db.serializers.report.report_list import ReportListSerializer
|
|
3
|
-
|
|
4
|
-
from django.core.paginator import Paginator
|
|
5
|
-
from django.db.models import Q
|
|
6
|
-
from rest_framework import status
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
from rest_framework.views import APIView
|
|
9
|
-
|
|
10
|
-
import logging
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
class ReportListView(APIView):
|
|
14
|
-
"""
|
|
15
|
-
API-Endpunkt für paginierte Report-Listen mit optionaler Filterung
|
|
16
|
-
GET /api/reports/
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
def get(self, request):
|
|
20
|
-
try:
|
|
21
|
-
# Query-Parameter abrufen
|
|
22
|
-
page = int(request.GET.get('page', 1))
|
|
23
|
-
page_size = min(int(request.GET.get('page_size', 20)), 100) # Max 100 pro Seite
|
|
24
|
-
|
|
25
|
-
# Filter-Parameter
|
|
26
|
-
file_type_filter = request.GET.get('file_type')
|
|
27
|
-
patient_name_filter = request.GET.get('patient_name')
|
|
28
|
-
casenumber_filter = request.GET.get('casenumber')
|
|
29
|
-
date_from = request.GET.get('date_from')
|
|
30
|
-
date_to = request.GET.get('date_to')
|
|
31
|
-
|
|
32
|
-
# Base QuerySet mit related data
|
|
33
|
-
queryset = RawPdfFile.objects.select_related('sensitive_meta').all()
|
|
34
|
-
|
|
35
|
-
# Filter anwenden
|
|
36
|
-
if patient_name_filter:
|
|
37
|
-
queryset = queryset.filter(
|
|
38
|
-
Q(sensitive_meta__patient_first_name__icontains=patient_name_filter) |
|
|
39
|
-
Q(sensitive_meta__patient_last_name__icontains=patient_name_filter)
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
if casenumber_filter:
|
|
43
|
-
queryset = queryset.filter(
|
|
44
|
-
sensitive_meta__case_number__icontains=casenumber_filter
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
if file_type_filter:
|
|
48
|
-
# Filter basierend auf Dateiendung
|
|
49
|
-
queryset = queryset.filter(file__endswith=f'.{file_type_filter}')
|
|
50
|
-
|
|
51
|
-
if date_from:
|
|
52
|
-
queryset = queryset.filter(created_at__gte=date_from)
|
|
53
|
-
|
|
54
|
-
if date_to:
|
|
55
|
-
queryset = queryset.filter(created_at__lte=date_to)
|
|
56
|
-
|
|
57
|
-
# Sortierung (neueste zuerst)
|
|
58
|
-
queryset = queryset.order_by('-created_at')
|
|
59
|
-
|
|
60
|
-
# Paginierung
|
|
61
|
-
paginator = Paginator(queryset, page_size)
|
|
62
|
-
|
|
63
|
-
if page > paginator.num_pages:
|
|
64
|
-
return Response({
|
|
65
|
-
'count': paginator.count,
|
|
66
|
-
'next': None,
|
|
67
|
-
'previous': None,
|
|
68
|
-
'results': []
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
page_obj = paginator.get_page(page)
|
|
72
|
-
|
|
73
|
-
# Serialisierung
|
|
74
|
-
serializer = ReportListSerializer(
|
|
75
|
-
page_obj.object_list,
|
|
76
|
-
many=True,
|
|
77
|
-
context={'request': request}
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
# URLs für Paginierung
|
|
81
|
-
next_url = None
|
|
82
|
-
previous_url = None
|
|
83
|
-
|
|
84
|
-
if page_obj.has_next():
|
|
85
|
-
next_url = request.build_absolute_uri(
|
|
86
|
-
f"?page={page_obj.next_page_number()}&page_size={page_size}"
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
if page_obj.has_previous():
|
|
90
|
-
previous_url = request.build_absolute_uri(
|
|
91
|
-
f"?page={page_obj.previous_page_number()}&page_size={page_size}"
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
return Response({
|
|
95
|
-
'count': paginator.count,
|
|
96
|
-
'next': next_url,
|
|
97
|
-
'previous': previous_url,
|
|
98
|
-
'results': serializer.data
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
except ValueError as e:
|
|
102
|
-
logger.error("Ungültige Parameter in ReportListView: %s", str(e))
|
|
103
|
-
return Response(
|
|
104
|
-
{"error": "Ungültige Parameter"},
|
|
105
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
106
|
-
)
|
|
107
|
-
except (AttributeError, TypeError, OSError) as e:
|
|
108
|
-
logger.error("Fehler in ReportListView: %s", str(e))
|
|
109
|
-
return Response(
|
|
110
|
-
{"error": "Fehler beim Laden der Reports"},
|
|
111
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
112
|
-
)
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
from endoreg_db.serializers.report.report import ReportDataSerializer
|
|
3
|
-
|
|
4
|
-
from django.shortcuts import get_object_or_404
|
|
5
|
-
from rest_framework import status
|
|
6
|
-
from rest_framework.response import Response
|
|
7
|
-
from rest_framework.views import APIView
|
|
8
|
-
|
|
9
|
-
import logging
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
class ReportWithSecureUrlView(APIView):
|
|
13
|
-
"""
|
|
14
|
-
API-Endpunkt für Reports mit sicherer URL-Generierung
|
|
15
|
-
GET /api/reports/{report_id}/with-secure-url/
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
def get(self, request, report_id):
|
|
19
|
-
try:
|
|
20
|
-
report = get_object_or_404(RawPdfFile, id=report_id)
|
|
21
|
-
serializer = ReportDataSerializer(report, context={'request': request})
|
|
22
|
-
return Response(serializer.data)
|
|
23
|
-
except (ValueError, TypeError) as e:
|
|
24
|
-
logger.error("Fehler beim Laden des Reports %s: %s", report_id, str(e))
|
|
25
|
-
return Response(
|
|
26
|
-
{"error": "Report konnte nicht geladen werden"},
|
|
27
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
28
|
-
)
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
import os
|
|
3
|
-
import mimetypes
|
|
4
|
-
from django.http import FileResponse, Http404
|
|
5
|
-
from rest_framework import viewsets, decorators, status
|
|
6
|
-
from rest_framework.views import APIView
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
from rest_framework.decorators import api_view, permission_classes
|
|
9
|
-
|
|
10
|
-
from ...serializers.label_video_segment.label_video_segment_update import LabelSegmentUpdateSerializer
|
|
11
|
-
|
|
12
|
-
from ...serializers.label.label import LabelSerializer
|
|
13
|
-
|
|
14
|
-
from ...serializers.video.video_file_list import VideoFileListSerializer
|
|
15
|
-
from ...models import VideoFile, Label, LabelVideoSegment
|
|
16
|
-
from ...serializers.video.segmentation import VideoFileSerializer
|
|
17
|
-
from ...utils.permissions import DEBUG_PERMISSIONS
|
|
18
|
-
|
|
19
|
-
# Phase 3.2: Import video streaming functionality from dedicated module
|
|
20
|
-
# Phase 3.2: VideoStreamView and _stream_video_file moved to video_stream.py
|
|
21
|
-
from .video_stream import _stream_video_file
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class VideoViewSet(viewsets.ReadOnlyModelViewSet):
|
|
25
|
-
"""
|
|
26
|
-
/api/videos/ → list of metadata (JSON)
|
|
27
|
-
/api/videos/<id>/ → single metadata (JSON)
|
|
28
|
-
/videos/<id>/stream/ → raw file (FileResponse, range-aware)
|
|
29
|
-
"""
|
|
30
|
-
queryset = VideoFile.objects.all()
|
|
31
|
-
serializer_class = VideoFileListSerializer # for the list view
|
|
32
|
-
permission_classes = DEBUG_PERMISSIONS
|
|
33
|
-
|
|
34
|
-
def list(self, request, *args, **kwargs):
|
|
35
|
-
"""
|
|
36
|
-
Returns a JSON response with all video metadata and available labels.
|
|
37
|
-
|
|
38
|
-
The response includes serialized lists of all videos and labels in the database.
|
|
39
|
-
"""
|
|
40
|
-
videos = VideoFile.objects.all()
|
|
41
|
-
labels = Label.objects.all()
|
|
42
|
-
|
|
43
|
-
video_serializer = VideoFileListSerializer(videos, many=True)
|
|
44
|
-
label_serializer = LabelSerializer(labels, many=True)
|
|
45
|
-
|
|
46
|
-
return Response({
|
|
47
|
-
"videos": video_serializer.data,
|
|
48
|
-
"labels": label_serializer.data
|
|
49
|
-
}, status=status.HTTP_200_OK)
|
|
50
|
-
|
|
51
|
-
# ---------- JSON ---------- #
|
|
52
|
-
def retrieve(self, request, *args, **kwargs):
|
|
53
|
-
"""
|
|
54
|
-
Retrieves detailed metadata for a specific video as a JSON response.
|
|
55
|
-
|
|
56
|
-
Returns:
|
|
57
|
-
JSON representation of the requested video's metadata.
|
|
58
|
-
"""
|
|
59
|
-
obj = self.get_object()
|
|
60
|
-
return Response(VideoFileSerializer(obj, context={'request': request}).data)
|
|
61
|
-
|
|
62
|
-
# ---------- BYTES ---------- #
|
|
63
|
-
@decorators.action(methods=['get'], detail=True,
|
|
64
|
-
url_path='stream', renderer_classes=[]) # <- disable HTML & JSON renderers
|
|
65
|
-
def stream(self, request, pk=None):
|
|
66
|
-
"""
|
|
67
|
-
Streams the raw video file for the specified video with HTTP range and CORS support.
|
|
68
|
-
"""
|
|
69
|
-
try:
|
|
70
|
-
vf: VideoFile = self.get_object()
|
|
71
|
-
frontend_origin = os.environ.get('FRONTEND_ORIGIN', 'http://localhost:8000')
|
|
72
|
-
return _stream_video_file(vf, frontend_origin)
|
|
73
|
-
except Http404:
|
|
74
|
-
# Re-raise Http404 exceptions as they should bubble up
|
|
75
|
-
raise
|
|
76
|
-
except Exception as e:
|
|
77
|
-
# Log unexpected errors and convert to Http404
|
|
78
|
-
import logging
|
|
79
|
-
logger = logging.getLogger(__name__)
|
|
80
|
-
logger.error(f"Unexpected error in video stream for pk={pk}: {str(e)}")
|
|
81
|
-
raise Http404("Video streaming failed")
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# Phase 3.2: VideoStreamView moved to video_stream.py - imported at top
|
|
85
|
-
# Old implementation removed to avoid duplication
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class VideoLabelView(APIView):
|
|
89
|
-
"""
|
|
90
|
-
API to fetch time segments (start & end times in seconds) for a specific label.
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
def get(self, request, video_id, label_name):
|
|
94
|
-
"""
|
|
95
|
-
Retrieves time segments and frame-level predictions for a specific label on a video.
|
|
96
|
-
|
|
97
|
-
Returns a JSON response containing the label name, a list of time segments (with frame ranges and timestamps), and frame-wise prediction data. Responds with HTTP 404 if the video or label does not exist, or HTTP 200 with empty data if no segments are found. Returns HTTP 500 with an error message for unexpected exceptions.
|
|
98
|
-
"""
|
|
99
|
-
try:
|
|
100
|
-
# Verify video exists
|
|
101
|
-
video_entry = VideoFile.objects.get(id=video_id)
|
|
102
|
-
|
|
103
|
-
# Try to get label by name
|
|
104
|
-
try:
|
|
105
|
-
label = Label.objects.get(name=label_name)
|
|
106
|
-
except Label.DoesNotExist:
|
|
107
|
-
return Response({
|
|
108
|
-
"error": f"Label '{label_name}' not found in database"
|
|
109
|
-
}, status=status.HTTP_404_NOT_FOUND)
|
|
110
|
-
|
|
111
|
-
# Get label video segments directly from the database
|
|
112
|
-
label_segments = LabelVideoSegment.objects.filter(
|
|
113
|
-
video_file=video_entry,
|
|
114
|
-
label=label
|
|
115
|
-
).order_by('start_frame_number')
|
|
116
|
-
|
|
117
|
-
if not label_segments.exists():
|
|
118
|
-
# No segments found for this label, return empty data
|
|
119
|
-
return Response({
|
|
120
|
-
"label": label_name,
|
|
121
|
-
"time_segments": [],
|
|
122
|
-
"frame_predictions": {}
|
|
123
|
-
}, status=status.HTTP_200_OK)
|
|
124
|
-
|
|
125
|
-
# Convert segments to time-based format
|
|
126
|
-
# Fix: Ensure fps is a number, not a string
|
|
127
|
-
fps_raw = getattr(video_entry, 'fps', None) or (video_entry.get_fps() if hasattr(video_entry, 'get_fps') else 25)
|
|
128
|
-
|
|
129
|
-
# Convert fps to float if it's a string
|
|
130
|
-
try:
|
|
131
|
-
if isinstance(fps_raw, str):
|
|
132
|
-
fps = float(fps_raw)
|
|
133
|
-
elif isinstance(fps_raw, (int, float)):
|
|
134
|
-
fps = float(fps_raw)
|
|
135
|
-
else:
|
|
136
|
-
fps = 25.0 # Default fallback
|
|
137
|
-
except (ValueError, TypeError):
|
|
138
|
-
fps = 25.0 # Default fallback if conversion fails
|
|
139
|
-
|
|
140
|
-
# Ensure fps is positive
|
|
141
|
-
if fps <= 0:
|
|
142
|
-
fps = 25.0
|
|
143
|
-
|
|
144
|
-
time_segments = []
|
|
145
|
-
frame_predictions = {}
|
|
146
|
-
|
|
147
|
-
for segment in label_segments:
|
|
148
|
-
# Now fps is guaranteed to be a float
|
|
149
|
-
start_time = segment.start_frame_number / fps
|
|
150
|
-
end_time = segment.end_frame_number / fps
|
|
151
|
-
|
|
152
|
-
segment_data = {
|
|
153
|
-
"segment_id": segment.id,
|
|
154
|
-
"segment_start": segment.start_frame_number,
|
|
155
|
-
"segment_end": segment.end_frame_number,
|
|
156
|
-
"start_time": round(start_time, 2),
|
|
157
|
-
"end_time": round(end_time, 2),
|
|
158
|
-
"frames": {}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
# Add frame-wise data if available
|
|
162
|
-
for frame_num in range(segment.start_frame_number, segment.end_frame_number + 1):
|
|
163
|
-
frame_filename = f"frame_{str(frame_num).zfill(7)}.jpg"
|
|
164
|
-
frame_predictions[frame_num] = {
|
|
165
|
-
"frame_number": frame_num,
|
|
166
|
-
"label": label_name,
|
|
167
|
-
"confidence": 1.0 # Default confidence
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
# Fix: Safely construct frame_file_path to avoid string/string division errors
|
|
171
|
-
frame_file_path = ""
|
|
172
|
-
if hasattr(video_entry, 'frame_dir') and video_entry.frame_dir:
|
|
173
|
-
try:
|
|
174
|
-
# Ensure frame_dir is converted to Path properly
|
|
175
|
-
if isinstance(video_entry.frame_dir, str):
|
|
176
|
-
frame_dir = Path(video_entry.frame_dir)
|
|
177
|
-
elif isinstance(video_entry.frame_dir, Path):
|
|
178
|
-
frame_dir = video_entry.frame_dir
|
|
179
|
-
else:
|
|
180
|
-
# Try to convert to string first, then to Path
|
|
181
|
-
frame_dir = Path(str(video_entry.frame_dir))
|
|
182
|
-
|
|
183
|
-
frame_file_path = str(frame_dir / frame_filename)
|
|
184
|
-
except (TypeError, ValueError) as e:
|
|
185
|
-
# Log warning but don't fail the request
|
|
186
|
-
import logging
|
|
187
|
-
logger = logging.getLogger(__name__)
|
|
188
|
-
logger.warning(f"Could not construct frame path for frame {frame_num}: {e}")
|
|
189
|
-
frame_file_path = ""
|
|
190
|
-
|
|
191
|
-
segment_data["frames"][frame_num] = {
|
|
192
|
-
"frame_filename": frame_filename,
|
|
193
|
-
"frame_file_path": frame_file_path,
|
|
194
|
-
"predictions": frame_predictions[frame_num]
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
time_segments.append(segment_data)
|
|
198
|
-
|
|
199
|
-
return Response({
|
|
200
|
-
"label": label_name,
|
|
201
|
-
"time_segments": time_segments,
|
|
202
|
-
"frame_predictions": frame_predictions
|
|
203
|
-
}, status=status.HTTP_200_OK)
|
|
204
|
-
|
|
205
|
-
except VideoFile.DoesNotExist:
|
|
206
|
-
return Response({
|
|
207
|
-
"error": "Video not found"
|
|
208
|
-
}, status=status.HTTP_404_NOT_FOUND)
|
|
209
|
-
|
|
210
|
-
except Exception as e:
|
|
211
|
-
# Log the error for debugging
|
|
212
|
-
import logging
|
|
213
|
-
logger = logging.getLogger(__name__)
|
|
214
|
-
logger.error(f"Error in VideoLabelView for video {video_id}, label {label_name}: {str(e)}")
|
|
215
|
-
|
|
216
|
-
return Response({
|
|
217
|
-
"error": f"Internal error: {str(e)}"
|
|
218
|
-
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
219
|
-
|
|
220
|
-
class UpdateLabelSegmentsView(APIView):
|
|
221
|
-
"""
|
|
222
|
-
API to update or create label segments for a video.
|
|
223
|
-
"""
|
|
224
|
-
|
|
225
|
-
def put(self, request, video_id, label_id):
|
|
226
|
-
"""
|
|
227
|
-
Updates segments for a given video & label.
|
|
228
|
-
"""
|
|
229
|
-
|
|
230
|
-
# Prepare data for serializer by combining URL params with request data
|
|
231
|
-
serializer_data = {
|
|
232
|
-
"video_id": video_id, # From URL parameter
|
|
233
|
-
"label_id": label_id, # From URL parameter
|
|
234
|
-
"segments": request.data.get("segments", []) # From request body
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
# Validate input data
|
|
238
|
-
serializer = LabelSegmentUpdateSerializer(data=serializer_data)
|
|
239
|
-
|
|
240
|
-
if not serializer.is_valid():
|
|
241
|
-
return Response({"error": "Invalid segment data", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
|
|
242
|
-
|
|
243
|
-
# Process and save segment updates
|
|
244
|
-
try:
|
|
245
|
-
result = serializer.save()
|
|
246
|
-
return Response({
|
|
247
|
-
"message": "Segments updated successfully.",
|
|
248
|
-
"updated_segments": result["updated_segments"],
|
|
249
|
-
"new_segments": result["new_segments"],
|
|
250
|
-
"deleted_segments": result["deleted_segments"]
|
|
251
|
-
}, status=status.HTTP_200_OK)
|
|
252
|
-
except Exception as e:
|
|
253
|
-
return Response({
|
|
254
|
-
"error": f"Failed to update segments: {str(e)}"
|
|
255
|
-
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
256
|
-
|
|
257
|
-
@api_view(['GET'])
|
|
258
|
-
@permission_classes(DEBUG_PERMISSIONS)
|
|
259
|
-
def rerun_segmentation(request, video_id):
|
|
260
|
-
"""
|
|
261
|
-
Rerun segmentation for a specific video.
|
|
262
|
-
"""
|
|
263
|
-
try:
|
|
264
|
-
video_file = VideoFile.objects.get(id=video_id)
|
|
265
|
-
video_file.pipe_1()
|
|
266
|
-
video_file.test_after_pipe_1()
|
|
267
|
-
return Response({'status': 'success', 'message': 'Segmentation rerun successfully'})
|
|
268
|
-
except VideoFile.DoesNotExist:
|
|
269
|
-
return Response({'status': 'error', 'message': 'Video file not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
270
|
-
except Exception as e:
|
|
271
|
-
import logging
|
|
272
|
-
logger = logging.getLogger(__name__)
|
|
273
|
-
logger.error(f"Error in rerun_segmentation: {e}")
|
|
274
|
-
return Response({'status': 'error', 'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from rest_framework import status
|
|
5
|
-
from rest_framework.response import Response
|
|
6
|
-
from rest_framework.views import APIView
|
|
7
|
-
from celery import current_app
|
|
8
|
-
|
|
9
|
-
class TaskStatusView(APIView):
|
|
10
|
-
"""
|
|
11
|
-
GET /api/task-status/{task_id}/ - Get status of async task
|
|
12
|
-
"""
|
|
13
|
-
#TODO refactor, this should be specified as video task status or moved to a more appropriate module
|
|
14
|
-
permission_classes = [EnvironmentAwarePermission]
|
|
15
|
-
|
|
16
|
-
def get(self, request, task_id):
|
|
17
|
-
try:
|
|
18
|
-
task_result = current_app.AsyncResult(task_id)
|
|
19
|
-
|
|
20
|
-
response_data = {
|
|
21
|
-
'task_id': task_id,
|
|
22
|
-
'status': task_result.status,
|
|
23
|
-
'progress': 0,
|
|
24
|
-
'message': 'Task pending...'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if task_result.status == 'PENDING':
|
|
28
|
-
response_data['message'] = 'Task is waiting to be processed'
|
|
29
|
-
elif task_result.status == 'PROGRESS':
|
|
30
|
-
response_data.update(task_result.result or {})
|
|
31
|
-
elif task_result.status == 'SUCCESS':
|
|
32
|
-
response_data.update({
|
|
33
|
-
'progress': 100,
|
|
34
|
-
'message': 'Task completed successfully',
|
|
35
|
-
'result': task_result.result
|
|
36
|
-
})
|
|
37
|
-
elif task_result.status == 'FAILURE':
|
|
38
|
-
response_data.update({
|
|
39
|
-
'message': str(task_result.result),
|
|
40
|
-
'error': True
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
return Response(response_data, status=status.HTTP_200_OK)
|
|
44
|
-
|
|
45
|
-
except Exception as e:
|
|
46
|
-
return Response(
|
|
47
|
-
{"error": f"Failed to get task status: {str(e)}"},
|
|
48
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
49
|
-
)
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
from django.shortcuts import render, get_object_or_404
|
|
2
|
-
from ...models import VideoFile
|
|
3
|
-
import json
|
|
4
|
-
from ...serializers.video import VideoFileSerializer
|
|
5
|
-
|
|
6
|
-
def video_timeline_view(request, video_id):
|
|
7
|
-
"""
|
|
8
|
-
Fetches 'outside' label segments and passes their timestamps to the template.
|
|
9
|
-
"""
|
|
10
|
-
video_entry = get_object_or_404(VideoFile, id=video_id)
|
|
11
|
-
|
|
12
|
-
# Get metadata (Assumes serializer method exists)
|
|
13
|
-
video_serializer = VideoFileSerializer(video_entry, context={'request': request})
|
|
14
|
-
label_segments = video_serializer.get_label_time_segments(video_entry)
|
|
15
|
-
|
|
16
|
-
segments = []
|
|
17
|
-
frame_markers = [] # Store frame timestamps
|
|
18
|
-
fps = 50 # Fixed FPS
|
|
19
|
-
|
|
20
|
-
# Ensure "outside" label exists
|
|
21
|
-
if "outside" in label_segments:
|
|
22
|
-
for segment in label_segments["outside"]["time_ranges"]:
|
|
23
|
-
segments.append({
|
|
24
|
-
"start_time": segment["start_time"],
|
|
25
|
-
"end_time": segment["end_time"]
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
# Extract frame timestamps for markers
|
|
29
|
-
for frame_num, _ in segment["frames"].items():
|
|
30
|
-
time_in_seconds = frame_num / fps
|
|
31
|
-
frame_markers.append(time_in_seconds)
|
|
32
|
-
|
|
33
|
-
# Set video duration correctly
|
|
34
|
-
video_duration = video_entry.duration if hasattr(video_entry, "duration") and video_entry.duration else 226 # Default to 226 seconds
|
|
35
|
-
|
|
36
|
-
print("Video ID:", video_id)
|
|
37
|
-
print("Segments:", segments)
|
|
38
|
-
print("Video Duration:", video_duration)
|
|
39
|
-
|
|
40
|
-
return render(request, "timeline.html", {
|
|
41
|
-
"video_id": video_id,
|
|
42
|
-
"video_url": video_serializer.get_video_url(video_entry),
|
|
43
|
-
"segments": json.dumps(segments), # Send segment start/end times
|
|
44
|
-
"frame_markers": json.dumps(frame_markers), # Send frame timestamps
|
|
45
|
-
"video_duration": video_duration,
|
|
46
|
-
})
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import VideoFile
|
|
2
|
-
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
3
|
-
|
|
4
|
-
from django.shortcuts import get_object_or_404
|
|
5
|
-
from rest_framework import status
|
|
6
|
-
from rest_framework.response import Response
|
|
7
|
-
from rest_framework.views import APIView
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class VideoAnalyzeView(APIView):
|
|
11
|
-
"""
|
|
12
|
-
POST /api/video-analyze/{id}/ - Analyze video for sensitive content
|
|
13
|
-
"""
|
|
14
|
-
permission_classes = [EnvironmentAwarePermission]
|
|
15
|
-
|
|
16
|
-
def post(self, request, pk):
|
|
17
|
-
video = get_object_or_404(VideoFile, pk=pk)
|
|
18
|
-
use_minicpm = request.data.get('use_minicpm', True)
|
|
19
|
-
_detailed_analysis = request.data.get('detailed_analysis', True)
|
|
20
|
-
|
|
21
|
-
try:
|
|
22
|
-
# Import FrameCleaner here to avoid circular imports
|
|
23
|
-
from lx_anonymizer.frame_cleaner import FrameCleaner
|
|
24
|
-
|
|
25
|
-
cleaner = FrameCleaner(
|
|
26
|
-
video_path=video.file.path,
|
|
27
|
-
use_minicpm=use_minicpm
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
# Perform analysis
|
|
31
|
-
analysis_result = cleaner.analyze_video_sensitivity()
|
|
32
|
-
|
|
33
|
-
# Update video metadata
|
|
34
|
-
if hasattr(video, 'sensitive_frame_count'):
|
|
35
|
-
video.sensitive_frame_count = analysis_result.get('sensitive_frames', 0)
|
|
36
|
-
if hasattr(video, 'total_frames'):
|
|
37
|
-
video.total_frames = analysis_result.get('total_frames', 0)
|
|
38
|
-
if hasattr(video, 'sensitive_ratio'):
|
|
39
|
-
video.sensitive_ratio = analysis_result.get('sensitivity_ratio', 0.0)
|
|
40
|
-
|
|
41
|
-
try:
|
|
42
|
-
video.save()
|
|
43
|
-
except Exception as e:
|
|
44
|
-
print(f"Warning: Could not save video metadata: {e}")
|
|
45
|
-
|
|
46
|
-
return Response(analysis_result, status=status.HTTP_200_OK)
|
|
47
|
-
|
|
48
|
-
except Exception as e:
|
|
49
|
-
return Response(
|
|
50
|
-
{"error": f"Analysis failed: {str(e)}"},
|
|
51
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
52
|
-
)
|
endoreg_db/views.py
DELETED
|
File without changes
|
|
File without changes
|
/endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py}
RENAMED
|
File without changes
|
|
File without changes
|