endoreg-db 0.8.9.2__py3-none-any.whl → 0.8.9.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/admin.py +10 -5
- endoreg_db/apps.py +4 -7
- endoreg_db/authz/auth.py +1 -0
- endoreg_db/authz/backends.py +1 -1
- endoreg_db/authz/management/commands/list_routes.py +2 -0
- endoreg_db/authz/middleware.py +8 -7
- endoreg_db/authz/permissions.py +21 -10
- endoreg_db/authz/policy.py +14 -19
- endoreg_db/authz/views_auth.py +14 -10
- endoreg_db/codemods/rename_datetime_fields.py +8 -1
- endoreg_db/exceptions.py +5 -2
- endoreg_db/forms/__init__.py +0 -1
- endoreg_db/forms/examination_form.py +4 -3
- endoreg_db/forms/patient_finding_intervention_form.py +30 -8
- endoreg_db/forms/patient_form.py +9 -13
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/settings/__init__.py +4 -1
- endoreg_db/forms/unit.py +2 -1
- endoreg_db/helpers/count_db.py +17 -14
- endoreg_db/helpers/default_objects.py +2 -1
- endoreg_db/helpers/download_segmentation_model.py +4 -3
- endoreg_db/helpers/interact.py +0 -5
- endoreg_db/helpers/test_video_helper.py +33 -25
- endoreg_db/import_files/__init__.py +1 -1
- endoreg_db/import_files/context/__init__.py +1 -1
- endoreg_db/import_files/context/default_sensitive_meta.py +11 -9
- endoreg_db/import_files/context/ensure_center.py +4 -4
- endoreg_db/import_files/context/file_lock.py +3 -3
- endoreg_db/import_files/context/import_context.py +11 -12
- endoreg_db/import_files/context/validate_directories.py +1 -0
- endoreg_db/import_files/file_storage/create_report_file.py +57 -34
- endoreg_db/import_files/file_storage/create_video_file.py +64 -35
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +5 -2
- endoreg_db/import_files/file_storage/state_management.py +89 -122
- endoreg_db/import_files/file_storage/storage.py +5 -1
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +24 -19
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +3 -3
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +18 -18
- endoreg_db/import_files/pseudonymization/k_anonymity.py +8 -9
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +16 -5
- endoreg_db/import_files/report_import_service.py +36 -30
- endoreg_db/import_files/video_import_service.py +27 -23
- endoreg_db/logger_conf.py +56 -40
- endoreg_db/management/__init__.py +1 -1
- endoreg_db/management/commands/__init__.py +1 -1
- endoreg_db/management/commands/check_auth.py +45 -38
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +53 -2
- endoreg_db/management/commands/create_multilabel_model_meta.py +54 -19
- endoreg_db/management/commands/fix_missing_patient_data.py +105 -71
- endoreg_db/management/commands/fix_video_paths.py +75 -54
- endoreg_db/management/commands/import_report.py +1 -3
- endoreg_db/management/commands/list_routes.py +2 -0
- endoreg_db/management/commands/load_ai_model_data.py +8 -2
- endoreg_db/management/commands/load_ai_model_label_data.py +0 -1
- endoreg_db/management/commands/load_center_data.py +3 -3
- endoreg_db/management/commands/load_distribution_data.py +35 -38
- endoreg_db/management/commands/load_endoscope_data.py +0 -3
- endoreg_db/management/commands/load_examination_data.py +20 -4
- endoreg_db/management/commands/load_finding_data.py +18 -3
- endoreg_db/management/commands/load_gender_data.py +17 -24
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +95 -85
- endoreg_db/management/commands/load_information_source.py +0 -3
- endoreg_db/management/commands/load_lab_value_data.py +14 -3
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_name_data.py +1 -2
- endoreg_db/management/commands/load_pdf_type_data.py +4 -8
- endoreg_db/management/commands/load_profession_data.py +0 -1
- endoreg_db/management/commands/load_report_reader_flag_data.py +0 -4
- endoreg_db/management/commands/load_requirement_data.py +6 -2
- endoreg_db/management/commands/load_unit_data.py +0 -4
- endoreg_db/management/commands/load_user_groups.py +5 -7
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +22 -16
- endoreg_db/management/commands/setup_endoreg_db.py +110 -32
- endoreg_db/management/commands/storage_management.py +14 -8
- endoreg_db/management/commands/summarize_db_content.py +154 -63
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +82 -50
- endoreg_db/management/commands/video_validation.py +4 -6
- endoreg_db/migrations/0001_initial.py +112 -63
- endoreg_db/models/__init__.py +8 -0
- endoreg_db/models/administration/ai/active_model.py +5 -5
- endoreg_db/models/administration/ai/ai_model.py +41 -18
- endoreg_db/models/administration/ai/model_type.py +1 -0
- endoreg_db/models/administration/case/case.py +22 -22
- endoreg_db/models/administration/center/__init__.py +5 -5
- endoreg_db/models/administration/center/center.py +6 -2
- endoreg_db/models/administration/center/center_resource.py +18 -4
- endoreg_db/models/administration/center/center_shift.py +3 -1
- endoreg_db/models/administration/center/center_waste.py +6 -2
- endoreg_db/models/administration/person/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/employee_type.py +3 -1
- endoreg_db/models/administration/person/examiner/__init__.py +1 -1
- endoreg_db/models/administration/person/examiner/examiner.py +10 -2
- endoreg_db/models/administration/person/names/first_name.py +6 -4
- endoreg_db/models/administration/person/names/last_name.py +4 -3
- endoreg_db/models/administration/person/patient/__init__.py +1 -1
- endoreg_db/models/administration/person/patient/patient.py +0 -1
- endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
- endoreg_db/models/administration/person/person.py +1 -1
- endoreg_db/models/administration/product/__init__.py +7 -6
- endoreg_db/models/administration/product/product.py +6 -2
- endoreg_db/models/administration/product/product_group.py +9 -7
- endoreg_db/models/administration/product/product_material.py +9 -2
- endoreg_db/models/administration/product/reference_product.py +64 -15
- endoreg_db/models/administration/qualification/qualification.py +3 -1
- endoreg_db/models/administration/shift/shift.py +3 -1
- endoreg_db/models/administration/shift/shift_type.py +12 -4
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +1 -1
- endoreg_db/models/label/label.py +10 -2
- endoreg_db/models/label/label_set.py +3 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
- endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
- endoreg_db/models/media/__init__.py +12 -5
- endoreg_db/models/media/frame/__init__.py +1 -1
- endoreg_db/models/media/frame/frame.py +34 -8
- endoreg_db/models/media/pdf/__init__.py +2 -1
- endoreg_db/models/media/pdf/raw_pdf.py +11 -4
- endoreg_db/models/media/pdf/report_file.py +6 -2
- endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
- endoreg_db/models/media/video/create_from_file.py +20 -41
- endoreg_db/models/media/video/pipe_1.py +75 -30
- endoreg_db/models/media/video/pipe_2.py +37 -12
- endoreg_db/models/media/video/video_file.py +36 -24
- endoreg_db/models/media/video/video_file_ai.py +235 -70
- endoreg_db/models/media/video/video_file_anonymize.py +240 -65
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
- endoreg_db/models/media/video/video_file_io.py +85 -33
- endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
- endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
- endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
- endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
- endoreg_db/models/media/video/video_file_segments.py +118 -27
- endoreg_db/models/media/video/video_metadata.py +25 -6
- endoreg_db/models/media/video/video_processing.py +54 -15
- endoreg_db/models/medical/__init__.py +3 -13
- endoreg_db/models/medical/contraindication/__init__.py +3 -1
- endoreg_db/models/medical/disease.py +18 -6
- endoreg_db/models/medical/event.py +6 -2
- endoreg_db/models/medical/examination/__init__.py +5 -1
- endoreg_db/models/medical/examination/examination.py +22 -6
- endoreg_db/models/medical/examination/examination_indication.py +23 -7
- endoreg_db/models/medical/examination/examination_time.py +6 -2
- endoreg_db/models/medical/finding/__init__.py +3 -1
- endoreg_db/models/medical/finding/finding.py +37 -12
- endoreg_db/models/medical/finding/finding_classification.py +27 -8
- endoreg_db/models/medical/finding/finding_intervention.py +19 -6
- endoreg_db/models/medical/finding/finding_type.py +3 -1
- endoreg_db/models/medical/hardware/__init__.py +1 -1
- endoreg_db/models/medical/hardware/endoscope.py +14 -2
- endoreg_db/models/medical/laboratory/__init__.py +1 -1
- endoreg_db/models/medical/laboratory/lab_value.py +139 -39
- endoreg_db/models/medical/medication/__init__.py +7 -3
- endoreg_db/models/medical/medication/medication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
- endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
- endoreg_db/models/medical/medication/medication_schedule.py +3 -1
- endoreg_db/models/medical/patient/__init__.py +2 -10
- endoreg_db/models/medical/patient/medication_examples.py +3 -14
- endoreg_db/models/medical/patient/patient_disease.py +17 -5
- endoreg_db/models/medical/patient/patient_event.py +12 -4
- endoreg_db/models/medical/patient/patient_examination.py +52 -15
- endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
- endoreg_db/models/medical/patient/patient_finding.py +105 -29
- endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
- endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
- endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
- endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
- endoreg_db/models/medical/patient/patient_medication.py +25 -7
- endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
- endoreg_db/models/metadata/model_meta.py +40 -12
- endoreg_db/models/metadata/model_meta_logic.py +51 -16
- endoreg_db/models/metadata/sensitive_meta.py +65 -28
- endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
- endoreg_db/models/metadata/video_meta.py +146 -39
- endoreg_db/models/metadata/video_prediction_logic.py +70 -21
- endoreg_db/models/metadata/video_prediction_meta.py +80 -27
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +10 -10
- endoreg_db/models/other/distribution/__init__.py +9 -7
- endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
- endoreg_db/models/other/emission/__init__.py +1 -1
- endoreg_db/models/other/emission/emission_factor.py +9 -3
- endoreg_db/models/other/information_source.py +15 -5
- endoreg_db/models/other/material.py +3 -1
- endoreg_db/models/other/transport_route.py +3 -1
- endoreg_db/models/other/unit.py +6 -2
- endoreg_db/models/report/report.py +0 -1
- endoreg_db/models/requirement/requirement.py +84 -27
- endoreg_db/models/requirement/requirement_error.py +5 -6
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
- endoreg_db/models/requirement/requirement_operator.py +28 -8
- endoreg_db/models/requirement/requirement_set.py +34 -11
- endoreg_db/models/state/__init__.py +1 -0
- endoreg_db/models/state/audit_ledger.py +9 -2
- endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +0 -1
- endoreg_db/models/state/video.py +2 -4
- endoreg_db/models/utils.py +4 -2
- endoreg_db/queries/__init__.py +2 -6
- endoreg_db/queries/annotations/__init__.py +1 -3
- endoreg_db/queries/annotations/legacy.py +37 -26
- endoreg_db/root_urls.py +3 -4
- endoreg_db/schemas/examination_evaluation.py +3 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/administration/__init__.py +1 -2
- endoreg_db/serializers/administration/ai/__init__.py +0 -1
- endoreg_db/serializers/administration/ai/active_model.py +3 -1
- endoreg_db/serializers/administration/ai/ai_model.py +5 -3
- endoreg_db/serializers/administration/ai/model_type.py +3 -1
- endoreg_db/serializers/administration/center.py +7 -2
- endoreg_db/serializers/administration/gender.py +4 -2
- endoreg_db/serializers/anonymization.py +13 -13
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
- endoreg_db/serializers/examination/__init__.py +1 -1
- endoreg_db/serializers/examination/base.py +12 -13
- endoreg_db/serializers/examination/dropdown.py +6 -7
- endoreg_db/serializers/examination_serializer.py +3 -6
- endoreg_db/serializers/finding/__init__.py +1 -1
- endoreg_db/serializers/finding/finding.py +14 -7
- endoreg_db/serializers/finding_classification/__init__.py +3 -3
- endoreg_db/serializers/finding_classification/choice.py +3 -3
- endoreg_db/serializers/finding_classification/classification.py +2 -4
- endoreg_db/serializers/label_video_segment/__init__.py +5 -3
- endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
- endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
- endoreg_db/serializers/meta/__init__.py +1 -2
- endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
- endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
- endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
- endoreg_db/serializers/misc/__init__.py +2 -2
- endoreg_db/serializers/misc/file_overview.py +11 -7
- endoreg_db/serializers/misc/stats.py +10 -8
- endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
- endoreg_db/serializers/misc/upload_job.py +32 -29
- endoreg_db/serializers/patient/__init__.py +2 -1
- endoreg_db/serializers/patient/patient.py +32 -15
- endoreg_db/serializers/patient/patient_dropdown.py +11 -3
- endoreg_db/serializers/patient_examination/__init__.py +1 -1
- endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
- endoreg_db/serializers/patient_finding/__init__.py +1 -1
- endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
- endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
- endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
- endoreg_db/serializers/pdf/__init__.py +1 -3
- endoreg_db/serializers/requirements/requirement_schema.py +1 -6
- endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
- endoreg_db/serializers/video/__init__.py +2 -2
- endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
- endoreg_db/serializers/video/video_file_brief.py +6 -2
- endoreg_db/serializers/video/video_file_detail.py +36 -23
- endoreg_db/serializers/video/video_file_list.py +4 -2
- endoreg_db/serializers/video/video_processing_history.py +54 -50
- endoreg_db/services/__init__.py +1 -1
- endoreg_db/services/anonymization.py +2 -2
- endoreg_db/services/examination_evaluation.py +40 -17
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/polling_coordinator.py +101 -70
- endoreg_db/services/pseudonym_service.py +27 -22
- endoreg_db/services/report_import.py +6 -3
- endoreg_db/services/segment_sync.py +75 -59
- endoreg_db/services/video_import.py +6 -7
- endoreg_db/urls/__init__.py +2 -2
- endoreg_db/urls/ai.py +7 -25
- endoreg_db/urls/anonymization.py +61 -15
- endoreg_db/urls/auth.py +4 -4
- endoreg_db/urls/classification.py +4 -9
- endoreg_db/urls/examination.py +27 -18
- endoreg_db/urls/media.py +27 -34
- endoreg_db/urls/patient.py +11 -7
- endoreg_db/urls/requirements.py +3 -1
- endoreg_db/urls/root_urls.py +2 -3
- endoreg_db/urls/stats.py +24 -16
- endoreg_db/urls/upload.py +3 -11
- endoreg_db/utils/__init__.py +14 -15
- endoreg_db/utils/ai/__init__.py +1 -1
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +2 -1
- endoreg_db/utils/ai/inference_dataset.py +14 -15
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
- endoreg_db/utils/ai/predict.py +4 -4
- endoreg_db/utils/ai/preprocess.py +19 -11
- endoreg_db/utils/calc_duration_seconds.py +4 -4
- endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
- endoreg_db/utils/check_video_files.py +74 -47
- endoreg_db/utils/cropping.py +10 -9
- endoreg_db/utils/dataloader.py +11 -3
- endoreg_db/utils/dates.py +3 -4
- endoreg_db/utils/defaults/set_default_center.py +7 -6
- endoreg_db/utils/env.py +6 -2
- endoreg_db/utils/extract_specific_frames.py +24 -9
- endoreg_db/utils/file_operations.py +30 -18
- endoreg_db/utils/fix_video_path_direct.py +57 -41
- endoreg_db/utils/frame_anonymization_utils.py +157 -157
- endoreg_db/utils/hashs.py +3 -18
- endoreg_db/utils/links/requirement_link.py +96 -52
- endoreg_db/utils/ocr.py +30 -25
- endoreg_db/utils/operation_log.py +61 -0
- endoreg_db/utils/parse_and_generate_yaml.py +12 -13
- endoreg_db/utils/paths.py +6 -6
- endoreg_db/utils/permissions.py +40 -24
- endoreg_db/utils/pipelines/process_video_dir.py +50 -26
- endoreg_db/utils/product/sum_emissions.py +5 -3
- endoreg_db/utils/product/sum_weights.py +4 -2
- endoreg_db/utils/pydantic_models/__init__.py +3 -4
- endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
- endoreg_db/utils/setup_config.py +21 -5
- endoreg_db/utils/storage.py +3 -1
- endoreg_db/utils/translation.py +19 -15
- endoreg_db/utils/uuid.py +1 -0
- endoreg_db/utils/validate_endo_roi.py +12 -4
- endoreg_db/utils/validate_subcategory_dict.py +26 -24
- endoreg_db/utils/validate_video_detailed.py +207 -149
- endoreg_db/utils/video/__init__.py +7 -3
- endoreg_db/utils/video/extract_frames.py +30 -18
- endoreg_db/utils/video/names.py +11 -6
- endoreg_db/utils/video/streaming_processor.py +175 -101
- endoreg_db/utils/video/video_splitter.py +30 -19
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
- endoreg_db/views/__init__.py +0 -20
- endoreg_db/views/anonymization/__init__.py +6 -2
- endoreg_db/views/anonymization/media_management.py +2 -6
- endoreg_db/views/anonymization/overview.py +34 -1
- endoreg_db/views/anonymization/validate.py +79 -18
- endoreg_db/views/auth/__init__.py +1 -1
- endoreg_db/views/auth/keycloak.py +16 -14
- endoreg_db/views/examination/__init__.py +12 -15
- endoreg_db/views/examination/examination.py +5 -5
- endoreg_db/views/examination/examination_manifest_cache.py +5 -5
- endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
- endoreg_db/views/examination/get_finding_classifications.py +9 -7
- endoreg_db/views/examination/get_findings.py +8 -10
- endoreg_db/views/examination/get_instruments.py +3 -2
- endoreg_db/views/examination/get_interventions.py +1 -1
- endoreg_db/views/finding/__init__.py +2 -2
- endoreg_db/views/finding/finding.py +58 -54
- endoreg_db/views/finding/get_classifications.py +1 -1
- endoreg_db/views/finding/get_interventions.py +1 -1
- endoreg_db/views/finding_classification/__init__.py +5 -5
- endoreg_db/views/finding_classification/finding_classification.py +5 -6
- endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
- endoreg_db/views/media/__init__.py +13 -13
- endoreg_db/views/media/pdf_media.py +9 -9
- endoreg_db/views/media/sensitive_metadata.py +10 -7
- endoreg_db/views/media/video_media.py +4 -4
- endoreg_db/views/meta/__init__.py +1 -1
- endoreg_db/views/meta/sensitive_meta_list.py +20 -22
- endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
- endoreg_db/views/misc/__init__.py +6 -34
- endoreg_db/views/misc/center.py +2 -1
- endoreg_db/views/misc/csrf.py +2 -1
- endoreg_db/views/misc/gender.py +2 -1
- endoreg_db/views/misc/stats.py +141 -106
- endoreg_db/views/patient/__init__.py +1 -3
- endoreg_db/views/patient/patient.py +141 -99
- endoreg_db/views/patient_examination/__init__.py +5 -5
- endoreg_db/views/patient_examination/patient_examination.py +43 -42
- endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
- endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
- endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
- endoreg_db/views/patient_examination/video.py +114 -80
- endoreg_db/views/patient_finding/__init__.py +1 -1
- endoreg_db/views/patient_finding/patient_finding.py +17 -10
- endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
- endoreg_db/views/patient_finding_classification/__init__.py +1 -1
- endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
- endoreg_db/views/report/reimport.py +1 -1
- endoreg_db/views/report/report_stream.py +5 -8
- endoreg_db/views/requirement/__init__.py +2 -1
- endoreg_db/views/requirement/evaluate.py +7 -9
- endoreg_db/views/requirement/lookup.py +2 -3
- endoreg_db/views/requirement/lookup_store.py +0 -1
- endoreg_db/views/requirement/requirement_utils.py +2 -4
- endoreg_db/views/stats/__init__.py +4 -4
- endoreg_db/views/stats/stats_views.py +152 -115
- endoreg_db/views/video/__init__.py +18 -27
- endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
- endoreg_db/views/{ai → video/ai}/label.py +20 -16
- endoreg_db/views/video/correction.py +5 -6
- endoreg_db/views/video/reimport.py +134 -99
- endoreg_db/views/video/segments_crud.py +134 -44
- endoreg_db/views/video/video_apply_mask.py +13 -12
- endoreg_db/views/video/video_correction.py +2 -1
- endoreg_db/views/video/video_download_processed.py +15 -15
- endoreg_db/views/video/video_meta_stats.py +7 -6
- endoreg_db/views/video/video_processing_history.py +3 -2
- endoreg_db/views/video/video_remove_frames.py +13 -12
- endoreg_db/views/video/video_stream.py +110 -82
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +434 -431
- endoreg_db/management/commands/import_fallback_video.py +0 -203
- endoreg_db/management/commands/import_video.py +0 -422
- endoreg_db/management/commands/import_video_with_classification.py +0 -367
- endoreg_db/models/media/processing_history/processing_history.py +0 -96
- endoreg_db/serializers/label/__init__.py +0 -7
- endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
- endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
- endoreg_db/services/__old/pdf_import.py +0 -1487
- endoreg_db/services/__old/video_import.py +0 -1306
- endoreg_db/tasks/upload_tasks.py +0 -216
- endoreg_db/tasks/video_ingest.py +0 -161
- endoreg_db/tasks/video_processing_tasks.py +0 -327
- endoreg_db/views/misc/translation.py +0 -182
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -19,72 +19,77 @@ from django.utils import timezone
|
|
|
19
19
|
logger = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
21
|
# Unterstützte Ausgabeformate
|
|
22
|
-
SUPPORTED_OUTPUT_FORMATS = [
|
|
22
|
+
SUPPORTED_OUTPUT_FORMATS = ["jpg", "jpeg", "png", "webp"]
|
|
23
23
|
|
|
24
24
|
# Anonymisierungsgrade
|
|
25
|
-
ANONYMIZATION_LEVELS = [
|
|
25
|
+
ANONYMIZATION_LEVELS = ["minimal", "faces", "full"]
|
|
26
26
|
|
|
27
27
|
# Maximale Dateigröße für Frames (in MB)
|
|
28
28
|
MAX_FRAME_SIZE_MB = 50
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def validate_anonymization_request(
|
|
32
|
-
|
|
31
|
+
def validate_anonymization_request(
|
|
32
|
+
video_id: int, segment_ids: List[int], anonymization_level: str, output_format: str
|
|
33
|
+
) -> Dict:
|
|
33
34
|
"""
|
|
34
35
|
Validiert eine Frame-Anonymisierungsanfrage.
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
Args:
|
|
37
38
|
video_id: Video-ID
|
|
38
39
|
segment_ids: Liste der Segment-IDs
|
|
39
40
|
anonymization_level: Anonymisierungsgrad
|
|
40
41
|
output_format: Ausgabeformat
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
Returns:
|
|
43
44
|
Dict mit Validierungsergebnis
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
Raises:
|
|
46
47
|
ValidationError: Bei ungültigen Parametern
|
|
47
48
|
"""
|
|
48
49
|
errors = []
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
# Anonymisierungsgrad validieren
|
|
51
52
|
if anonymization_level not in ANONYMIZATION_LEVELS:
|
|
52
|
-
errors.append(
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
errors.append(
|
|
54
|
+
f"Invalid anonymization level: {anonymization_level}. "
|
|
55
|
+
f"Supported levels: {', '.join(ANONYMIZATION_LEVELS)}"
|
|
56
|
+
)
|
|
57
|
+
|
|
55
58
|
# Ausgabeformat validieren
|
|
56
59
|
if output_format.lower() not in SUPPORTED_OUTPUT_FORMATS:
|
|
57
|
-
errors.append(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
errors.append(
|
|
61
|
+
f"Invalid output format: {output_format}. "
|
|
62
|
+
f"Supported formats: {', '.join(SUPPORTED_OUTPUT_FORMATS)}"
|
|
63
|
+
)
|
|
64
|
+
|
|
60
65
|
# Segment-IDs validieren
|
|
61
66
|
if not segment_ids or len(segment_ids) == 0:
|
|
62
67
|
errors.append("At least one segment ID must be provided")
|
|
63
|
-
|
|
68
|
+
|
|
64
69
|
if len(segment_ids) > 100: # Reasonable limit
|
|
65
70
|
errors.append("Too many segments requested (max 100)")
|
|
66
|
-
|
|
71
|
+
|
|
67
72
|
# Video-ID validieren
|
|
68
73
|
if video_id <= 0:
|
|
69
74
|
errors.append("Invalid video ID")
|
|
70
|
-
|
|
75
|
+
|
|
71
76
|
if errors:
|
|
72
77
|
raise ValidationError(errors)
|
|
73
|
-
|
|
78
|
+
|
|
74
79
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
"valid": True,
|
|
81
|
+
"normalized_format": output_format.lower(),
|
|
82
|
+
"segment_count": len(segment_ids),
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
|
|
81
86
|
def generate_secure_token(length: int = 32) -> str:
|
|
82
87
|
"""
|
|
83
88
|
Generiert einen sicheren Token für Downloads.
|
|
84
|
-
|
|
89
|
+
|
|
85
90
|
Args:
|
|
86
91
|
length: Token-Länge
|
|
87
|
-
|
|
92
|
+
|
|
88
93
|
Returns:
|
|
89
94
|
Sicherer Token
|
|
90
95
|
"""
|
|
@@ -94,54 +99,54 @@ def generate_secure_token(length: int = 32) -> str:
|
|
|
94
99
|
def create_secure_download_url(frame_id: int, expiry_hours: int = 24) -> Dict:
|
|
95
100
|
"""
|
|
96
101
|
Erstellt eine sichere Download-URL für einen anonymisierten Frame.
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
Args:
|
|
99
104
|
frame_id: Frame-ID
|
|
100
105
|
expiry_hours: Gültigkeitsdauer in Stunden
|
|
101
|
-
|
|
106
|
+
|
|
102
107
|
Returns:
|
|
103
108
|
Dict mit URL und Token-Informationen
|
|
104
109
|
"""
|
|
105
110
|
token = generate_secure_token()
|
|
106
111
|
expiry_time = timezone.now() + timedelta(hours=expiry_hours)
|
|
107
|
-
|
|
112
|
+
|
|
108
113
|
# Token hashen für Datenbank-Speicherung
|
|
109
114
|
token_hash = hashlib.sha256(token.encode()).hexdigest()
|
|
110
|
-
|
|
115
|
+
|
|
111
116
|
return {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
"token": token,
|
|
118
|
+
"token_hash": token_hash,
|
|
119
|
+
"expires_at": expiry_time,
|
|
120
|
+
"frame_id": frame_id,
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
|
|
119
124
|
def validate_secure_token(token: str, frame_id: int) -> bool:
|
|
120
125
|
"""
|
|
121
126
|
Validiert einen sicheren Download-Token.
|
|
122
|
-
|
|
127
|
+
|
|
123
128
|
Args:
|
|
124
129
|
token: Download-Token
|
|
125
130
|
frame_id: Frame-ID
|
|
126
|
-
|
|
131
|
+
|
|
127
132
|
Returns:
|
|
128
133
|
True wenn Token gültig ist
|
|
129
134
|
"""
|
|
130
135
|
try:
|
|
131
136
|
from endoreg_db.models import AnonymousFrame
|
|
132
|
-
|
|
137
|
+
|
|
133
138
|
# Token hashen
|
|
134
139
|
token_hash = hashlib.sha256(token.encode()).hexdigest()
|
|
135
|
-
|
|
140
|
+
|
|
136
141
|
# Frame mit Token finden
|
|
137
142
|
frame = AnonymousFrame.objects.filter(
|
|
138
143
|
id=frame_id,
|
|
139
144
|
download_token_hash=token_hash,
|
|
140
|
-
download_expires_at__gt=timezone.now()
|
|
145
|
+
download_expires_at__gt=timezone.now(),
|
|
141
146
|
).first()
|
|
142
|
-
|
|
147
|
+
|
|
143
148
|
return frame is not None
|
|
144
|
-
|
|
149
|
+
|
|
145
150
|
except Exception as e:
|
|
146
151
|
logger.error(f"Token validation error: {str(e)}")
|
|
147
152
|
return False
|
|
@@ -150,139 +155,137 @@ def validate_secure_token(token: str, frame_id: int) -> bool:
|
|
|
150
155
|
def get_frame_file_info(frame_path: str) -> Optional[Dict]:
|
|
151
156
|
"""
|
|
152
157
|
Holt Dateiinformationen für einen Frame.
|
|
153
|
-
|
|
158
|
+
|
|
154
159
|
Args:
|
|
155
160
|
frame_path: Pfad zum Frame
|
|
156
|
-
|
|
161
|
+
|
|
157
162
|
Returns:
|
|
158
163
|
Dict mit Dateiinformationen oder None
|
|
159
164
|
"""
|
|
160
165
|
try:
|
|
161
166
|
path = Path(frame_path)
|
|
162
|
-
|
|
167
|
+
|
|
163
168
|
if not path.exists():
|
|
164
169
|
return None
|
|
165
|
-
|
|
170
|
+
|
|
166
171
|
stat = path.stat()
|
|
167
|
-
|
|
172
|
+
|
|
168
173
|
return {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
"filename": path.name,
|
|
175
|
+
"size_bytes": stat.st_size,
|
|
176
|
+
"size_mb": round(stat.st_size / (1024 * 1024), 2),
|
|
177
|
+
"created_at": datetime.fromtimestamp(stat.st_ctime),
|
|
178
|
+
"modified_at": datetime.fromtimestamp(stat.st_mtime),
|
|
179
|
+
"extension": path.suffix.lower(),
|
|
180
|
+
"exists": True,
|
|
176
181
|
}
|
|
177
|
-
|
|
182
|
+
|
|
178
183
|
except Exception as e:
|
|
179
184
|
logger.error(f"Error getting file info for {frame_path}: {str(e)}")
|
|
180
185
|
return None
|
|
181
186
|
|
|
182
187
|
|
|
183
|
-
def calculate_anonymization_progress(
|
|
184
|
-
|
|
188
|
+
def calculate_anonymization_progress(
|
|
189
|
+
total_frames: int, processed_frames: int, failed_frames: int
|
|
190
|
+
) -> Dict:
|
|
185
191
|
"""
|
|
186
192
|
Berechnet den Fortschritt der Anonymisierung.
|
|
187
|
-
|
|
193
|
+
|
|
188
194
|
Args:
|
|
189
195
|
total_frames: Gesamtzahl der Frames
|
|
190
196
|
processed_frames: Anzahl verarbeiteter Frames
|
|
191
197
|
failed_frames: Anzahl fehlgeschlagener Frames
|
|
192
|
-
|
|
198
|
+
|
|
193
199
|
Returns:
|
|
194
200
|
Dict mit Fortschrittsinformationen
|
|
195
201
|
"""
|
|
196
202
|
if total_frames == 0:
|
|
197
203
|
return {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
"progress_percent": 0,
|
|
205
|
+
"completed_frames": 0,
|
|
206
|
+
"remaining_frames": 0,
|
|
207
|
+
"success_rate": 0,
|
|
208
|
+
"status": "pending",
|
|
203
209
|
}
|
|
204
|
-
|
|
210
|
+
|
|
205
211
|
completed_frames = processed_frames + failed_frames
|
|
206
212
|
progress_percent = (completed_frames / total_frames) * 100
|
|
207
|
-
success_rate = (
|
|
208
|
-
|
|
213
|
+
success_rate = (
|
|
214
|
+
(processed_frames / completed_frames * 100) if completed_frames > 0 else 0
|
|
215
|
+
)
|
|
216
|
+
|
|
209
217
|
# Status bestimmen
|
|
210
218
|
if completed_frames == 0:
|
|
211
|
-
status =
|
|
219
|
+
status = "pending"
|
|
212
220
|
elif completed_frames < total_frames:
|
|
213
|
-
status =
|
|
221
|
+
status = "processing"
|
|
214
222
|
elif failed_frames == total_frames:
|
|
215
|
-
status =
|
|
223
|
+
status = "failed"
|
|
216
224
|
else:
|
|
217
|
-
status =
|
|
218
|
-
|
|
225
|
+
status = "completed"
|
|
226
|
+
|
|
219
227
|
return {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
"progress_percent": round(progress_percent, 1),
|
|
229
|
+
"completed_frames": completed_frames,
|
|
230
|
+
"remaining_frames": total_frames - completed_frames,
|
|
231
|
+
"success_rate": round(success_rate, 1),
|
|
232
|
+
"status": status,
|
|
233
|
+
"total_frames": total_frames,
|
|
234
|
+
"processed_frames": processed_frames,
|
|
235
|
+
"failed_frames": failed_frames,
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
|
|
231
239
|
def estimate_processing_time(total_frames: int, anonymization_level: str) -> Dict:
|
|
232
240
|
"""
|
|
233
241
|
Schätzt die Verarbeitungszeit für die Anonymisierung.
|
|
234
|
-
|
|
242
|
+
|
|
235
243
|
Args:
|
|
236
244
|
total_frames: Anzahl der zu verarbeitenden Frames
|
|
237
245
|
anonymization_level: Anonymisierungsgrad
|
|
238
|
-
|
|
246
|
+
|
|
239
247
|
Returns:
|
|
240
248
|
Dict mit Zeitschätzungen
|
|
241
249
|
"""
|
|
242
250
|
# Geschätzte Verarbeitungszeit pro Frame (in Sekunden)
|
|
243
|
-
time_per_frame = {
|
|
244
|
-
|
|
245
|
-
'faces': 1.0,
|
|
246
|
-
'full': 0.8
|
|
247
|
-
}
|
|
248
|
-
|
|
251
|
+
time_per_frame = {"minimal": 0.5, "faces": 1.0, "full": 0.8}
|
|
252
|
+
|
|
249
253
|
base_time = time_per_frame.get(anonymization_level, 1.0)
|
|
250
254
|
estimated_seconds = total_frames * base_time
|
|
251
|
-
|
|
255
|
+
|
|
252
256
|
# Overhead für Setup und Cleanup
|
|
253
257
|
overhead_seconds = min(30, total_frames * 0.1)
|
|
254
258
|
total_seconds = estimated_seconds + overhead_seconds
|
|
255
|
-
|
|
259
|
+
|
|
256
260
|
return {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
"estimated_seconds": int(total_seconds),
|
|
262
|
+
"estimated_minutes": round(total_seconds / 60, 1),
|
|
263
|
+
"frames_per_second": round(1 / base_time, 1),
|
|
264
|
+
"anonymization_level": anonymization_level,
|
|
261
265
|
}
|
|
262
266
|
|
|
263
267
|
|
|
264
268
|
def cleanup_expired_tokens():
|
|
265
269
|
"""
|
|
266
270
|
Bereinigt abgelaufene Download-Tokens.
|
|
267
|
-
|
|
271
|
+
|
|
268
272
|
Returns:
|
|
269
273
|
Anzahl bereinigter Tokens
|
|
270
274
|
"""
|
|
271
275
|
try:
|
|
272
276
|
from endoreg_db.models import AnonymousFrame
|
|
273
|
-
|
|
277
|
+
|
|
274
278
|
# Frames mit abgelaufenen Tokens finden
|
|
275
279
|
expired_frames = AnonymousFrame.objects.filter(
|
|
276
|
-
download_expires_at__lt=timezone.now(),
|
|
277
|
-
download_token_hash__isnull=False
|
|
280
|
+
download_expires_at__lt=timezone.now(), download_token_hash__isnull=False
|
|
278
281
|
)
|
|
279
|
-
|
|
282
|
+
|
|
280
283
|
count = expired_frames.count()
|
|
281
284
|
expired_frames.update(download_token_hash=None, download_expires_at=None)
|
|
282
|
-
|
|
285
|
+
|
|
283
286
|
logger.info(f"Cleaned up {count} expired download tokens")
|
|
284
287
|
return count
|
|
285
|
-
|
|
288
|
+
|
|
286
289
|
except Exception as e:
|
|
287
290
|
logger.error(f"Error cleaning up expired tokens: {str(e)}")
|
|
288
291
|
return 0
|
|
@@ -291,88 +294,83 @@ def cleanup_expired_tokens():
|
|
|
291
294
|
def get_anonymization_statistics(video_id: Optional[int] = None) -> Dict:
|
|
292
295
|
"""
|
|
293
296
|
Holt Statistiken zur Frame-Anonymisierung.
|
|
294
|
-
|
|
297
|
+
|
|
295
298
|
Args:
|
|
296
299
|
video_id: Optional - Video-ID für spezifische Statistiken
|
|
297
|
-
|
|
300
|
+
|
|
298
301
|
Returns:
|
|
299
302
|
Dict mit Statistiken
|
|
300
303
|
"""
|
|
301
304
|
try:
|
|
302
305
|
from endoreg_db.models import FrameAnonymizationRequest, AnonymousFrame
|
|
303
306
|
from django.db.models import Count, Q
|
|
304
|
-
|
|
307
|
+
|
|
305
308
|
# Basis-Queryset
|
|
306
309
|
requests_qs = FrameAnonymizationRequest.objects.all()
|
|
307
310
|
frames_qs = AnonymousFrame.objects.all()
|
|
308
|
-
|
|
311
|
+
|
|
309
312
|
if video_id:
|
|
310
313
|
requests_qs = requests_qs.filter(video_file_id=video_id)
|
|
311
314
|
frames_qs = frames_qs.filter(video_file_id=video_id)
|
|
312
|
-
|
|
315
|
+
|
|
313
316
|
# Request-Statistiken
|
|
314
317
|
request_stats = requests_qs.aggregate(
|
|
315
|
-
total_requests=Count(
|
|
316
|
-
pending_requests=Count(
|
|
317
|
-
processing_requests=Count(
|
|
318
|
-
completed_requests=Count(
|
|
319
|
-
failed_requests=Count(
|
|
318
|
+
total_requests=Count("id"),
|
|
319
|
+
pending_requests=Count("id", filter=Q(status="pending")),
|
|
320
|
+
processing_requests=Count("id", filter=Q(status="processing")),
|
|
321
|
+
completed_requests=Count("id", filter=Q(status="completed")),
|
|
322
|
+
failed_requests=Count("id", filter=Q(status="failed")),
|
|
320
323
|
)
|
|
321
|
-
|
|
324
|
+
|
|
322
325
|
# Frame-Statistiken
|
|
323
326
|
frame_stats = frames_qs.aggregate(
|
|
324
|
-
total_frames=Count(
|
|
325
|
-
faces_anonymized=Count(
|
|
326
|
-
full_anonymized=Count(
|
|
327
|
-
minimal_anonymized=Count(
|
|
327
|
+
total_frames=Count("id"),
|
|
328
|
+
faces_anonymized=Count("id", filter=Q(anonymization_level="faces")),
|
|
329
|
+
full_anonymized=Count("id", filter=Q(anonymization_level="full")),
|
|
330
|
+
minimal_anonymized=Count("id", filter=Q(anonymization_level="minimal")),
|
|
328
331
|
)
|
|
329
|
-
|
|
332
|
+
|
|
330
333
|
# Disk-Space Statistiken
|
|
331
334
|
total_size = 0
|
|
332
|
-
for frame in frames_qs.values_list(
|
|
335
|
+
for frame in frames_qs.values_list("anonymized_frame_path", flat=True):
|
|
333
336
|
file_info = get_frame_file_info(frame)
|
|
334
337
|
if file_info:
|
|
335
|
-
total_size += file_info[
|
|
336
|
-
|
|
338
|
+
total_size += file_info["size_bytes"]
|
|
339
|
+
|
|
337
340
|
return {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
"requests": request_stats,
|
|
342
|
+
"frames": frame_stats,
|
|
343
|
+
"storage": {
|
|
344
|
+
"total_size_bytes": total_size,
|
|
345
|
+
"total_size_mb": round(total_size / (1024 * 1024), 2),
|
|
343
346
|
},
|
|
344
|
-
|
|
347
|
+
"video_id": video_id,
|
|
345
348
|
}
|
|
346
|
-
|
|
349
|
+
|
|
347
350
|
except Exception as e:
|
|
348
351
|
logger.error(f"Error getting anonymization statistics: {str(e)}")
|
|
349
|
-
return {
|
|
350
|
-
'requests': {},
|
|
351
|
-
'frames': {},
|
|
352
|
-
'storage': {},
|
|
353
|
-
'error': str(e)
|
|
354
|
-
}
|
|
352
|
+
return {"requests": {}, "frames": {}, "storage": {}, "error": str(e)}
|
|
355
353
|
|
|
356
354
|
|
|
357
355
|
def validate_frame_path(frame_path: str) -> bool:
|
|
358
356
|
"""
|
|
359
357
|
Validiert einen Frame-Pfad auf Sicherheit.
|
|
360
|
-
|
|
358
|
+
|
|
361
359
|
Args:
|
|
362
360
|
frame_path: Zu validierender Pfad
|
|
363
|
-
|
|
361
|
+
|
|
364
362
|
Returns:
|
|
365
363
|
True wenn Pfad sicher ist
|
|
366
364
|
"""
|
|
367
365
|
try:
|
|
368
366
|
path = Path(frame_path).resolve()
|
|
369
|
-
|
|
367
|
+
|
|
370
368
|
# Basis-Verzeichnisse definieren
|
|
371
369
|
allowed_dirs = [
|
|
372
370
|
Path(settings.MEDIA_ROOT).resolve(),
|
|
373
|
-
Path(getattr(settings,
|
|
371
|
+
Path(getattr(settings, "FRAME_STORAGE_ROOT", "/tmp")).resolve(),
|
|
374
372
|
]
|
|
375
|
-
|
|
373
|
+
|
|
376
374
|
# Prüfen ob Pfad in erlaubten Verzeichnissen liegt
|
|
377
375
|
for allowed_dir in allowed_dirs:
|
|
378
376
|
try:
|
|
@@ -380,10 +378,10 @@ def validate_frame_path(frame_path: str) -> bool:
|
|
|
380
378
|
return True
|
|
381
379
|
except ValueError:
|
|
382
380
|
continue
|
|
383
|
-
|
|
381
|
+
|
|
384
382
|
logger.warning(f"Frame path outside allowed directories: {frame_path}")
|
|
385
383
|
return False
|
|
386
|
-
|
|
384
|
+
|
|
387
385
|
except Exception as e:
|
|
388
386
|
logger.error(f"Error validating frame path {frame_path}: {str(e)}")
|
|
389
387
|
return False
|
|
@@ -392,32 +390,32 @@ def validate_frame_path(frame_path: str) -> bool:
|
|
|
392
390
|
def get_video_frame_count(video_id: int) -> int:
|
|
393
391
|
"""
|
|
394
392
|
Ermittelt die Anzahl verfügbarer Frames für ein Video.
|
|
395
|
-
|
|
393
|
+
|
|
396
394
|
Args:
|
|
397
395
|
video_id: Video-ID
|
|
398
|
-
|
|
396
|
+
|
|
399
397
|
Returns:
|
|
400
398
|
Anzahl der Frames
|
|
401
399
|
"""
|
|
402
400
|
try:
|
|
403
401
|
from endoreg_db.models import VideoFile
|
|
404
|
-
|
|
402
|
+
|
|
405
403
|
video = VideoFile.objects.get(id=video_id)
|
|
406
|
-
|
|
404
|
+
|
|
407
405
|
if not video.frame_dir:
|
|
408
406
|
return 0
|
|
409
|
-
|
|
407
|
+
|
|
410
408
|
frame_dir = Path(video.frame_dir)
|
|
411
409
|
if not frame_dir.exists():
|
|
412
410
|
return 0
|
|
413
|
-
|
|
411
|
+
|
|
414
412
|
# Zähle alle Bilddateien
|
|
415
413
|
frame_count = 0
|
|
416
|
-
for ext in [
|
|
414
|
+
for ext in ["*.jpg", "*.jpeg", "*.png"]:
|
|
417
415
|
frame_count += len(list(frame_dir.glob(ext)))
|
|
418
|
-
|
|
416
|
+
|
|
419
417
|
return frame_count
|
|
420
|
-
|
|
418
|
+
|
|
421
419
|
except Exception as e:
|
|
422
420
|
logger.error(f"Error counting frames for video {video_id}: {str(e)}")
|
|
423
421
|
return 0
|
|
@@ -426,24 +424,26 @@ def get_video_frame_count(video_id: int) -> int:
|
|
|
426
424
|
def format_file_size(size_bytes: int) -> str:
|
|
427
425
|
"""
|
|
428
426
|
Formatiert Dateigröße in lesbares Format.
|
|
429
|
-
|
|
427
|
+
|
|
430
428
|
Args:
|
|
431
429
|
size_bytes: Größe in Bytes
|
|
432
|
-
|
|
430
|
+
|
|
433
431
|
Returns:
|
|
434
432
|
Formatierte Größe
|
|
435
433
|
"""
|
|
436
|
-
for unit in [
|
|
434
|
+
for unit in ["B", "KB", "MB", "GB"]:
|
|
437
435
|
if size_bytes < 1024.0:
|
|
438
436
|
return f"{size_bytes:.1f} {unit}"
|
|
439
437
|
size_bytes /= 1024.0
|
|
440
438
|
return f"{size_bytes:.1f} TB"
|
|
441
439
|
|
|
442
440
|
|
|
443
|
-
def log_anonymization_activity(
|
|
441
|
+
def log_anonymization_activity(
|
|
442
|
+
activity_type: str, details: Dict, user_id: Optional[int] = None
|
|
443
|
+
):
|
|
444
444
|
"""
|
|
445
445
|
Protokolliert Anonymisierungsaktivitäten für Audit-Zwecke.
|
|
446
|
-
|
|
446
|
+
|
|
447
447
|
Args:
|
|
448
448
|
activity_type: Art der Aktivität
|
|
449
449
|
details: Details der Aktivität
|
|
@@ -451,13 +451,13 @@ def log_anonymization_activity(activity_type: str, details: Dict, user_id: Optio
|
|
|
451
451
|
"""
|
|
452
452
|
try:
|
|
453
453
|
log_entry = {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
454
|
+
"timestamp": timezone.now().isoformat(),
|
|
455
|
+
"activity_type": activity_type,
|
|
456
|
+
"details": details,
|
|
457
|
+
"user_id": user_id,
|
|
458
458
|
}
|
|
459
|
-
|
|
459
|
+
|
|
460
460
|
logger.info(f"Anonymization activity: {activity_type}", extra=log_entry)
|
|
461
|
-
|
|
461
|
+
|
|
462
462
|
except Exception as e:
|
|
463
|
-
logger.error(f"Error logging anonymization activity: {str(e)}")
|
|
463
|
+
logger.error(f"Error logging anonymization activity: {str(e)}")
|
endoreg_db/utils/hashs.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from datetime import datetime, date
|
|
4
|
-
|
|
4
|
+
from endoreg_db.utils.file_operations import sha256_file
|
|
5
5
|
import os
|
|
6
6
|
|
|
7
7
|
SALT = os.getenv("DJANGO_SALT", "default_salt")
|
|
@@ -12,13 +12,7 @@ def get_video_hash(video_path):
|
|
|
12
12
|
"""
|
|
13
13
|
Get the hash of a video file.
|
|
14
14
|
"""
|
|
15
|
-
|
|
16
|
-
with open(video_path, "rb") as f:
|
|
17
|
-
# Create the hash object, passing in the video contents for hashing:
|
|
18
|
-
hash_object = hashlib.sha256(f.read())
|
|
19
|
-
# Get the hexadecimal representation of the hash
|
|
20
|
-
video_hash = hash_object.hexdigest()
|
|
21
|
-
assert len(video_hash) <= 255, "Hash length exceeds 255 characters"
|
|
15
|
+
video_hash = sha256_file(video_path)
|
|
22
16
|
|
|
23
17
|
return video_hash
|
|
24
18
|
|
|
@@ -27,17 +21,8 @@ def get_pdf_hash(pdf_path: Path):
|
|
|
27
21
|
"""
|
|
28
22
|
Get the hash of a pdf file.
|
|
29
23
|
"""
|
|
30
|
-
pdf_hash = None
|
|
31
|
-
|
|
32
|
-
# Open the file in binary mode and read its contents
|
|
33
|
-
with open(pdf_path, "rb") as f:
|
|
34
|
-
pdf_contents = f.read()
|
|
35
|
-
# Create a hash object using SHA-256 algorithm
|
|
36
24
|
|
|
37
|
-
|
|
38
|
-
# Get the hexadecimal representation of the hash
|
|
39
|
-
pdf_hash = hash_object.hexdigest()
|
|
40
|
-
assert len(pdf_hash) <= 255, "Hash length exceeds 255 characters"
|
|
25
|
+
pdf_hash = sha256_file(pdf_path)
|
|
41
26
|
|
|
42
27
|
return pdf_hash
|
|
43
28
|
|