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
|
@@ -4,6 +4,7 @@ from ...models import SensitiveMeta
|
|
|
4
4
|
|
|
5
5
|
logger = logging.getLogger(__name__)
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
8
9
|
"""
|
|
9
10
|
Serializer for displaying SensitiveMeta details with verification state.
|
|
@@ -17,7 +18,9 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
17
18
|
|
|
18
19
|
# Related fields
|
|
19
20
|
center_name = serializers.CharField(source="center.name", read_only=True)
|
|
20
|
-
patient_gender_name = serializers.CharField(
|
|
21
|
+
patient_gender_name = serializers.CharField(
|
|
22
|
+
source="patient_gender.name", read_only=True
|
|
23
|
+
)
|
|
21
24
|
examiners_display = serializers.SerializerMethodField()
|
|
22
25
|
|
|
23
26
|
# Formatted display fields
|
|
@@ -57,7 +60,7 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
57
60
|
"text",
|
|
58
61
|
"anonymized_text",
|
|
59
62
|
"external_id",
|
|
60
|
-
"external_id_origin"
|
|
63
|
+
"external_id_origin",
|
|
61
64
|
]
|
|
62
65
|
read_only_fields = [
|
|
63
66
|
"id",
|
|
@@ -66,14 +69,23 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
66
69
|
]
|
|
67
70
|
|
|
68
71
|
# --- Verification getters ---
|
|
69
|
-
def get_is_verified(self, obj):
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
def get_is_verified(self, obj):
|
|
73
|
+
return getattr(obj, "is_verified", False)
|
|
74
|
+
|
|
75
|
+
def get_dob_verified(self, obj):
|
|
76
|
+
return getattr(getattr(obj, "state", None), "dob_verified", False)
|
|
77
|
+
|
|
78
|
+
def get_names_verified(self, obj):
|
|
79
|
+
return getattr(getattr(obj, "state", None), "names_verified", False)
|
|
72
80
|
|
|
73
81
|
# --- Examiner display ---
|
|
74
82
|
def get_examiners_display(self, obj):
|
|
75
83
|
try:
|
|
76
|
-
return
|
|
84
|
+
return (
|
|
85
|
+
[f"{e.first_name} {e.last_name}" for e in obj.examiners.all()]
|
|
86
|
+
if obj.pk
|
|
87
|
+
else []
|
|
88
|
+
)
|
|
77
89
|
except Exception as e:
|
|
78
90
|
logger.warning(f"Error fetching examiners for SensitiveMeta {obj.pk}: {e}")
|
|
79
91
|
return []
|
|
@@ -83,7 +95,9 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
83
95
|
return obj.patient_dob.strftime("%Y-%m-%d") if obj.patient_dob else None
|
|
84
96
|
|
|
85
97
|
def get_examination_date_display(self, obj):
|
|
86
|
-
return
|
|
98
|
+
return (
|
|
99
|
+
obj.examination_date.strftime("%Y-%m-%d") if obj.examination_date else None
|
|
100
|
+
)
|
|
87
101
|
|
|
88
102
|
# --- Hash short forms ---
|
|
89
103
|
def get_patient_hash_display(self, obj):
|
|
@@ -98,10 +112,11 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
98
112
|
|
|
99
113
|
def get_anonymized_text(self, obj):
|
|
100
114
|
return obj.anonymized_text if isinstance(obj.anonymized_text, str) else None
|
|
101
|
-
|
|
102
|
-
def get_external_id(self, obj) -> str | None:
|
|
103
|
-
return obj.external_id if isinstance(obj.external_id, str) else None
|
|
104
|
-
|
|
105
|
-
def get_external_id_origin(self, obj) -> str | None:
|
|
106
|
-
return obj.external_id_origin if isinstance(obj.external_id_origin, str) else None
|
|
107
115
|
|
|
116
|
+
def get_external_id(self, obj) -> str | None:
|
|
117
|
+
return obj.external_id if isinstance(obj.external_id, str) else None
|
|
118
|
+
|
|
119
|
+
def get_external_id_origin(self, obj) -> str | None:
|
|
120
|
+
return (
|
|
121
|
+
obj.external_id_origin if isinstance(obj.external_id_origin, str) else None
|
|
122
|
+
)
|
|
@@ -7,44 +7,43 @@ from ...models import SensitiveMeta, Center, Gender
|
|
|
7
7
|
logger = logging.getLogger(__name__)
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
12
11
|
"""
|
|
13
12
|
Serializer for updating SensitiveMeta fields including verification state.
|
|
14
13
|
Handles partial updates and state management.
|
|
15
14
|
"""
|
|
16
|
-
|
|
15
|
+
|
|
17
16
|
# Verification state fields
|
|
18
17
|
dob_verified = serializers.BooleanField(required=False)
|
|
19
18
|
names_verified = serializers.BooleanField(required=False)
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
# Center can be updated by name
|
|
22
21
|
center_name = serializers.CharField(write_only=True, required=False)
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
# Gender can be updated by name
|
|
25
24
|
patient_gender_name = serializers.CharField(write_only=True, required=False)
|
|
26
25
|
|
|
27
26
|
class Meta:
|
|
28
27
|
model = SensitiveMeta
|
|
29
28
|
fields = [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
"patient_first_name",
|
|
30
|
+
"patient_last_name",
|
|
31
|
+
"patient_dob",
|
|
32
|
+
"examination_date",
|
|
33
|
+
"center_name",
|
|
34
|
+
"patient_gender_name",
|
|
35
|
+
"endoscope_type",
|
|
36
|
+
"endoscope_sn",
|
|
37
|
+
"examiner_first_name",
|
|
38
|
+
"examiner_last_name",
|
|
39
|
+
"dob_verified",
|
|
40
|
+
"names_verified",
|
|
42
41
|
]
|
|
43
42
|
|
|
44
43
|
def validate_center_name(self, value):
|
|
45
44
|
"""
|
|
46
45
|
Validates that a center with the given natural key exists.
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
Raises a validation error if the specified center does not exist.
|
|
49
48
|
"""
|
|
50
49
|
if value:
|
|
@@ -58,7 +57,7 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
58
57
|
def validate_patient_gender_name(self, value):
|
|
59
58
|
"""
|
|
60
59
|
Validates that a gender with the given name exists.
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
Raises a validation error if no matching Gender is found.
|
|
63
62
|
"""
|
|
64
63
|
if value:
|
|
@@ -72,21 +71,21 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
72
71
|
def validate(self, data):
|
|
73
72
|
"""
|
|
74
73
|
Validate that patient first and last names, if provided, are not empty strings.
|
|
75
|
-
|
|
74
|
+
|
|
76
75
|
Raises a validation error if either `patient_first_name` or `patient_last_name` is present but empty.
|
|
77
76
|
"""
|
|
78
77
|
# Ensure names are not empty if provided
|
|
79
|
-
first_name = data.get(
|
|
78
|
+
first_name = data.get("patient_first_name")
|
|
80
79
|
if first_name is not None and not first_name.strip():
|
|
81
|
-
raise serializers.ValidationError(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
last_name = data.get(
|
|
80
|
+
raise serializers.ValidationError(
|
|
81
|
+
{"patient_first_name": "First name cannot be empty."}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
last_name = data.get("patient_last_name")
|
|
86
85
|
if last_name is not None and not last_name.strip():
|
|
87
|
-
raise serializers.ValidationError(
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
raise serializers.ValidationError(
|
|
87
|
+
{"patient_last_name": "Last name cannot be empty."}
|
|
88
|
+
)
|
|
90
89
|
|
|
91
90
|
return data
|
|
92
91
|
|
|
@@ -94,55 +93,61 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
94
93
|
def update(self, instance, validated_data):
|
|
95
94
|
"""
|
|
96
95
|
Updates a SensitiveMeta instance with provided data, including related center, gender, and verification state fields.
|
|
97
|
-
|
|
96
|
+
|
|
98
97
|
Handles assignment of related Center and Gender objects by name, updates model fields, and manages verification state flags (`dob_verified`, `names_verified`) in the associated state object if provided.
|
|
99
|
-
|
|
98
|
+
|
|
100
99
|
Returns:
|
|
101
100
|
SensitiveMeta: The updated SensitiveMeta instance.
|
|
102
101
|
"""
|
|
103
102
|
# Extract verification state data
|
|
104
|
-
dob_verified = validated_data.pop(
|
|
105
|
-
names_verified = validated_data.pop(
|
|
106
|
-
|
|
103
|
+
dob_verified = validated_data.pop("dob_verified", None)
|
|
104
|
+
names_verified = validated_data.pop("names_verified", None)
|
|
105
|
+
|
|
107
106
|
# Extract and handle center update
|
|
108
|
-
center_name = validated_data.pop(
|
|
107
|
+
center_name = validated_data.pop("center_name", None)
|
|
109
108
|
if center_name:
|
|
110
109
|
try:
|
|
111
110
|
center = Center.objects.get_by_natural_key(center_name)
|
|
112
111
|
instance.center = center
|
|
113
112
|
except Center.DoesNotExist:
|
|
114
113
|
logger.error(f"Center '{center_name}' not found during update")
|
|
115
|
-
raise serializers.ValidationError(
|
|
116
|
-
|
|
114
|
+
raise serializers.ValidationError(
|
|
115
|
+
f"Center '{center_name}' does not exist."
|
|
116
|
+
)
|
|
117
|
+
|
|
117
118
|
# Extract and handle gender update
|
|
118
|
-
patient_gender_name = validated_data.pop(
|
|
119
|
+
patient_gender_name = validated_data.pop("patient_gender_name", None)
|
|
119
120
|
if patient_gender_name:
|
|
120
121
|
try:
|
|
121
122
|
gender = Gender.objects.get(name=patient_gender_name)
|
|
122
123
|
instance.patient_gender = gender
|
|
123
124
|
except Gender.DoesNotExist:
|
|
124
125
|
logger.error(f"Gender '{patient_gender_name}' not found during update")
|
|
125
|
-
raise serializers.ValidationError(
|
|
126
|
+
raise serializers.ValidationError(
|
|
127
|
+
f"Gender '{patient_gender_name}' does not exist."
|
|
128
|
+
)
|
|
126
129
|
|
|
127
130
|
# Update regular fields using the model's update_from_dict method
|
|
128
131
|
if validated_data:
|
|
129
132
|
instance.update_from_dict(validated_data)
|
|
130
|
-
|
|
133
|
+
|
|
131
134
|
# Update verification state if provided
|
|
132
135
|
if dob_verified is not None or names_verified is not None:
|
|
133
136
|
# Ensure state exists
|
|
134
137
|
state = instance.get_or_create_state()
|
|
135
|
-
|
|
138
|
+
|
|
136
139
|
if dob_verified is not None:
|
|
137
140
|
state.dob_verified = dob_verified
|
|
138
|
-
logger.info(
|
|
139
|
-
|
|
141
|
+
logger.info(
|
|
142
|
+
f"Updated DOB verification for SensitiveMeta {instance.pk}: {dob_verified}"
|
|
143
|
+
)
|
|
144
|
+
|
|
140
145
|
if names_verified is not None:
|
|
141
146
|
state.names_verified = names_verified
|
|
142
|
-
logger.info(
|
|
143
|
-
|
|
147
|
+
logger.info(
|
|
148
|
+
f"Updated names verification for SensitiveMeta {instance.pk}: {names_verified}"
|
|
149
|
+
)
|
|
150
|
+
|
|
144
151
|
state.save()
|
|
145
152
|
|
|
146
153
|
return instance
|
|
147
|
-
|
|
148
|
-
|
|
@@ -5,20 +5,21 @@ from ...models import SensitiveMeta
|
|
|
5
5
|
|
|
6
6
|
logger = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
class SensitiveMetaVerificationSerializer(serializers.Serializer):
|
|
9
10
|
"""
|
|
10
11
|
Simple serializer for bulk verification state updates.
|
|
11
12
|
Used when only updating verification flags.
|
|
12
13
|
"""
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
sensitive_meta_id = serializers.IntegerField()
|
|
15
16
|
dob_verified = serializers.BooleanField(required=False)
|
|
16
17
|
names_verified = serializers.BooleanField(required=False)
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
def validate_sensitive_meta_id(self, value):
|
|
19
20
|
"""
|
|
20
21
|
Validates that a SensitiveMeta object with the given ID exists and caches it.
|
|
21
|
-
|
|
22
|
+
|
|
22
23
|
Raises:
|
|
23
24
|
ValidationError: If no SensitiveMeta object is found with the specified ID.
|
|
24
25
|
"""
|
|
@@ -27,33 +28,35 @@ class SensitiveMetaVerificationSerializer(serializers.Serializer):
|
|
|
27
28
|
self._cached_sensitive_meta = SensitiveMeta.objects.get(id=value)
|
|
28
29
|
return value
|
|
29
30
|
except SensitiveMeta.DoesNotExist:
|
|
30
|
-
raise serializers.ValidationError(
|
|
31
|
+
raise serializers.ValidationError(
|
|
32
|
+
f"SensitiveMeta with ID {value} does not exist."
|
|
33
|
+
)
|
|
31
34
|
|
|
32
35
|
def save(self):
|
|
33
36
|
"""
|
|
34
37
|
Updates the verification state for a specified SensitiveMeta instance.
|
|
35
|
-
|
|
36
|
-
Uses the cached SensitiveMeta object from validation, obtains or creates its verification state,
|
|
38
|
+
|
|
39
|
+
Uses the cached SensitiveMeta object from validation, obtains or creates its verification state,
|
|
37
40
|
updates the `dob_verified` and `names_verified` fields if provided, and saves the changes.
|
|
38
|
-
|
|
41
|
+
|
|
39
42
|
Returns:
|
|
40
43
|
The updated verification state object.
|
|
41
44
|
"""
|
|
42
|
-
sensitive_meta_id = self.validated_data[
|
|
43
|
-
dob_verified = self.validated_data.get(
|
|
44
|
-
names_verified = self.validated_data.get(
|
|
45
|
-
|
|
45
|
+
sensitive_meta_id = self.validated_data["sensitive_meta_id"]
|
|
46
|
+
dob_verified = self.validated_data.get("dob_verified")
|
|
47
|
+
names_verified = self.validated_data.get("names_verified")
|
|
48
|
+
|
|
46
49
|
# Use the cached instance from the validation step, avoiding a redundant query.
|
|
47
50
|
sensitive_meta = self._cached_sensitive_meta
|
|
48
51
|
state = sensitive_meta.get_or_create_state()
|
|
49
|
-
|
|
52
|
+
|
|
50
53
|
if dob_verified is not None:
|
|
51
54
|
state.dob_verified = dob_verified
|
|
52
|
-
|
|
55
|
+
|
|
53
56
|
if names_verified is not None:
|
|
54
57
|
state.names_verified = names_verified
|
|
55
|
-
|
|
58
|
+
|
|
56
59
|
state.save()
|
|
57
|
-
|
|
60
|
+
|
|
58
61
|
logger.info(f"Updated verification state for SensitiveMeta {sensitive_meta_id}")
|
|
59
|
-
return state
|
|
62
|
+
return state
|
|
@@ -3,8 +3,12 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
from rest_framework import serializers
|
|
4
4
|
|
|
5
5
|
from endoreg_db.models.media import RawPdfFile, VideoFile
|
|
6
|
-
from endoreg_db.models.state.anonymization import
|
|
7
|
-
|
|
6
|
+
from endoreg_db.models.state.anonymization import (
|
|
7
|
+
AnonymizationState as PdfAnonymizationState,
|
|
8
|
+
)
|
|
9
|
+
from endoreg_db.models.state.anonymization import (
|
|
10
|
+
AnonymizationState as VideoAnonymizationState,
|
|
11
|
+
)
|
|
8
12
|
|
|
9
13
|
if TYPE_CHECKING:
|
|
10
14
|
pass
|
|
@@ -41,8 +45,6 @@ class FileOverviewSerializer(serializers.Serializer):
|
|
|
41
45
|
Raises:
|
|
42
46
|
TypeError: If the instance is not a VideoFile or RawPdfFile.
|
|
43
47
|
"""
|
|
44
|
-
text = ""
|
|
45
|
-
anonym_text = ""
|
|
46
48
|
|
|
47
49
|
if isinstance(instance, VideoFile):
|
|
48
50
|
media_type = "video"
|
|
@@ -76,10 +78,12 @@ class FileOverviewSerializer(serializers.Serializer):
|
|
|
76
78
|
rps.anonymization_status if rps else PdfAnonymizationState.NOT_STARTED
|
|
77
79
|
)
|
|
78
80
|
|
|
79
|
-
# ------- annotation status (not applicable for
|
|
81
|
+
# ------- annotation status (not applicable for reports)
|
|
80
82
|
annot_status = (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
PdfAnonymizationState.VALIDATED
|
|
84
|
+
if rps.anonymization_validated
|
|
85
|
+
else PdfAnonymizationState.NOT_STARTED
|
|
86
|
+
)
|
|
83
87
|
|
|
84
88
|
else: # shouldn't happen
|
|
85
89
|
raise TypeError(f"Unsupported instance for overview: {type(instance)}")
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
from rest_framework import serializers
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
class StatsSerializer(serializers.Serializer):
|
|
4
5
|
"""
|
|
5
6
|
Serializer for statistics data from AuditLedger.
|
|
6
|
-
|
|
7
|
+
|
|
7
8
|
This serializer defines the structure of statistics data and ensures
|
|
8
9
|
consistent API responses.
|
|
9
10
|
"""
|
|
11
|
+
|
|
10
12
|
totalCases = serializers.IntegerField()
|
|
11
13
|
totalVideos = serializers.IntegerField()
|
|
12
14
|
totalAnnotations = serializers.IntegerField()
|
|
@@ -14,20 +16,20 @@ class StatsSerializer(serializers.Serializer):
|
|
|
14
16
|
totalImages = serializers.IntegerField()
|
|
15
17
|
videosCompleted = serializers.IntegerField()
|
|
16
18
|
videosAnonym = serializers.IntegerField()
|
|
17
|
-
|
|
19
|
+
|
|
18
20
|
# You can add additional fields or methods here as needed
|
|
19
21
|
# For example, to calculate derived statistics:
|
|
20
|
-
#TODO
|
|
22
|
+
# TODO
|
|
21
23
|
def get_completion_percentage(self, obj):
|
|
22
24
|
"""
|
|
23
25
|
Calculates the percentage of completed videos out of the total videos.
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
Args:
|
|
26
28
|
obj: A dictionary containing 'videosCompleted' and 'totalVideos' keys.
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
Returns:
|
|
29
31
|
The completion percentage as a float rounded to two decimal places, or 0 if totalVideos is zero or less.
|
|
30
32
|
"""
|
|
31
|
-
if obj[
|
|
32
|
-
return round((obj[
|
|
33
|
-
return 0
|
|
33
|
+
if obj["totalVideos"] > 0:
|
|
34
|
+
return round((obj["videosCompleted"] / obj["totalVideos"]) * 100, 2)
|
|
35
|
+
return 0
|
|
@@ -4,20 +4,20 @@ from django.utils.translation import get_language
|
|
|
4
4
|
class TranslatableFieldMixin:
|
|
5
5
|
"""Mixin für automatische Sprachauswahl basierend auf Accept-Language"""
|
|
6
6
|
|
|
7
|
-
def get_localized_name(self, obj, field_base=
|
|
7
|
+
def get_localized_name(self, obj, field_base="name"):
|
|
8
8
|
"""
|
|
9
9
|
Retrieve a localized value for a specified field from an object, using language preference fallbacks.
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
Attempts to return the value of the field with the current language code suffix (e.g., `name_en`). If unavailable or empty, falls back to the German (`_de`) version, then the English (`_en`) version, and finally the base field without a language suffix. Returns an empty string if no value is found.
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
Parameters:
|
|
14
14
|
obj: The object containing the translatable fields.
|
|
15
15
|
field_base (str): The base name of the field to localize (default is 'name').
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
Returns:
|
|
18
18
|
str: The localized field value, or an empty string if none is available.
|
|
19
19
|
"""
|
|
20
|
-
current_lang = get_language() or
|
|
20
|
+
current_lang = get_language() or "en"
|
|
21
21
|
|
|
22
22
|
# Versuche sprachspezifisches Feld
|
|
23
23
|
lang_field = f"{field_base}_{current_lang}"
|
|
@@ -41,4 +41,4 @@ class TranslatableFieldMixin:
|
|
|
41
41
|
return value
|
|
42
42
|
|
|
43
43
|
# Letzter Fallback auf Basis-Feld
|
|
44
|
-
return getattr(obj, field_base,
|
|
44
|
+
return getattr(obj, field_base, "")
|
|
@@ -7,27 +7,29 @@ class UploadJobStatusSerializer(serializers.ModelSerializer):
|
|
|
7
7
|
Read-only serializer for upload job status responses.
|
|
8
8
|
Returns status information for polling endpoints.
|
|
9
9
|
"""
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
sensitive_meta_id = serializers.IntegerField(
|
|
12
|
-
source=
|
|
12
|
+
source="sensitive_meta.id",
|
|
13
13
|
read_only=True,
|
|
14
14
|
allow_null=True,
|
|
15
|
-
help_text="ID of the created SensitiveMeta record (only when anonymized)"
|
|
15
|
+
help_text="ID of the created SensitiveMeta record (only when anonymized)",
|
|
16
16
|
)
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
# Optional helper fields for preview (can be populated by view if needed)
|
|
19
19
|
text = serializers.CharField(read_only=True, required=False, allow_blank=True)
|
|
20
|
-
anonymized_text = serializers.CharField(
|
|
20
|
+
anonymized_text = serializers.CharField(
|
|
21
|
+
read_only=True, required=False, allow_blank=True
|
|
22
|
+
)
|
|
21
23
|
|
|
22
24
|
class Meta:
|
|
23
25
|
model = UploadJob
|
|
24
26
|
fields = [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
"status",
|
|
28
|
+
"error_detail",
|
|
29
|
+
"sensitive_meta_id",
|
|
30
|
+
"id",
|
|
31
|
+
"text",
|
|
32
|
+
"anonymized_text",
|
|
31
33
|
]
|
|
32
34
|
read_only_fields = fields
|
|
33
35
|
|
|
@@ -36,21 +38,24 @@ class UploadJobStatusSerializer(serializers.ModelSerializer):
|
|
|
36
38
|
Customize the representation to only include relevant fields based on status.
|
|
37
39
|
"""
|
|
38
40
|
data = super().to_representation(instance)
|
|
39
|
-
|
|
41
|
+
|
|
40
42
|
# Only include error_detail if status is error
|
|
41
43
|
if instance.status != UploadJob.Status.ERROR:
|
|
42
|
-
data.pop(
|
|
43
|
-
|
|
44
|
+
data.pop("error_detail", None)
|
|
45
|
+
|
|
44
46
|
# Only include sensitive_meta_id if status is anonymized and we have a meta record
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
if (
|
|
48
|
+
instance.status != UploadJob.Status.ANONYMIZED
|
|
49
|
+
or not instance.sensitive_meta
|
|
50
|
+
):
|
|
51
|
+
data.pop("sensitive_meta_id", None)
|
|
52
|
+
|
|
48
53
|
# Remove empty optional fields
|
|
49
|
-
if not data.get(
|
|
50
|
-
data.pop(
|
|
51
|
-
if not data.get(
|
|
52
|
-
data.pop(
|
|
53
|
-
|
|
54
|
+
if not data.get("text"):
|
|
55
|
+
data.pop("text", None)
|
|
56
|
+
if not data.get("anonymized_text"):
|
|
57
|
+
data.pop("anonymized_text", None)
|
|
58
|
+
|
|
54
59
|
return data
|
|
55
60
|
|
|
56
61
|
|
|
@@ -59,13 +64,11 @@ class UploadCreateResponseSerializer(serializers.Serializer):
|
|
|
59
64
|
Serializer for the initial upload response.
|
|
60
65
|
Returns upload_id and status_url for polling.
|
|
61
66
|
"""
|
|
62
|
-
|
|
67
|
+
|
|
63
68
|
upload_id = serializers.UUIDField(
|
|
64
|
-
read_only=True,
|
|
65
|
-
help_text="UUID of the created upload job"
|
|
69
|
+
read_only=True, help_text="UUID of the created upload job"
|
|
66
70
|
)
|
|
67
|
-
|
|
71
|
+
|
|
68
72
|
status_url = serializers.CharField(
|
|
69
|
-
read_only=True,
|
|
70
|
-
|
|
71
|
-
)
|
|
73
|
+
read_only=True, help_text="URL to poll for upload status updates"
|
|
74
|
+
)
|