endoreg-db 0.6.4__py3-none-any.whl → 0.8.1__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 +26 -26
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +12 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +92 -0
- endoreg_db/config/env.py +101 -0
- endoreg_db/data/__init__.py +12 -0
- endoreg_db/data/ai_model/data.yaml +1 -1
- endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
- endoreg_db/data/ai_model_label/label-set/data.yaml +20 -1
- endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
- endoreg_db/data/center/data.yaml +13 -12
- endoreg_db/data/center_shift/ukw.yaml +9 -0
- endoreg_db/data/db_summary.csv +58 -0
- endoreg_db/data/db_summary.xlsx +0 -0
- endoreg_db/data/disease/misc.yaml +1 -2
- endoreg_db/data/endoscopy_processor/data.yaml +3 -0
- endoreg_db/data/event/cardiology.yaml +0 -13
- endoreg_db/data/examination/examinations/data.yaml +14 -9
- endoreg_db/data/examination_indication/endoscopy.yaml +30 -30
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +11 -11
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/finding/complication.yaml +16 -0
- endoreg_db/data/finding/data.yaml +3 -46
- endoreg_db/data/finding/examination_setting.yaml +16 -0
- endoreg_db/data/finding/medication_related.yaml +18 -0
- endoreg_db/data/finding/outcome.yaml +12 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_circularity_default.yaml +0 -2
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_nice.yaml +4 -7
- endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_paris.yaml +0 -8
- endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_planarity_default.yaml +6 -13
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_surface_intact_default.yaml +3 -6
- endoreg_db/data/{finding_location_classification_choice/colonoscopy.yaml → finding_classification_choice/colonoscopy_location.yaml} +11 -22
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +8 -3
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +6 -6
- endoreg_db/data/finding_type/data.yaml +23 -10
- endoreg_db/data/gender/data.yaml +8 -1
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/prediction.yaml +7 -0
- endoreg_db/data/information_source_type/data.yaml +8 -0
- endoreg_db/data/lab_value/misc.yaml +43 -0
- endoreg_db/data/medication/anticoagulation.yaml +5 -5
- endoreg_db/data/medication/tah.yaml +5 -5
- endoreg_db/data/medication_intake_time/base.yaml +4 -4
- endoreg_db/data/names_first/first_names.yaml +3 -0
- endoreg_db/data/pdf_type/data.yaml +26 -2
- endoreg_db/data/qualification/endoscopy.yaml +36 -0
- endoreg_db/data/qualification/m2.yaml +39 -0
- endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
- endoreg_db/data/qualification/sonography.yaml +36 -0
- endoreg_db/data/qualification_type/base.yaml +29 -0
- endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +5 -0
- endoreg_db/data/requirement/age.yaml +26 -0
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +6 -6
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +9 -6
- endoreg_db/data/requirement/disease_hepatology.yaml +1 -1
- endoreg_db/data/requirement/disease_misc.yaml +3 -3
- endoreg_db/data/requirement/disease_renal.yaml +18 -2
- endoreg_db/data/requirement/{colonoscopy_indications.yaml → endoscopy_bleeding_risk.yaml} +6 -3
- endoreg_db/data/requirement/event_cardiology.yaml +17 -17
- endoreg_db/data/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/gender.yaml +25 -0
- endoreg_db/data/requirement/lab_value.yaml +352 -31
- endoreg_db/data/requirement/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/age.yaml +13 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +36 -35
- endoreg_db/data/requirement_operator/model_operators.yaml +13 -7
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +42 -2
- endoreg_db/data/requirement_type/requirement_types.yaml +82 -0
- endoreg_db/data/shift/endoscopy.yaml +21 -0
- endoreg_db/data/shift_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
- endoreg_db/data/unit/concentration.yaml +23 -0
- endoreg_db/exceptions.py +19 -0
- endoreg_db/forms/patient_finding_intervention_form.py +4 -5
- endoreg_db/forms/patient_form.py +7 -6
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/questionnaires/tto_questionnaire.py +19 -19
- endoreg_db/helpers/count_db.py +45 -0
- endoreg_db/helpers/data_loader.py +208 -0
- endoreg_db/helpers/default_objects.py +359 -0
- endoreg_db/helpers/interact.py +6 -0
- endoreg_db/helpers/test_video_helper.py +119 -0
- endoreg_db/logger_conf.py +140 -0
- endoreg_db/management/__init__.py +1 -0
- endoreg_db/management/commands/__init__.py +1 -0
- endoreg_db/management/commands/anonymize_video.py +0 -0
- endoreg_db/management/commands/check_auth.py +125 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
- endoreg_db/management/commands/fix_video_paths.py +165 -0
- endoreg_db/management/commands/import_fallback_video.py +203 -0
- endoreg_db/management/commands/import_report.py +298 -0
- endoreg_db/management/commands/import_video.py +422 -0
- endoreg_db/management/commands/import_video_with_classification.py +367 -0
- endoreg_db/management/commands/init_default_ai_model.py +112 -0
- endoreg_db/management/commands/load_ai_model_data.py +2 -7
- endoreg_db/management/commands/load_base_db_data.py +1 -0
- endoreg_db/management/commands/load_endoscope_data.py +2 -2
- endoreg_db/management/commands/load_examination_indication_data.py +2 -3
- endoreg_db/management/commands/load_finding_data.py +49 -92
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +0 -1
- endoreg_db/management/commands/load_information_source.py +13 -7
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/load_qualification_data.py +59 -0
- endoreg_db/management/commands/load_requirement_data.py +30 -6
- endoreg_db/management/commands/load_shift_data.py +60 -0
- endoreg_db/management/commands/load_tag_data.py +57 -0
- endoreg_db/management/commands/register_ai_model.py +1 -1
- endoreg_db/management/commands/start_filewatcher.py +106 -0
- endoreg_db/management/commands/storage_management.py +548 -0
- endoreg_db/management/commands/summarize_db_content.py +189 -0
- endoreg_db/management/commands/validate_video.py +204 -0
- endoreg_db/management/commands/validate_video_files.py +161 -0
- endoreg_db/management/commands/video_validation.py +22 -0
- endoreg_db/migrations/0001_initial.py +625 -813
- endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
- endoreg_db/models/__init__.py +270 -307
- endoreg_db/models/administration/__init__.py +116 -0
- endoreg_db/models/{ai_model → administration/ai}/__init__.py +6 -1
- endoreg_db/models/administration/ai/active_model.py +35 -0
- endoreg_db/models/administration/ai/ai_model.py +156 -0
- endoreg_db/models/{ai_model → administration/ai}/model_type.py +6 -1
- endoreg_db/models/administration/case/__init__.py +19 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/{case_template → administration/case/case_template}/case_template.py +3 -3
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule.py +3 -10
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule_value.py +2 -4
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_type.py +1 -3
- endoreg_db/models/{center → administration/center}/__init__.py +3 -1
- endoreg_db/models/administration/center/center.py +61 -0
- endoreg_db/models/administration/center/center_product.py +64 -0
- endoreg_db/models/{center → administration/center}/center_resource.py +19 -3
- endoreg_db/models/administration/center/center_shift.py +88 -0
- endoreg_db/models/administration/center/center_waste.py +30 -0
- endoreg_db/models/administration/permissions/__init__.py +44 -0
- endoreg_db/models/administration/person/__init__.py +24 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +35 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
- endoreg_db/models/administration/person/employee/employee_type.py +42 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +54 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/{persons → administration/person/names}/first_name.py +1 -1
- endoreg_db/models/{persons → administration/person/names}/last_name.py +2 -3
- endoreg_db/models/administration/person/patient/__init__.py +5 -0
- endoreg_db/models/administration/person/patient/patient.py +460 -0
- endoreg_db/models/administration/person/profession/__init__.py +24 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
- endoreg_db/models/administration/product/product.py +97 -0
- endoreg_db/models/administration/product/product_group.py +39 -0
- endoreg_db/models/administration/product/product_material.py +54 -0
- endoreg_db/models/{product → administration/product}/product_weight.py +9 -0
- endoreg_db/models/{product → administration/product}/reference_product.py +26 -11
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +37 -0
- endoreg_db/models/administration/qualification/qualification_type.py +35 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +69 -0
- endoreg_db/models/administration/shift/shift.py +51 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/label/__init__.py +24 -1
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +84 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
- endoreg_db/models/label/label.py +45 -74
- endoreg_db/models/label/label_set.py +53 -0
- endoreg_db/models/label/label_type.py +29 -0
- endoreg_db/models/label/label_video_segment/__init__.py +3 -0
- endoreg_db/models/label/label_video_segment/_create_from_video.py +41 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
- endoreg_db/models/label/video_segmentation_label.py +31 -0
- endoreg_db/models/{annotation → label}/video_segmentation_labelset.py +7 -0
- endoreg_db/models/media/__init__.py +14 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +111 -0
- endoreg_db/models/media/pdf/__init__.py +11 -0
- endoreg_db/models/media/pdf/raw_pdf.py +608 -0
- endoreg_db/models/media/pdf/report_file.py +162 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +77 -0
- endoreg_db/models/media/video/__init__.py +4 -0
- endoreg_db/models/media/video/create_from_file.py +336 -0
- endoreg_db/models/media/video/pipe_1.py +195 -0
- endoreg_db/models/media/video/pipe_2.py +105 -0
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file.py +680 -0
- endoreg_db/models/media/video/video_file_ai.py +443 -0
- endoreg_db/models/media/video/video_file_anonymize.py +348 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -0
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +104 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/media/video/video_file_io.py +166 -0
- endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +45 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
- endoreg_db/models/media/video/video_file_meta.py +11 -0
- endoreg_db/models/media/video/video_file_segments.py +209 -0
- endoreg_db/models/medical/__init__.py +146 -0
- endoreg_db/models/{contraindication → medical/contraindication}/__init__.py +1 -5
- endoreg_db/models/{disease.py → medical/disease.py} +60 -52
- endoreg_db/models/{event.py → medical/event.py} +31 -54
- endoreg_db/models/{examination → medical/examination}/__init__.py +1 -1
- endoreg_db/models/medical/examination/examination.py +148 -0
- endoreg_db/models/{examination → medical/examination}/examination_indication.py +64 -35
- endoreg_db/models/{examination → medical/examination}/examination_time.py +0 -4
- endoreg_db/models/{examination → medical/examination}/examination_time_type.py +1 -8
- endoreg_db/models/{examination → medical/examination}/examination_type.py +1 -7
- endoreg_db/models/medical/finding/__init__.py +18 -0
- endoreg_db/models/medical/finding/finding.py +96 -0
- endoreg_db/models/medical/finding/finding_classification.py +142 -0
- endoreg_db/models/{finding → medical/finding}/finding_intervention.py +2 -10
- endoreg_db/models/medical/finding/finding_type.py +35 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/{hardware → medical/hardware}/endoscope.py +28 -23
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +419 -0
- endoreg_db/models/{medication → medical/medication}/medication.py +1 -3
- endoreg_db/models/{medication → medical/medication}/medication_indication_type.py +8 -3
- endoreg_db/models/{medication → medical/medication}/medication_intake_time.py +21 -3
- endoreg_db/models/{medication → medical/medication}/medication_schedule.py +13 -5
- endoreg_db/models/{organ → medical/organ}/__init__.py +3 -6
- endoreg_db/models/medical/patient/__init__.py +56 -0
- endoreg_db/models/medical/patient/medication_examples.py +38 -0
- endoreg_db/models/medical/patient/patient_disease.py +63 -0
- endoreg_db/models/medical/patient/patient_event.py +75 -0
- endoreg_db/models/medical/patient/patient_examination.py +249 -0
- endoreg_db/models/{persons → medical}/patient/patient_examination_indication.py +21 -9
- endoreg_db/models/medical/patient/patient_finding.py +357 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
- endoreg_db/models/{patient → medical/patient}/patient_finding_intervention.py +15 -1
- endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
- endoreg_db/models/{persons → medical}/patient/patient_lab_value.py +40 -15
- endoreg_db/models/medical/patient/patient_medication.py +104 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
- endoreg_db/models/{risk → medical/risk}/risk_type.py +0 -4
- endoreg_db/models/{data_file/metadata → metadata}/__init__.py +6 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/metadata/model_meta.py +193 -0
- endoreg_db/models/metadata/model_meta_logic.py +236 -0
- endoreg_db/models/{data_file/metadata → metadata}/pdf_meta.py +28 -13
- endoreg_db/models/metadata/sensitive_meta.py +288 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +643 -0
- endoreg_db/models/metadata/video_meta.py +332 -0
- endoreg_db/models/metadata/video_prediction_logic.py +190 -0
- endoreg_db/models/metadata/video_prediction_meta.py +270 -0
- endoreg_db/models/other/__init__.py +17 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +0 -2
- endoreg_db/models/other/distribution/numeric_value_distribution.py +30 -2
- endoreg_db/models/{emission → other/emission}/emission_factor.py +15 -6
- endoreg_db/models/{persons → other}/gender.py +8 -3
- endoreg_db/models/other/information_source.py +159 -0
- endoreg_db/models/other/material.py +10 -2
- endoreg_db/models/other/resource.py +6 -2
- endoreg_db/models/other/tag.py +27 -0
- endoreg_db/models/other/transport_route.py +13 -2
- endoreg_db/models/{unit.py → other/unit.py} +16 -6
- endoreg_db/models/other/waste.py +10 -3
- endoreg_db/models/requirement/requirement.py +556 -114
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +4 -132
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +80 -87
- endoreg_db/models/requirement/requirement_operator.py +132 -14
- endoreg_db/models/requirement/requirement_set.py +181 -21
- endoreg_db/models/rule/__init__.py +13 -0
- endoreg_db/models/{rules → rule}/rule.py +6 -3
- endoreg_db/models/{rules → rule}/rule_attribute_dtype.py +0 -2
- endoreg_db/models/{rules → rule}/rule_type.py +0 -2
- endoreg_db/models/{rules → rule}/ruleset.py +0 -2
- endoreg_db/models/state/__init__.py +12 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/audit_ledger.py +150 -0
- endoreg_db/models/state/label_video_segment.py +22 -0
- endoreg_db/models/state/raw_pdf.py +187 -0
- endoreg_db/models/state/sensitive_meta.py +46 -0
- endoreg_db/models/state/video.py +232 -0
- endoreg_db/models/upload_job.py +99 -0
- endoreg_db/models/utils.py +135 -0
- endoreg_db/models/video_metadata.py +66 -0
- endoreg_db/models/video_processing.py +153 -0
- endoreg_db/renames.yml +8 -0
- endoreg_db/root_urls.py +9 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +27 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
- endoreg_db/serializers/__init__.py +147 -10
- endoreg_db/serializers/{raw_pdf_meta_validation.py → _old/raw_pdf_meta_validation.py} +3 -3
- endoreg_db/serializers/{raw_video_meta_validation.py → _old/raw_video_meta_validation.py} +18 -14
- endoreg_db/serializers/_old/video.py +71 -0
- endoreg_db/serializers/administration/__init__.py +14 -0
- endoreg_db/serializers/administration/ai/__init__.py +10 -0
- endoreg_db/serializers/administration/ai/active_model.py +10 -0
- endoreg_db/serializers/administration/ai/ai_model.py +18 -0
- endoreg_db/serializers/administration/ai/model_type.py +10 -0
- endoreg_db/serializers/administration/center.py +9 -0
- endoreg_db/serializers/administration/gender.py +9 -0
- endoreg_db/serializers/anonymization.py +66 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +46 -0
- endoreg_db/serializers/examination/dropdown.py +21 -0
- endoreg_db/serializers/examination_serializer.py +12 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +54 -0
- endoreg_db/serializers/finding_classification/__init__.py +7 -0
- endoreg_db/serializers/finding_classification/choice.py +19 -0
- endoreg_db/serializers/finding_classification/classification.py +13 -0
- endoreg_db/serializers/label/__init__.py +7 -0
- endoreg_db/serializers/label/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/__init__.py +7 -0
- endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
- endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
- endoreg_db/serializers/meta/__init__.py +19 -0
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
- endoreg_db/serializers/meta/report_meta.py +53 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -0
- endoreg_db/serializers/meta/video_meta.py +39 -0
- endoreg_db/serializers/misc/__init__.py +14 -0
- endoreg_db/serializers/misc/file_overview.py +152 -0
- endoreg_db/serializers/misc/stats.py +33 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +71 -0
- endoreg_db/serializers/misc/vop_patient_data.py +120 -0
- endoreg_db/serializers/patient/__init__.py +11 -0
- endoreg_db/serializers/patient/patient.py +86 -0
- endoreg_db/serializers/patient/patient_dropdown.py +27 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
- endoreg_db/serializers/pdf/__init__.py +5 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
- endoreg_db/serializers/report/__init__.py +9 -0
- endoreg_db/serializers/report/mixins.py +45 -0
- endoreg_db/serializers/report/report.py +105 -0
- endoreg_db/serializers/report/report_list.py +22 -0
- endoreg_db/serializers/report/secure_file_url.py +26 -0
- endoreg_db/serializers/requirements/requirement_schema.py +25 -0
- endoreg_db/serializers/requirements/requirement_sets.py +29 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/segmentation.py +263 -0
- endoreg_db/serializers/video/video_file_brief.py +10 -0
- endoreg_db/serializers/video/video_file_detail.py +83 -0
- endoreg_db/serializers/video/video_file_list.py +67 -0
- endoreg_db/serializers/video/video_metadata.py +105 -0
- endoreg_db/serializers/video/video_processing_history.py +153 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +223 -0
- endoreg_db/services/examination_evaluation.py +149 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +241 -0
- endoreg_db/services/lookup_store.py +122 -0
- endoreg_db/services/ollama_api_docs.py +1528 -0
- endoreg_db/services/pdf_import.py +993 -0
- endoreg_db/services/polling_coordinator.py +288 -0
- endoreg_db/services/pseudonym_service.py +89 -0
- endoreg_db/services/requirements_object.py +147 -0
- endoreg_db/services/segment_sync.py +155 -0
- endoreg_db/services/storage_aware_video_processor.py +344 -0
- endoreg_db/services/video_import.py +915 -0
- endoreg_db/tasks/upload_tasks.py +207 -0
- endoreg_db/tasks/video_ingest.py +157 -0
- endoreg_db/tasks/video_processing_tasks.py +327 -0
- endoreg_db/urls/__init__.py +72 -0
- endoreg_db/urls/anonymization.py +32 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +39 -0
- endoreg_db/urls/examination.py +54 -0
- endoreg_db/urls/files.py +6 -0
- endoreg_db/urls/label_video_segment_validate.py +33 -0
- endoreg_db/urls/label_video_segments.py +44 -0
- endoreg_db/urls/media.py +32 -0
- endoreg_db/urls/patient.py +19 -0
- endoreg_db/urls/pdf.py +0 -0
- endoreg_db/urls/report.py +78 -0
- endoreg_db/urls/requirements.py +13 -0
- endoreg_db/urls/sensitive_meta.py +36 -0
- endoreg_db/urls/stats.py +46 -0
- endoreg_db/urls/upload.py +20 -0
- endoreg_db/urls/video.py +119 -0
- endoreg_db/urls.py +6 -283
- endoreg_db/utils/__init__.py +66 -57
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/{models/ai_model/utils.py → utils/ai/get.py} +1 -4
- endoreg_db/{models/ai_model/lightning → utils/ai}/inference_dataset.py +0 -1
- endoreg_db/{models/ai_model/lightning → utils/ai}/multilabel_classification_net.py +14 -10
- endoreg_db/{models/ai_model/lightning → utils/ai}/postprocess.py +15 -5
- endoreg_db/utils/ai/predict.py +291 -0
- endoreg_db/{models/ai_model/lightning → utils/ai}/preprocess.py +1 -1
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +0 -0
- endoreg_db/utils/check_video_files.py +148 -0
- endoreg_db/utils/dataloader.py +50 -12
- endoreg_db/utils/dates.py +21 -0
- endoreg_db/utils/env.py +33 -0
- endoreg_db/utils/extract_specific_frames.py +72 -0
- endoreg_db/utils/file_operations.py +29 -1
- endoreg_db/utils/fix_video_path_direct.py +141 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +193 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +2 -0
- endoreg_db/utils/paths.py +100 -82
- endoreg_db/utils/permissions.py +143 -0
- endoreg_db/utils/pipelines/Readme.md +235 -0
- endoreg_db/utils/pipelines/__init__.py +0 -0
- endoreg_db/utils/pipelines/process_video_dir.py +120 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +20 -0
- endoreg_db/utils/product/sum_weights.py +18 -0
- endoreg_db/utils/pydantic_models/db_config.py +1 -1
- endoreg_db/utils/requirement_helpers.py +0 -0
- endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
- endoreg_db/utils/requirement_operator_logic/lab_value_operators.py +578 -0
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
- endoreg_db/utils/translation.py +27 -0
- endoreg_db/utils/validate_video_detailed.py +357 -0
- endoreg_db/utils/video/__init__.py +19 -6
- endoreg_db/utils/video/extract_frames.py +37 -70
- endoreg_db/utils/video/ffmpeg_wrapper.py +772 -0
- endoreg_db/utils/video/names.py +42 -0
- endoreg_db/utils/video/streaming_processor.py +312 -0
- endoreg_db/utils/video/video_splitter.py +94 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
- endoreg_db/views/__init__.py +282 -2
- endoreg_db/views/anonymization/__init__.py +27 -0
- endoreg_db/views/anonymization/media_management.py +454 -0
- endoreg_db/views/anonymization/overview.py +216 -0
- endoreg_db/views/anonymization/validate.py +63 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/{views.py → auth/keycloak.py} +19 -13
- endoreg_db/views/examination/__init__.py +33 -0
- endoreg_db/views/examination/examination.py +37 -0
- endoreg_db/views/examination/examination_manifest_cache.py +26 -0
- endoreg_db/views/examination/get_finding_classification_choices.py +59 -0
- endoreg_db/views/examination/get_finding_classifications.py +36 -0
- endoreg_db/views/examination/get_findings.py +41 -0
- endoreg_db/views/examination/get_instruments.py +18 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +112 -0
- endoreg_db/views/finding/get_classifications.py +14 -0
- endoreg_db/views/finding/get_interventions.py +17 -0
- endoreg_db/views/finding_classification/__init__.py +13 -0
- endoreg_db/views/finding_classification/base.py +0 -0
- endoreg_db/views/finding_classification/finding_classification.py +42 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
- endoreg_db/views/label/__init__.py +5 -0
- endoreg_db/views/label/label.py +15 -0
- endoreg_db/views/label_video_segment/__init__.py +16 -0
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
- endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
- endoreg_db/views/label_video_segment/validate.py +226 -0
- endoreg_db/views/media/__init__.py +9 -0
- endoreg_db/views/media/pdf_media.py +386 -0
- endoreg_db/views/media/video_media.py +272 -0
- endoreg_db/views/meta/__init__.py +15 -0
- endoreg_db/views/meta/available_files_list.py +146 -0
- endoreg_db/views/meta/report_meta.py +53 -0
- endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
- endoreg_db/views/meta/sensitive_meta_list.py +104 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
- endoreg_db/views/misc/__init__.py +63 -0
- endoreg_db/views/misc/center.py +13 -0
- endoreg_db/views/misc/gender.py +14 -0
- endoreg_db/views/misc/secure_file_serving_view.py +80 -0
- endoreg_db/views/misc/secure_file_url_view.py +84 -0
- endoreg_db/views/misc/secure_url_validate.py +79 -0
- endoreg_db/views/misc/stats.py +220 -0
- endoreg_db/views/misc/translation.py +182 -0
- endoreg_db/views/misc/upload_views.py +240 -0
- endoreg_db/views/patient/__init__.py +5 -0
- endoreg_db/views/patient/patient.py +210 -0
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +140 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
- endoreg_db/views/patient_examination/video.py +194 -0
- endoreg_db/views/patient_finding/__init__.py +7 -0
- endoreg_db/views/patient_finding/base.py +0 -0
- endoreg_db/views/patient_finding/patient_finding.py +64 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
- endoreg_db/views/patient_finding_location/__init__.py +5 -0
- endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
- endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
- endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
- endoreg_db/views/pdf/__init__.py +11 -0
- endoreg_db/views/pdf/pdf_media.py +239 -0
- endoreg_db/views/pdf/pdf_stream_views.py +127 -0
- endoreg_db/views/pdf/reimport.py +151 -0
- endoreg_db/views/report/__init__.py +9 -0
- endoreg_db/views/report/report_list.py +112 -0
- endoreg_db/views/report/report_with_secure_url.py +28 -0
- endoreg_db/views/report/start_examination.py +7 -0
- endoreg_db/views/requirement/__init__.py +10 -0
- endoreg_db/views/requirement/evaluate.py +279 -0
- endoreg_db/views/requirement/lookup.py +483 -0
- endoreg_db/views/requirement/lookup_store.py +252 -0
- endoreg_db/views/requirement_lookup/lookup.py +0 -0
- endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
- endoreg_db/views/stats/__init__.py +13 -0
- endoreg_db/views/stats/stats_views.py +229 -0
- endoreg_db/views/video/__init__.py +72 -0
- endoreg_db/views/video/correction.py +672 -0
- endoreg_db/views/video/media/__init__.py +23 -0
- endoreg_db/views/video/media/task_status.py +49 -0
- endoreg_db/views/video/media/video_analyze.py +52 -0
- endoreg_db/views/video/media/video_apply_mask.py +48 -0
- endoreg_db/views/video/media/video_correction.py +21 -0
- endoreg_db/views/video/media/video_download_processed.py +58 -0
- endoreg_db/views/video/media/video_media.py +158 -0
- endoreg_db/views/video/media/video_meta.py +29 -0
- endoreg_db/views/video/media/video_processing_history.py +24 -0
- endoreg_db/views/video/media/video_remove_frames.py +48 -0
- endoreg_db/views/video/media/video_reprocess.py +40 -0
- endoreg_db/views/video/reimport.py +192 -0
- endoreg_db/views/video/segmentation.py +274 -0
- endoreg_db/views/{views_for_timeline.py → video/timeline.py} +3 -3
- endoreg_db/views/video/video_examination_viewset.py +329 -0
- endoreg_db/views/video/video_stream.py +188 -0
- endoreg_db-0.8.1.dist-info/METADATA +384 -0
- endoreg_db-0.8.1.dist-info/RECORD +789 -0
- endoreg_db/data/agl_service/data.yaml +0 -19
- endoreg_db/data/finding_location_classification/colonoscopy.yaml +0 -46
- endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +0 -48
- endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +0 -57
- endoreg_db/management/commands/_load_model_template.py +0 -41
- endoreg_db/management/commands/delete_all.py +0 -18
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +0 -32
- endoreg_db/management/commands/fix_auth_permission.py +0 -20
- endoreg_db/management/commands/load_active_model_data.py +0 -45
- endoreg_db/management/commands/load_g_play_data.py +0 -113
- endoreg_db/management/commands/load_logging_data.py +0 -39
- endoreg_db/management/commands/load_lx_data.py +0 -64
- endoreg_db/management/commands/load_medication_indication_data.py +0 -63
- endoreg_db/management/commands/load_medication_indication_type_data.py +0 -41
- endoreg_db/management/commands/load_medication_intake_time_data.py +0 -41
- endoreg_db/management/commands/load_medication_schedule_data.py +0 -55
- endoreg_db/management/commands/load_network_data.py +0 -57
- endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +0 -23
- endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +0 -23
- endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +0 -25
- endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +0 -33
- endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +0 -23
- endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +0 -24
- endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +0 -48
- endoreg_db/migrations/0009_requirementoperator_requirementsettype_and_more.py +0 -154
- endoreg_db/models/ai_model/active_model.py +0 -9
- endoreg_db/models/ai_model/ai_model.py +0 -90
- endoreg_db/models/ai_model/lightning/__init__.py +0 -3
- endoreg_db/models/ai_model/lightning/predict.py +0 -172
- endoreg_db/models/ai_model/lightning/prediction_visualizer.py +0 -55
- endoreg_db/models/ai_model/lightning/run_visualizer.py +0 -21
- endoreg_db/models/ai_model/model_meta.py +0 -240
- endoreg_db/models/annotation/__init__.py +0 -32
- endoreg_db/models/annotation/anonymized_image_annotation.py +0 -115
- endoreg_db/models/annotation/binary_classification_annotation_task.py +0 -117
- endoreg_db/models/annotation/image_classification.py +0 -86
- endoreg_db/models/annotation/video_segmentation_annotation.py +0 -52
- endoreg_db/models/case/__init__.py +0 -1
- endoreg_db/models/case/case.py +0 -34
- endoreg_db/models/center/center.py +0 -51
- endoreg_db/models/center/center_product.py +0 -33
- endoreg_db/models/center/center_waste.py +0 -16
- endoreg_db/models/data_file/__init__.py +0 -39
- endoreg_db/models/data_file/base_classes/__init__.py +0 -7
- endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -98
- endoreg_db/models/data_file/base_classes/abstract_pdf.py +0 -127
- endoreg_db/models/data_file/base_classes/abstract_video.py +0 -806
- endoreg_db/models/data_file/base_classes/frame_helpers.py +0 -17
- endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +0 -19
- endoreg_db/models/data_file/base_classes/utils.py +0 -58
- endoreg_db/models/data_file/frame.py +0 -29
- endoreg_db/models/data_file/import_classes/__init__.py +0 -18
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +0 -35
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +0 -28
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +0 -260
- endoreg_db/models/data_file/import_classes/raw_pdf.py +0 -254
- endoreg_db/models/data_file/import_classes/raw_video.py +0 -290
- endoreg_db/models/data_file/metadata/sensitive_meta.py +0 -290
- endoreg_db/models/data_file/metadata/video_meta.py +0 -199
- endoreg_db/models/data_file/report_file.py +0 -56
- endoreg_db/models/data_file/video/__init__.py +0 -11
- endoreg_db/models/data_file/video/import_meta.py +0 -25
- endoreg_db/models/data_file/video/video.py +0 -196
- endoreg_db/models/data_file/video_segment.py +0 -214
- endoreg_db/models/examination/examination.py +0 -67
- endoreg_db/models/finding/__init__.py +0 -11
- endoreg_db/models/finding/finding.py +0 -75
- endoreg_db/models/finding/finding_location_classification.py +0 -94
- endoreg_db/models/finding/finding_morphology_classification.py +0 -89
- endoreg_db/models/finding/finding_type.py +0 -22
- endoreg_db/models/hardware/__init__.py +0 -2
- endoreg_db/models/information_source.py +0 -65
- endoreg_db/models/laboratory/__init__.py +0 -1
- endoreg_db/models/laboratory/lab_value.py +0 -162
- endoreg_db/models/logging/__init__.py +0 -11
- endoreg_db/models/logging/agl_service.py +0 -19
- endoreg_db/models/logging/base.py +0 -22
- endoreg_db/models/logging/log_type.py +0 -23
- endoreg_db/models/logging/network_device.py +0 -27
- endoreg_db/models/lx/__init__.py +0 -4
- endoreg_db/models/lx/client.py +0 -57
- endoreg_db/models/lx/identity.py +0 -34
- endoreg_db/models/lx/permission.py +0 -18
- endoreg_db/models/lx/user.py +0 -16
- endoreg_db/models/network/__init__.py +0 -9
- endoreg_db/models/network/agl_service.py +0 -38
- endoreg_db/models/network/network_device.py +0 -58
- endoreg_db/models/network/network_device_type.py +0 -23
- endoreg_db/models/other/distribution.py +0 -5
- endoreg_db/models/patient/__init__.py +0 -24
- endoreg_db/models/patient/patient_examination.py +0 -182
- endoreg_db/models/patient/patient_finding.py +0 -143
- endoreg_db/models/patient/patient_finding_location.py +0 -120
- endoreg_db/models/patient/patient_finding_morphology.py +0 -166
- endoreg_db/models/permissions/__init__.py +0 -44
- endoreg_db/models/persons/__init__.py +0 -34
- endoreg_db/models/persons/examiner/__init__.py +0 -2
- endoreg_db/models/persons/examiner/examiner.py +0 -60
- endoreg_db/models/persons/examiner/examiner_type.py +0 -2
- endoreg_db/models/persons/patient/__init__.py +0 -8
- endoreg_db/models/persons/patient/patient.py +0 -389
- endoreg_db/models/persons/patient/patient_disease.py +0 -22
- endoreg_db/models/persons/patient/patient_event.py +0 -52
- endoreg_db/models/persons/patient/patient_lab_sample.py +0 -108
- endoreg_db/models/persons/patient/patient_medication.py +0 -59
- endoreg_db/models/persons/patient/patient_medication_schedule.py +0 -88
- endoreg_db/models/persons/portal_user_information.py +0 -27
- endoreg_db/models/prediction/__init__.py +0 -8
- endoreg_db/models/prediction/image_classification.py +0 -51
- endoreg_db/models/prediction/video_prediction_meta.py +0 -306
- endoreg_db/models/product/product.py +0 -110
- endoreg_db/models/product/product_group.py +0 -27
- endoreg_db/models/product/product_material.py +0 -28
- endoreg_db/models/questionnaires/__init__.py +0 -114
- endoreg_db/models/quiz/__init__.py +0 -9
- endoreg_db/models/quiz/quiz_answer.py +0 -41
- endoreg_db/models/quiz/quiz_question.py +0 -54
- endoreg_db/models/report_reader/report_reader_config.py +0 -53
- endoreg_db/models/rules/__init__.py +0 -5
- endoreg_db/queries/get/__init__.py +0 -6
- endoreg_db/queries/get/center.py +0 -42
- endoreg_db/queries/get/model.py +0 -13
- endoreg_db/queries/get/patient.py +0 -14
- endoreg_db/queries/get/patient_examination.py +0 -20
- endoreg_db/queries/get/report_file.py +0 -33
- endoreg_db/queries/get/video.py +0 -31
- endoreg_db/serializers/ai_model.py +0 -19
- endoreg_db/serializers/annotation.py +0 -14
- endoreg_db/serializers/center.py +0 -11
- endoreg_db/serializers/examination.py +0 -33
- endoreg_db/serializers/frame.py +0 -9
- endoreg_db/serializers/hardware.py +0 -21
- endoreg_db/serializers/label.py +0 -22
- endoreg_db/serializers/patient.py +0 -33
- endoreg_db/serializers/prediction.py +0 -10
- endoreg_db/serializers/raw_pdf_anony_text_validation.py +0 -137
- endoreg_db/serializers/report_file.py +0 -7
- endoreg_db/serializers/video.py +0 -20
- endoreg_db/serializers/video_segmentation.py +0 -574
- endoreg_db/tests.py +0 -3
- endoreg_db/utils/legacy_ocr.py +0 -201
- endoreg_db/utils/video/transcode_videofile.py +0 -111
- endoreg_db/views/patient_views.py +0 -90
- endoreg_db/views/raw_pdf_anony_text_validation_views.py +0 -95
- endoreg_db/views/raw_pdf_meta_validation_views.py +0 -111
- endoreg_db/views/raw_video_meta_validation_views.py +0 -148
- endoreg_db/views/report_views.py +0 -96
- endoreg_db/views/video_segmentation_views.py +0 -166
- endoreg_db-0.6.4.dist-info/METADATA +0 -161
- endoreg_db-0.6.4.dist-info/RECORD +0 -470
- /endoreg_db/{case_generator/__init__.py → api/serializers/finding_descriptions.py} +0 -0
- /endoreg_db/{queries/get/annotation.py → api/views/finding_descriptions.py} +0 -0
- /endoreg_db/{queries/get/prediction.py → data/shift/m2.yaml} +0 -0
- /endoreg_db/{queries/get/video_import_meta.py → factories/__init__.py} +0 -0
- /endoreg_db/{queries/get/video_prediction_meta.py → helpers/__init__.py} +0 -0
- /endoreg_db/models/{case_template → administration/case/case_template}/__init__.py +0 -0
- /endoreg_db/models/{persons → administration/person}/person.py +0 -0
- /endoreg_db/models/{product → administration/product}/__init__.py +0 -0
- /endoreg_db/models/{report_reader → media/pdf/report_reader}/__init__.py +0 -0
- /endoreg_db/models/{report_reader → media/pdf/report_reader}/report_reader_flag.py +0 -0
- /endoreg_db/models/{hardware → medical/hardware}/endoscopy_processor.py +0 -0
- /endoreg_db/models/{medication → medical/medication}/__init__.py +0 -0
- /endoreg_db/models/{medication → medical/medication}/medication_indication.py +0 -0
- /endoreg_db/models/{risk → medical/risk}/__init__.py +0 -0
- /endoreg_db/models/{risk → medical/risk}/risk.py +0 -0
- /endoreg_db/models/{emission → other/emission}/__init__.py +0 -0
- /endoreg_db/models/{rules → rule}/rule_applicator.py +0 -0
- /endoreg_db/{case_generator → utils/case_generator}/case_generator.py +0 -0
- /endoreg_db/{case_generator → utils/case_generator}/lab_sample_factory.py +0 -0
- /endoreg_db/{case_generator → utils/case_generator}/utils.py +0 -0
- /endoreg_db/views/{csrf.py → misc/csrf.py} +0 -0
- {endoreg_db-0.6.4.dist-info → endoreg_db-0.8.1.dist-info}/WHEEL +0 -0
- {endoreg_db-0.6.4.dist-info → endoreg_db-0.8.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
from typing import List
|
|
3
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from urllib.parse import urljoin
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from ...models import LabelVideoSegment, VideoFile
|
|
9
|
+
import logging
|
|
10
|
+
from ._lvs_create import (
|
|
11
|
+
_create,
|
|
12
|
+
_get_video_file,
|
|
13
|
+
_get_label,
|
|
14
|
+
_validate_fps,
|
|
15
|
+
_calculate_frame_numbers,
|
|
16
|
+
_get_information_source
|
|
17
|
+
)
|
|
18
|
+
from ._lvs_update import (
|
|
19
|
+
_update,
|
|
20
|
+
)
|
|
21
|
+
from ._lvs_validate import (
|
|
22
|
+
_validate,
|
|
23
|
+
_extract_and_validate_basic_attrs,
|
|
24
|
+
_process_time_data,
|
|
25
|
+
_process_frame_data,
|
|
26
|
+
_validate_time_and_frame_presence,
|
|
27
|
+
_validate_time_constraints,
|
|
28
|
+
_validate_frame_constraints
|
|
29
|
+
)
|
|
30
|
+
from endoreg_db.serializers import ImageClassificationAnnotationSerializer
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
# add these small helpers (could be private functions in this module)
|
|
35
|
+
def _media_relpath_from_file_path(file_path) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Return a media-relative path (never an absolute server path).
|
|
38
|
+
If MEDIA_ROOT is a prefix, strip it; otherwise return the basename.
|
|
39
|
+
Accepts str or Path-like.
|
|
40
|
+
"""
|
|
41
|
+
p = Path(str(file_path))
|
|
42
|
+
media_root = getattr(settings, "MEDIA_ROOT", None)
|
|
43
|
+
if media_root:
|
|
44
|
+
try:
|
|
45
|
+
rel = p.resolve().relative_to(Path(media_root).resolve())
|
|
46
|
+
return rel.as_posix()
|
|
47
|
+
except Exception:
|
|
48
|
+
pass
|
|
49
|
+
return p.name # safe fallback
|
|
50
|
+
|
|
51
|
+
def _media_url_from_file_path(file_path, request=None) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Build a public URL for the file using MEDIA_URL + relpath.
|
|
54
|
+
If `request` is provided, return an absolute URL.
|
|
55
|
+
"""
|
|
56
|
+
base = getattr(settings, "MEDIA_URL", "/media/")
|
|
57
|
+
if not base.endswith("/"):
|
|
58
|
+
base += "/"
|
|
59
|
+
rel = _media_relpath_from_file_path(file_path)
|
|
60
|
+
url = urljoin(base, rel)
|
|
61
|
+
if request is not None:
|
|
62
|
+
try:
|
|
63
|
+
return request.build_absolute_uri(url)
|
|
64
|
+
except Exception:
|
|
65
|
+
pass
|
|
66
|
+
return url
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class LabelVideoSegmentSerializer(serializers.ModelSerializer):
|
|
70
|
+
"""Serializer for creating and retrieving LabelVideoSegment instances."""
|
|
71
|
+
|
|
72
|
+
# Additional fields for convenience - matching frontend expectations
|
|
73
|
+
start_time = serializers.SerializerMethodField()
|
|
74
|
+
end_time = serializers.SerializerMethodField()
|
|
75
|
+
|
|
76
|
+
# Input fields (write_only for creation)
|
|
77
|
+
video_id = serializers.IntegerField(required=False, help_text="Video file ID")
|
|
78
|
+
label_id = serializers.IntegerField(required=False, allow_null=True, help_text="Label ID")
|
|
79
|
+
|
|
80
|
+
# Add support for label names (both Label and VideoSegmentationLabel)
|
|
81
|
+
label_name = serializers.CharField(write_only=True, required=False, allow_null=True, help_text="Label name")
|
|
82
|
+
label_display = serializers.SerializerMethodField()
|
|
83
|
+
|
|
84
|
+
# Read-only fields for response
|
|
85
|
+
video_name = serializers.SerializerMethodField(read_only=True)
|
|
86
|
+
frame_predictions = serializers.SerializerMethodField(read_only=True, help_text="Frame predictions for the video segment")
|
|
87
|
+
manual_frame_annotations = serializers.SerializerMethodField(read_only=True, help_text="Manual frame annotations for the video segment")
|
|
88
|
+
|
|
89
|
+
time_segments = serializers.SerializerMethodField(read_only=True, help_text="Time segments for the video segment")
|
|
90
|
+
|
|
91
|
+
create = _create
|
|
92
|
+
get_video_file = _get_video_file
|
|
93
|
+
get_label = _get_label
|
|
94
|
+
validate_fps = _validate_fps
|
|
95
|
+
calculate_frame_numbers = _calculate_frame_numbers
|
|
96
|
+
get_information_source = _get_information_source
|
|
97
|
+
|
|
98
|
+
update = _update
|
|
99
|
+
|
|
100
|
+
validate = _validate
|
|
101
|
+
extract_and_validate_basic_attrs = _extract_and_validate_basic_attrs
|
|
102
|
+
process_time_data = _process_time_data
|
|
103
|
+
process_frame_data = _process_frame_data
|
|
104
|
+
validate_time_and_frame_presence = _validate_time_and_frame_presence
|
|
105
|
+
validate_time_constraints = _validate_time_constraints
|
|
106
|
+
validate_frame_constraints = _validate_frame_constraints
|
|
107
|
+
|
|
108
|
+
class Meta:
|
|
109
|
+
model = LabelVideoSegment
|
|
110
|
+
fields = [
|
|
111
|
+
'id',
|
|
112
|
+
"video_file",
|
|
113
|
+
'video_name',
|
|
114
|
+
"video_id",
|
|
115
|
+
"label",
|
|
116
|
+
'label_name',
|
|
117
|
+
"label_id",
|
|
118
|
+
'start_frame_number',
|
|
119
|
+
'end_frame_number',
|
|
120
|
+
'start_time',
|
|
121
|
+
'end_time',
|
|
122
|
+
"label_display",
|
|
123
|
+
"frame_predictions",
|
|
124
|
+
"manual_frame_annotations",
|
|
125
|
+
"time_segments"
|
|
126
|
+
]
|
|
127
|
+
read_only_fields = ['id', 'video_name']
|
|
128
|
+
extra_kwargs = {
|
|
129
|
+
'start_frame_number': {'required': False},
|
|
130
|
+
'end_frame_number': {'required': False},
|
|
131
|
+
'video_file': {'required': False},
|
|
132
|
+
'label': {'required': False},
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def __init__(self, *args, **kwargs):
|
|
137
|
+
"""
|
|
138
|
+
Initialize the serializer and log the initial input data if available.
|
|
139
|
+
"""
|
|
140
|
+
super().__init__(*args, **kwargs)
|
|
141
|
+
if hasattr(self, 'initial_data'):
|
|
142
|
+
logger.debug(f"Serializer initialized with data: {self.initial_data}")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def get_time_segments(self, obj: LabelVideoSegment) -> List[dict]:
|
|
146
|
+
frames = obj.frames
|
|
147
|
+
time_segments = {
|
|
148
|
+
"segment_id": obj.id,
|
|
149
|
+
"segment_start": obj.start_frame_number,
|
|
150
|
+
"segment_end": obj.end_frame_number,
|
|
151
|
+
"start_time": obj.start_time,
|
|
152
|
+
"end_time": obj.end_time,
|
|
153
|
+
"frames": []
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
request = self.context.get("request") if hasattr(self, "context") else None
|
|
157
|
+
|
|
158
|
+
for frame in frames:
|
|
159
|
+
all_classifications = ImageClassificationAnnotationSerializer(
|
|
160
|
+
frame.image_classification_annotations.all(), many=True
|
|
161
|
+
).data
|
|
162
|
+
predictions = ImageClassificationAnnotationSerializer(frame.predictions, many=True).data
|
|
163
|
+
manual_annotations = ImageClassificationAnnotationSerializer(
|
|
164
|
+
frame.manual_annotations, many=True
|
|
165
|
+
).data if frame.has_manual_annotations else []
|
|
166
|
+
|
|
167
|
+
# 👇 changed here: no absolute server path; give a media-relative path + a URL
|
|
168
|
+
rel = _media_relpath_from_file_path(frame.file_path)
|
|
169
|
+
url = _media_url_from_file_path(frame.file_path, request=request)
|
|
170
|
+
|
|
171
|
+
frame_data = {
|
|
172
|
+
"frame_filename": Path(str(frame.file_path)).name,
|
|
173
|
+
"frame_file_path": rel, # backwards-compatible, now relative
|
|
174
|
+
"frame_url": url, # new: what the frontend should use
|
|
175
|
+
"all_classifications": all_classifications,
|
|
176
|
+
"predictions": predictions,
|
|
177
|
+
"frame_id": frame.id,
|
|
178
|
+
"manual_annotations": manual_annotations
|
|
179
|
+
}
|
|
180
|
+
time_segments["frames"].append(frame_data)
|
|
181
|
+
|
|
182
|
+
return time_segments
|
|
183
|
+
|
|
184
|
+
def get_label_name(self, obj):# -> Any | Literal['unknown']:
|
|
185
|
+
"""
|
|
186
|
+
Return the name of the label associated with the segment, or "unknown" if no label is set.
|
|
187
|
+
"""
|
|
188
|
+
if obj.label:
|
|
189
|
+
return obj.label.name
|
|
190
|
+
return "unknown"
|
|
191
|
+
|
|
192
|
+
def get_manual_frame_annotations(self, obj:LabelVideoSegment):
|
|
193
|
+
"""
|
|
194
|
+
Return serialized manual frame annotations for the given video segment.
|
|
195
|
+
|
|
196
|
+
Parameters:
|
|
197
|
+
obj (LabelVideoSegment): The video segment instance whose manual frame annotations are to be serialized.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
list: A list of serialized manual frame annotation data.
|
|
201
|
+
"""
|
|
202
|
+
return ImageClassificationAnnotationSerializer(obj.manual_frame_annotations, many=True).data
|
|
203
|
+
|
|
204
|
+
def get_frame_predictions(self, obj:LabelVideoSegment) -> List[dict]:
|
|
205
|
+
"""
|
|
206
|
+
Return serialized frame prediction annotations for the given video segment.
|
|
207
|
+
|
|
208
|
+
Parameters:
|
|
209
|
+
obj (LabelVideoSegment): The video segment instance whose frame predictions are to be serialized.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
List[dict]: A list of serialized frame prediction annotation data.
|
|
213
|
+
"""
|
|
214
|
+
return ImageClassificationAnnotationSerializer(obj.frame_predictions, many=True).data
|
|
215
|
+
|
|
216
|
+
def get_all_annotations(self, obj:LabelVideoSegment):
|
|
217
|
+
"""
|
|
218
|
+
Retrieve all image classification annotations for every frame in the given video segment.
|
|
219
|
+
|
|
220
|
+
Parameters:
|
|
221
|
+
obj (LabelVideoSegment): The video segment instance whose frame annotations are to be retrieved.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
list: A list of serialized image classification annotations for all frames in the segment.
|
|
225
|
+
"""
|
|
226
|
+
return ImageClassificationAnnotationSerializer(obj.all_frame_annotations, many=True).data
|
|
227
|
+
|
|
228
|
+
def get_label_display(self, obj:LabelVideoSegment):
|
|
229
|
+
"""
|
|
230
|
+
Return the German translation of the label name for display purposes.
|
|
231
|
+
|
|
232
|
+
If the segment has no label, returns "Unbekannt". If a translation is not available, returns the original label name.
|
|
233
|
+
"""
|
|
234
|
+
if not obj.label:
|
|
235
|
+
return "Unbekannt"
|
|
236
|
+
|
|
237
|
+
label_name = obj.label.name
|
|
238
|
+
#TODO Refactor
|
|
239
|
+
translations = {
|
|
240
|
+
'appendix': 'Appendix',
|
|
241
|
+
'blood': 'Blut',
|
|
242
|
+
'diverticule': 'Divertikel',
|
|
243
|
+
'grasper': 'Greifer',
|
|
244
|
+
'ileocaecalvalve': 'Ileozäkalklappe',
|
|
245
|
+
'ileum': 'Ileum',
|
|
246
|
+
'low_quality': 'Niedrige Bildqualität',
|
|
247
|
+
'nbi': 'Narrow Band Imaging',
|
|
248
|
+
'needle': 'Nadel',
|
|
249
|
+
'outside': 'Außerhalb',
|
|
250
|
+
'polyp': 'Polyp',
|
|
251
|
+
'snare': 'Snare',
|
|
252
|
+
'water_jet': 'Wasserstrahl',
|
|
253
|
+
'wound': 'Wunde'
|
|
254
|
+
}
|
|
255
|
+
return translations.get(label_name, label_name)
|
|
256
|
+
|
|
257
|
+
def get_video_name(self, obj):
|
|
258
|
+
"""
|
|
259
|
+
Return the display name of the video file associated with the segment.
|
|
260
|
+
|
|
261
|
+
If the video file has an `original_file_name`, it is returned; otherwise, a fallback name using the video ID is provided. Returns "Unknown Video" if the video file is inaccessible.
|
|
262
|
+
"""
|
|
263
|
+
try:
|
|
264
|
+
video = obj.video_file
|
|
265
|
+
return getattr(video, 'original_file_name', f'Video {video.id}')
|
|
266
|
+
except (AttributeError, ObjectDoesNotExist):
|
|
267
|
+
return 'Unknown Video'
|
|
268
|
+
|
|
269
|
+
def get_start_time(self, obj:LabelVideoSegment):
|
|
270
|
+
"""
|
|
271
|
+
Return the start time of the video segment in seconds.
|
|
272
|
+
"""
|
|
273
|
+
return obj.start_time
|
|
274
|
+
|
|
275
|
+
def get_end_time(self, obj):
|
|
276
|
+
"""
|
|
277
|
+
Return the end time of the video segment in seconds.
|
|
278
|
+
"""
|
|
279
|
+
return obj.end_time
|
|
280
|
+
|
|
281
|
+
def is_valid(self, raise_exception=False):
|
|
282
|
+
"""
|
|
283
|
+
Validates the serializer input data and logs the validation process.
|
|
284
|
+
|
|
285
|
+
Parameters:
|
|
286
|
+
raise_exception (bool): If True, raises a ValidationError on failure.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
bool: True if the data is valid, False otherwise.
|
|
290
|
+
"""
|
|
291
|
+
logger.debug("Starting validation")
|
|
292
|
+
result = super().is_valid(raise_exception=raise_exception)
|
|
293
|
+
if not result:
|
|
294
|
+
logger.debug(f"Validation errors: {self.errors}")
|
|
295
|
+
return result
|
|
296
|
+
|
|
297
|
+
def to_internal_value(self, data):
|
|
298
|
+
"""
|
|
299
|
+
Normalizes input data by mapping between `video_id`/`label_id` and `video_file`/`label` keys to ensure consistent internal representation for model creation and validation.
|
|
300
|
+
|
|
301
|
+
This allows the serializer to accept either set of keys and internally synchronize them before further processing.
|
|
302
|
+
"""
|
|
303
|
+
#TODO @coderabbitai create an issue for @Hamzaukw
|
|
304
|
+
# we need to ensure consistent naming across serializers
|
|
305
|
+
# Currently we use it in various places, but it should be consistent
|
|
306
|
+
# Either make the usage consistent or create another serializer that handles this
|
|
307
|
+
# Map video_file → video_id and label → label_id
|
|
308
|
+
if 'video_file' in data:
|
|
309
|
+
data['video_id'] = data['video_file']
|
|
310
|
+
if 'label' in data:
|
|
311
|
+
data['label_id'] = data['label']
|
|
312
|
+
# Map video_id → video_file and label_id → label
|
|
313
|
+
if 'video_id' in data:
|
|
314
|
+
data['video_file'] = data['video_id']
|
|
315
|
+
if 'label_id' in data:
|
|
316
|
+
data['label'] = data['label_id']
|
|
317
|
+
return super().to_internal_value(data)
|
|
318
|
+
|
|
319
|
+
def to_representation(self, instance):
|
|
320
|
+
"""
|
|
321
|
+
Return a JSON-compatible representation of a label video segment with calculated start and end times in seconds, label name, and explicit video and label IDs.
|
|
322
|
+
|
|
323
|
+
Raises:
|
|
324
|
+
ValueError: If the segment is not associated with a video file.
|
|
325
|
+
TypeError: If the associated video file is not a VideoFile instance.
|
|
326
|
+
"""
|
|
327
|
+
data = super().to_representation(instance)
|
|
328
|
+
video_file = instance.video_file
|
|
329
|
+
if video_file is None:
|
|
330
|
+
raise ValueError("Video file must be associated with the segment")
|
|
331
|
+
if not isinstance(video_file, VideoFile):
|
|
332
|
+
raise TypeError("Expected video_file to be an instance of VideoFile")
|
|
333
|
+
# Add calculated time fields for frontend compatibility
|
|
334
|
+
data['start_time'] = video_file.frame_number_to_s(instance.start_frame_number)
|
|
335
|
+
data['end_time'] = video_file.frame_number_to_s(instance.end_frame_number)
|
|
336
|
+
# Ensure label_name is always present in response
|
|
337
|
+
if instance.label:
|
|
338
|
+
data['label_name'] = instance.label.name
|
|
339
|
+
else:
|
|
340
|
+
data['label_name'] = None
|
|
341
|
+
# Explicitly add video_id and label_id to the output for frontend convenience
|
|
342
|
+
data['video_id'] = instance.video_file.id if instance.video_file else None
|
|
343
|
+
data['label_id'] = instance.label.id if instance.label else None
|
|
344
|
+
return data
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LabelVideoSegmentAnnotationSerializer(serializers.Serializer):
|
|
8
|
+
"""
|
|
9
|
+
Serializer for annotation data.
|
|
10
|
+
Handles segment annotations with metadata including segmentId.
|
|
11
|
+
"""
|
|
12
|
+
id = serializers.IntegerField(read_only=True)
|
|
13
|
+
videoId = serializers.IntegerField(required=True)
|
|
14
|
+
startTime = serializers.FloatField(required=False)
|
|
15
|
+
endTime = serializers.FloatField(required=False)
|
|
16
|
+
type = serializers.CharField(max_length=50, required=True)
|
|
17
|
+
text = serializers.CharField(max_length=1000, required=False, allow_blank=True)
|
|
18
|
+
tags = serializers.ListField(
|
|
19
|
+
child=serializers.CharField(max_length=100),
|
|
20
|
+
required=False,
|
|
21
|
+
default=list
|
|
22
|
+
)
|
|
23
|
+
userId = serializers.CharField(max_length=100, required=False)
|
|
24
|
+
isPublic = serializers.BooleanField(default=False)
|
|
25
|
+
confidence = serializers.FloatField(required=False, min_value=0.0, max_value=1.0)
|
|
26
|
+
metadata = serializers.DictField(required=False, default=dict)
|
|
27
|
+
|
|
28
|
+
def validate(self, data):
|
|
29
|
+
"""
|
|
30
|
+
Validates annotation data, enforcing required fields and value constraints for segment annotations.
|
|
31
|
+
|
|
32
|
+
For annotations of type 'segment', ensures both `startTime` and `endTime` are present and that `startTime` is less than `endTime`. If `metadata.segmentId` is provided, verifies it is a valid integer.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
serializers.ValidationError: If validation fails.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
dict: The validated annotation data.
|
|
39
|
+
"""
|
|
40
|
+
annotation_type = data.get('type')
|
|
41
|
+
|
|
42
|
+
if annotation_type == 'segment':
|
|
43
|
+
if 'startTime' not in data or 'endTime' not in data:
|
|
44
|
+
raise serializers.ValidationError(
|
|
45
|
+
"Segment annotations must include startTime and endTime"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
start_time = data.get('startTime')
|
|
49
|
+
end_time = data.get('endTime')
|
|
50
|
+
|
|
51
|
+
if start_time >= end_time:
|
|
52
|
+
raise serializers.ValidationError(
|
|
53
|
+
"startTime must be less than endTime"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Validate metadata contains segmentId if provided
|
|
57
|
+
metadata = data.get('metadata', {})
|
|
58
|
+
segment_id = metadata.get('segmentId')
|
|
59
|
+
if segment_id is not None:
|
|
60
|
+
try:
|
|
61
|
+
int(segment_id)
|
|
62
|
+
except (ValueError, TypeError):
|
|
63
|
+
raise serializers.ValidationError(
|
|
64
|
+
"metadata.segmentId must be a valid integer"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return data
|
|
68
|
+
|
|
69
|
+
#@maxhild we need to verify if this is the right place for these methods, if so we should implement them here
|
|
70
|
+
def create(self, validated_data):
|
|
71
|
+
"""
|
|
72
|
+
Assigns a unique ID to the annotation data and returns the updated data dictionary.
|
|
73
|
+
|
|
74
|
+
In this simulated implementation, the method mimics creating a new annotation by incrementing an internal counter for the ID. No data is persisted to a database or external storage.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
dict: The annotation data with an assigned unique ID.
|
|
78
|
+
"""
|
|
79
|
+
# Simulate creating an annotation with an ID
|
|
80
|
+
validated_data['id'] = getattr(self, '_next_id', 1)
|
|
81
|
+
self._next_id = validated_data['id'] + 1
|
|
82
|
+
return validated_data
|
|
83
|
+
|
|
84
|
+
def update(self, instance, validated_data):
|
|
85
|
+
"""
|
|
86
|
+
Update annotation data structure.
|
|
87
|
+
"""
|
|
88
|
+
for attr, value in validated_data.items():
|
|
89
|
+
instance[attr] = value
|
|
90
|
+
return instance
|
|
91
|
+
|
|
92
|
+
def save(self, **kwargs):
|
|
93
|
+
"""
|
|
94
|
+
Save the annotation.
|
|
95
|
+
"""
|
|
96
|
+
if self.instance:
|
|
97
|
+
return self.update(self.instance, self.validated_data)
|
|
98
|
+
else:
|
|
99
|
+
return self.create(self.validated_data)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from django.db import transaction
|
|
2
|
+
from rest_framework import serializers
|
|
3
|
+
|
|
4
|
+
from endoreg_db.models import LabelVideoSegment, VideoPredictionMeta
|
|
5
|
+
from endoreg_db.serializers.label_video_segment import LabelVideoSegmentSerializer
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
class LabelSegmentUpdateSerializer(serializers.Serializer):
|
|
11
|
+
"""
|
|
12
|
+
Serializer for updating label segments.
|
|
13
|
+
|
|
14
|
+
- Ensures that the segments stored in the database match exactly with what is sent from the frontend.
|
|
15
|
+
- Updates existing segments if their `start_frame_number` matches but `end_frame_number` has changed.
|
|
16
|
+
- Inserts new segments if they are not already present in the database.
|
|
17
|
+
- Deletes extra segments from the database if they are no longer in the frontend data.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
video_id = serializers.IntegerField()
|
|
21
|
+
label_id = serializers.IntegerField()
|
|
22
|
+
segments = serializers.ListField(
|
|
23
|
+
child=serializers.DictField(
|
|
24
|
+
child=serializers.FloatField() # Ensure we handle float values
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def validate(self, data):
|
|
29
|
+
"""
|
|
30
|
+
Validate that the input data contains a non-empty list of segments with valid frame numbers.
|
|
31
|
+
|
|
32
|
+
Raises a validation error if any segment is missing required fields or if a segment's start frame exceeds its end frame.
|
|
33
|
+
"""
|
|
34
|
+
if not data.get("segments"):
|
|
35
|
+
raise serializers.ValidationError("No segments provided.")
|
|
36
|
+
|
|
37
|
+
for segment in data["segments"]:
|
|
38
|
+
if "start_frame_number" not in segment or "end_frame_number" not in segment:
|
|
39
|
+
raise serializers.ValidationError(
|
|
40
|
+
"Each segment must have `start_frame_number` and `end_frame_number`."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if segment["start_frame_number"] > segment["end_frame_number"]:
|
|
44
|
+
raise serializers.ValidationError(
|
|
45
|
+
"Start frame must be less than or equal to end frame."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return data
|
|
49
|
+
|
|
50
|
+
def save(self):
|
|
51
|
+
"""
|
|
52
|
+
Synchronizes label segments in the database to match the provided frontend data for a specific video and label.
|
|
53
|
+
|
|
54
|
+
Compares incoming segments to existing database entries, updating segments with changed end frames, creating new segments as needed, and deleting segments that are no longer present. All changes are performed within a transaction to ensure consistency. Raises a validation error if no prediction metadata exists for the specified video.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict: A dictionary containing serialized updated segments, newly created segments, and the count of deleted segments.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
video_id = self.validated_data["video_id"]
|
|
61
|
+
label_id = self.validated_data["label_id"]
|
|
62
|
+
new_segments = self.validated_data["segments"] # Remove new_keys assignment
|
|
63
|
+
|
|
64
|
+
# Fetch the correct `prediction_meta_id` based on `video_id`
|
|
65
|
+
prediction_meta_entry = VideoPredictionMeta.objects.filter(
|
|
66
|
+
video_file_id=video_id # Changed from video_id to video_file_id
|
|
67
|
+
).first()
|
|
68
|
+
if not prediction_meta_entry:
|
|
69
|
+
raise serializers.ValidationError(
|
|
70
|
+
{"error": "No prediction metadata found for this video."}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
prediction_meta_id = (
|
|
74
|
+
prediction_meta_entry.id
|
|
75
|
+
) # Get the correct prediction_meta_id
|
|
76
|
+
|
|
77
|
+
existing_segments = LabelVideoSegment.objects.filter(
|
|
78
|
+
video_file_id=video_id, label_id=label_id # FIXED: video_file_id instead of video_id
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Convert existing segments into a dictionary for quick lookup
|
|
82
|
+
# Key format: (start_frame_number, end_frame_number)
|
|
83
|
+
existing_segments_dict = {
|
|
84
|
+
(float(seg.start_frame_number), float(seg.end_frame_number)): seg
|
|
85
|
+
for seg in existing_segments
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Prepare lists for batch processing
|
|
89
|
+
# Initialize sets to track updates and new entries
|
|
90
|
+
updated_segments = set()
|
|
91
|
+
new_entries = []
|
|
92
|
+
existing_keys = set()
|
|
93
|
+
new_keys = set()
|
|
94
|
+
|
|
95
|
+
# Iterate through the validated data to update or create label video segments
|
|
96
|
+
print(f" Before Update: Found {existing_segments.count()} existing segments.")
|
|
97
|
+
logger.debug(f"Before Update: Found %d existing segments.", existing_segments.count())
|
|
98
|
+
logger.debug(f"New Segments Received: %d", len(new_segments))
|
|
99
|
+
logger.debug(f"Using prediction_meta_id: %d", prediction_meta_id)
|
|
100
|
+
with transaction.atomic():
|
|
101
|
+
for segment in new_segments:
|
|
102
|
+
start_frame = float(segment["start_frame_number"])
|
|
103
|
+
end_frame = float(segment["end_frame_number"])
|
|
104
|
+
|
|
105
|
+
if (start_frame, end_frame) in existing_keys:
|
|
106
|
+
# If segment with exact start_frame and end_frame already exists, no change is needed
|
|
107
|
+
continue
|
|
108
|
+
else:
|
|
109
|
+
# Check if a segment exists with the same start_frame but different end_frame
|
|
110
|
+
existing_segment = LabelVideoSegment.objects.filter(
|
|
111
|
+
video_file_id=video_id, # Changed from video_id to video_file_id
|
|
112
|
+
label_id=label_id,
|
|
113
|
+
start_frame_number=start_frame,
|
|
114
|
+
).first()
|
|
115
|
+
|
|
116
|
+
if existing_segment:
|
|
117
|
+
# If a segment with the same_start_frame exists but the end_frame is different, update it
|
|
118
|
+
if float(existing_segment.end_frame_number) != end_frame:
|
|
119
|
+
existing_segment.end_frame_number = end_frame
|
|
120
|
+
existing_segment.save()
|
|
121
|
+
updated_segments.append(existing_segment)
|
|
122
|
+
else: # Added else block to create new segment if not existing
|
|
123
|
+
new_entries.append(
|
|
124
|
+
LabelVideoSegment(
|
|
125
|
+
video_file_id=video_id, # Changed from video_id to video_file_id
|
|
126
|
+
label_id=label_id,
|
|
127
|
+
start_frame_number=start_frame,
|
|
128
|
+
end_frame_number=end_frame,
|
|
129
|
+
prediction_meta_id=prediction_meta_id,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
print(
|
|
133
|
+
f" Adding new segment: Start {start_frame} → End {end_frame}"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Delete segments that are no longer present in the frontend data
|
|
137
|
+
# Segments to delete are those in existing_keys but not in new_keys
|
|
138
|
+
keys_to_delete = existing_keys - set((float(s['start_frame_number']), float(s['end_frame_number'])) for s in new_segments)
|
|
139
|
+
segments_to_delete_ids = [existing_segments_dict[key].id for key in keys_to_delete]
|
|
140
|
+
|
|
141
|
+
if segments_to_delete_ids:
|
|
142
|
+
LabelVideoSegment.objects.filter(id__in=segments_to_delete_ids).delete()
|
|
143
|
+
deleted_count = len(segments_to_delete_ids)
|
|
144
|
+
else:
|
|
145
|
+
deleted_count = 0
|
|
146
|
+
|
|
147
|
+
# Insert new segments in bulk for efficiency
|
|
148
|
+
if new_entries:
|
|
149
|
+
LabelVideoSegment.objects.bulk_create(new_entries)
|
|
150
|
+
|
|
151
|
+
logger.debug(
|
|
152
|
+
"After Update: Updated %d segments, Added %d, Deleted %d",
|
|
153
|
+
len(updated_segments), len(new_entries), deleted_count
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
"updated_segments": LabelVideoSegmentSerializer(
|
|
159
|
+
updated_segments, many=True
|
|
160
|
+
).data,
|
|
161
|
+
"new_segments": LabelVideoSegmentSerializer(new_entries, many=True).data,
|
|
162
|
+
"deleted_segments": deleted_count,
|
|
163
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .pdf_file_meta_extraction import PDFFileForMetaSerializer
|
|
2
|
+
from .report_meta import (
|
|
3
|
+
ReportMetaSerializer,
|
|
4
|
+
)
|
|
5
|
+
from .sensitive_meta_detail import SensitiveMetaDetailSerializer
|
|
6
|
+
from .sensitive_meta_update import SensitiveMetaUpdateSerializer
|
|
7
|
+
from .sensitive_meta_verification import SensitiveMetaVerificationSerializer
|
|
8
|
+
from .video_meta import (
|
|
9
|
+
VideoMetaSerializer,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"PDFFileForMetaSerializer",
|
|
14
|
+
"ReportMetaSerializer",
|
|
15
|
+
"SensitiveMetaDetailSerializer",
|
|
16
|
+
"SensitiveMetaUpdateSerializer",
|
|
17
|
+
"SensitiveMetaVerificationSerializer",
|
|
18
|
+
"VideoMetaSerializer",
|
|
19
|
+
]
|