endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/authz/auth.py +74 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +18 -0
- endoreg_db/authz/middleware.py +83 -0
- endoreg_db/authz/permissions.py +127 -0
- endoreg_db/authz/policy.py +218 -0
- endoreg_db/authz/views_auth.py +66 -0
- endoreg_db/config/env.py +13 -8
- endoreg_db/data/__init__.py +2 -11
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/examination/examinations/data.yaml +114 -14
- endoreg_db/data/examination/time-type/data.yaml +0 -3
- endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
- endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
- endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
- endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_type/data.yaml +8 -12
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set_type/data.yaml +21 -0
- endoreg_db/data/setup_config.yaml +4 -4
- endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
- endoreg_db/exceptions.py +4 -2
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +125 -53
- endoreg_db/helpers/default_objects.py +116 -81
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +43 -0
- endoreg_db/import_files/context/validate_directories.py +56 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +76 -0
- endoreg_db/import_files/file_storage/create_video_file.py +75 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
- endoreg_db/import_files/file_storage/state_management.py +400 -0
- endoreg_db/import_files/file_storage/storage.py +36 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
- endoreg_db/import_files/report_import_service.py +141 -0
- endoreg_db/import_files/video_import_service.py +150 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
- endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
- endoreg_db/management/commands/import_report.py +130 -65
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +2 -2
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_ai_model_data.py +5 -5
- endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
- endoreg_db/management/commands/load_base_db_data.py +5 -134
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_contraindication_data.py +14 -16
- endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
- endoreg_db/management/commands/load_disease_classification_data.py +15 -18
- endoreg_db/management/commands/load_disease_data.py +25 -28
- endoreg_db/management/commands/load_endoscope_data.py +20 -27
- endoreg_db/management/commands/load_event_data.py +14 -16
- endoreg_db/management/commands/load_examination_data.py +31 -44
- endoreg_db/management/commands/load_examination_indication_data.py +20 -21
- endoreg_db/management/commands/load_finding_data.py +52 -80
- endoreg_db/management/commands/load_information_source.py +21 -23
- endoreg_db/management/commands/load_lab_value_data.py +17 -26
- endoreg_db/management/commands/load_medication_data.py +13 -12
- endoreg_db/management/commands/load_organ_data.py +15 -19
- endoreg_db/management/commands/load_pdf_type_data.py +19 -18
- endoreg_db/management/commands/load_profession_data.py +14 -17
- endoreg_db/management/commands/load_qualification_data.py +20 -23
- endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
- endoreg_db/management/commands/load_requirement_data.py +62 -39
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/load_risk_data.py +7 -6
- endoreg_db/management/commands/load_shift_data.py +20 -23
- endoreg_db/management/commands/load_tag_data.py +8 -11
- endoreg_db/management/commands/load_unit_data.py +17 -19
- endoreg_db/management/commands/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +297 -250
- endoreg_db/models/__init__.py +78 -123
- endoreg_db/models/administration/__init__.py +21 -42
- endoreg_db/models/administration/ai/active_model.py +2 -2
- endoreg_db/models/administration/ai/ai_model.py +7 -6
- endoreg_db/models/administration/case/__init__.py +1 -15
- endoreg_db/models/administration/case/case.py +3 -3
- endoreg_db/models/administration/case/case_template/__init__.py +2 -14
- endoreg_db/models/administration/case/case_template/case_template.py +2 -124
- endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
- endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
- endoreg_db/models/administration/center/center.py +33 -19
- endoreg_db/models/administration/center/center_product.py +12 -9
- endoreg_db/models/administration/center/center_resource.py +25 -19
- endoreg_db/models/administration/center/center_shift.py +21 -17
- endoreg_db/models/administration/center/center_waste.py +16 -8
- endoreg_db/models/administration/person/__init__.py +2 -0
- endoreg_db/models/administration/person/employee/employee.py +10 -5
- endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
- endoreg_db/models/administration/person/employee/employee_type.py +12 -6
- endoreg_db/models/administration/person/examiner/examiner.py +13 -11
- endoreg_db/models/administration/person/patient/__init__.py +2 -0
- endoreg_db/models/administration/person/patient/patient.py +129 -100
- endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
- endoreg_db/models/administration/person/person.py +4 -0
- endoreg_db/models/administration/person/profession/__init__.py +8 -4
- endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
- endoreg_db/models/administration/product/product.py +20 -15
- endoreg_db/models/administration/product/product_material.py +17 -18
- endoreg_db/models/administration/product/product_weight.py +12 -8
- endoreg_db/models/administration/product/reference_product.py +23 -55
- endoreg_db/models/administration/qualification/qualification.py +7 -3
- endoreg_db/models/administration/qualification/qualification_type.py +7 -3
- endoreg_db/models/administration/shift/scheduled_days.py +8 -5
- endoreg_db/models/administration/shift/shift.py +16 -12
- endoreg_db/models/administration/shift/shift_type.py +23 -31
- endoreg_db/models/label/__init__.py +8 -9
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
- endoreg_db/models/label/label.py +15 -15
- endoreg_db/models/label/label_set.py +19 -6
- endoreg_db/models/label/label_type.py +1 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
- endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
- endoreg_db/models/label/video_segmentation_label.py +4 -0
- endoreg_db/models/label/video_segmentation_labelset.py +4 -3
- endoreg_db/models/media/frame/frame.py +22 -22
- endoreg_db/models/media/pdf/raw_pdf.py +194 -194
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/processing_history/__init__.py +5 -0
- endoreg_db/models/media/processing_history/processing_history.py +96 -0
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +139 -77
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +174 -112
- endoreg_db/models/media/video/video_file_ai.py +288 -74
- endoreg_db/models/media/video/video_file_anonymize.py +38 -38
- endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
- endoreg_db/models/media/video/video_file_io.py +113 -61
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
- endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
- endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
- endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
- endoreg_db/models/media/video/video_file_segments.py +24 -17
- endoreg_db/models/media/video/video_metadata.py +19 -35
- endoreg_db/models/media/video/video_processing.py +96 -95
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/contraindication/__init__.py +13 -3
- endoreg_db/models/medical/disease.py +22 -16
- endoreg_db/models/medical/event.py +31 -18
- endoreg_db/models/medical/examination/__init__.py +13 -6
- endoreg_db/models/medical/examination/examination.py +39 -20
- endoreg_db/models/medical/examination/examination_indication.py +30 -95
- endoreg_db/models/medical/examination/examination_time.py +23 -8
- endoreg_db/models/medical/examination/examination_time_type.py +9 -6
- endoreg_db/models/medical/examination/examination_type.py +3 -4
- endoreg_db/models/medical/finding/finding.py +32 -40
- endoreg_db/models/medical/finding/finding_classification.py +42 -72
- endoreg_db/models/medical/finding/finding_intervention.py +25 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +26 -26
- endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
- endoreg_db/models/medical/laboratory/lab_value.py +62 -91
- endoreg_db/models/medical/medication/medication.py +22 -10
- endoreg_db/models/medical/medication/medication_indication.py +29 -3
- endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
- endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
- endoreg_db/models/medical/medication/medication_schedule.py +27 -16
- endoreg_db/models/medical/organ/__init__.py +15 -12
- endoreg_db/models/medical/patient/medication_examples.py +6 -6
- endoreg_db/models/medical/patient/patient_disease.py +20 -23
- endoreg_db/models/medical/patient/patient_event.py +19 -22
- endoreg_db/models/medical/patient/patient_examination.py +48 -54
- endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
- endoreg_db/models/medical/patient/patient_finding.py +122 -139
- endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
- endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
- endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
- endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
- endoreg_db/models/medical/patient/patient_medication.py +27 -38
- endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
- endoreg_db/models/medical/risk/risk.py +7 -6
- endoreg_db/models/medical/risk/risk_type.py +8 -5
- endoreg_db/models/metadata/model_meta.py +60 -29
- endoreg_db/models/metadata/model_meta_logic.py +125 -18
- endoreg_db/models/metadata/pdf_meta.py +31 -24
- endoreg_db/models/metadata/sensitive_meta.py +105 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
- endoreg_db/models/metadata/video_meta.py +51 -31
- endoreg_db/models/metadata/video_prediction_logic.py +16 -23
- endoreg_db/models/metadata/video_prediction_meta.py +29 -33
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
- endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
- endoreg_db/models/other/emission/emission_factor.py +18 -8
- endoreg_db/models/other/gender.py +10 -5
- endoreg_db/models/other/information_source.py +50 -29
- endoreg_db/models/other/material.py +9 -5
- endoreg_db/models/other/resource.py +6 -4
- endoreg_db/models/other/tag.py +10 -5
- endoreg_db/models/other/transport_route.py +13 -8
- endoreg_db/models/other/unit.py +10 -6
- endoreg_db/models/other/waste.py +6 -5
- endoreg_db/models/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +329 -361
- endoreg_db/models/requirement/requirement_error.py +85 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
- endoreg_db/models/requirement/requirement_operator.py +103 -112
- endoreg_db/models/requirement/requirement_set.py +74 -57
- endoreg_db/models/state/__init__.py +4 -4
- endoreg_db/models/state/abstract.py +2 -2
- endoreg_db/models/state/anonymization.py +12 -0
- endoreg_db/models/state/audit_ledger.py +49 -51
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +101 -68
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +110 -90
- endoreg_db/models/upload_job.py +35 -34
- endoreg_db/models/utils.py +28 -25
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/root_urls.py +21 -2
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -10
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
- endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
- endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +128 -89
- endoreg_db/services/lookup_service.py +65 -52
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1382
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1255
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +5 -32
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +121 -83
- endoreg_db/urls/root_urls.py +29 -0
- endoreg_db/utils/__init__.py +15 -5
- endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/dataloader.py +142 -40
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- endoreg_db/utils/setup_config.py +8 -5
- endoreg_db/utils/storage.py +115 -0
- endoreg_db/utils/validate_endo_roi.py +8 -2
- endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
- endoreg_db/views/__init__.py +85 -183
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +202 -166
- endoreg_db/views/anonymization/overview.py +99 -67
- endoreg_db/views/anonymization/validate.py +182 -44
- endoreg_db/views/media/__init__.py +7 -20
- endoreg_db/views/media/pdf_media.py +197 -174
- endoreg_db/views/media/sensitive_metadata.py +193 -138
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/meta/__init__.py +0 -8
- endoreg_db/views/misc/__init__.py +1 -7
- endoreg_db/views/misc/upload_views.py +94 -93
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/report/__init__.py +5 -7
- endoreg_db/views/{pdf → report}/reimport.py +22 -22
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +23 -24
- endoreg_db/views/video/correction.py +201 -172
- endoreg_db/views/video/reimport.py +1 -1
- endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
- endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
- endoreg_db/views/video/video_stream.py +7 -8
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
- endoreg_db/data/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/finding/complication.yaml +0 -16
- endoreg_db/data/finding/data.yaml +0 -105
- endoreg_db/data/finding/examination_setting.yaml +0 -16
- endoreg_db/data/finding/medication_related.yaml +0 -18
- endoreg_db/data/finding/outcome.yaml +0 -12
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
- endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
- endoreg_db/data/requirement/age.yaml +0 -26
- endoreg_db/data/requirement/gender.yaml +0 -25
- endoreg_db/management/commands/init_default_ai_model.py +0 -112
- endoreg_db/management/commands/reset_celery_schedule.py +0 -9
- endoreg_db/management/commands/validate_video.py +0 -204
- endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
- endoreg_db/migrations/0003_add_center_display_name.py +0 -30
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- endoreg_db/models/rule/__init__.py +0 -13
- endoreg_db/models/rule/rule.py +0 -27
- endoreg_db/models/rule/rule_applicator.py +0 -224
- endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
- endoreg_db/models/rule/rule_type.py +0 -20
- endoreg_db/models/rule/ruleset.py +0 -17
- endoreg_db/renames.yml +0 -8
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
- endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
- endoreg_db/serializers/_old/video.py +0 -71
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
- endoreg_db/serializers/meta/report_meta.py +0 -53
- endoreg_db/serializers/report/__init__.py +0 -9
- endoreg_db/serializers/report/mixins.py +0 -45
- endoreg_db/serializers/report/report.py +0 -105
- endoreg_db/serializers/report/report_list.py +0 -22
- endoreg_db/serializers/report/secure_file_url.py +0 -26
- endoreg_db/serializers/video/video_metadata.py +0 -105
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -344
- endoreg_db/urls/files.py +0 -6
- endoreg_db/urls/label_video_segment_validate.py +0 -33
- endoreg_db/urls/label_video_segments.py +0 -46
- endoreg_db/urls/report.py +0 -48
- endoreg_db/urls/video.py +0 -61
- endoreg_db/utils/case_generator/case_generator.py +0 -159
- endoreg_db/utils/case_generator/utils.py +0 -30
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
- endoreg_db/views/label/__init__.py +0 -5
- endoreg_db/views/label/label.py +0 -15
- endoreg_db/views/label_video_segment/__init__.py +0 -16
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
- endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
- endoreg_db/views/label_video_segment/validate.py +0 -226
- endoreg_db/views/media/segments.py +0 -71
- endoreg_db/views/meta/available_files_list.py +0 -146
- endoreg_db/views/meta/report_meta.py +0 -53
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
- endoreg_db/views/misc/secure_file_serving_view.py +0 -80
- endoreg_db/views/misc/secure_file_url_view.py +0 -84
- endoreg_db/views/misc/secure_url_validate.py +0 -79
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
- endoreg_db/views/patient_finding_location/__init__.py +0 -5
- endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
- endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
- endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
- endoreg_db/views/pdf/__init__.py +0 -8
- endoreg_db/views/report/report_list.py +0 -112
- endoreg_db/views/report/report_with_secure_url.py +0 -28
- endoreg_db/views/report/start_examination.py +0 -7
- endoreg_db/views/video/segmentation.py +0 -274
- endoreg_db/views/video/task_status.py +0 -49
- endoreg_db/views/video/timeline.py +0 -46
- endoreg_db/views/video/video_analyze.py +0 -52
- endoreg_db/views.py +0 -0
- /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
- /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
- /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
- /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
- /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
- /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
- /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
- /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
- /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import TYPE_CHECKING, List,
|
|
2
|
+
from typing import TYPE_CHECKING, List, Optional, Tuple
|
|
3
|
+
|
|
3
4
|
import numpy as np
|
|
4
5
|
|
|
5
|
-
# Import necessary models and utils used by the logic
|
|
6
|
-
from ..utils import find_segments_in_prediction_array
|
|
7
6
|
from ..label.label_video_segment import LabelVideoSegment
|
|
8
7
|
|
|
8
|
+
# Import necessary models and utils used by the logic
|
|
9
|
+
from ..utils import find_segments_in_prediction_array
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
13
|
+
# TODO configure via settings
|
|
12
14
|
DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
|
|
13
15
|
DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
|
|
14
16
|
|
|
15
17
|
if TYPE_CHECKING:
|
|
16
|
-
from .video_prediction_meta import VideoPredictionMeta
|
|
17
18
|
from ..label import Label
|
|
19
|
+
from .video_prediction_meta import VideoPredictionMeta
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
def apply_running_mean_logic(instance: "VideoPredictionMeta", confidence_array: np.ndarray, window_size_in_seconds: Optional[float] = None) -> np.ndarray:
|
|
@@ -63,6 +65,7 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
|
|
|
63
65
|
Does not save the array itself.
|
|
64
66
|
"""
|
|
65
67
|
from ..label import ImageClassificationAnnotation
|
|
68
|
+
|
|
66
69
|
video_obj = instance.get_video()
|
|
67
70
|
model_meta = instance.model_meta
|
|
68
71
|
label_list = instance.get_label_list()
|
|
@@ -78,15 +81,10 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
|
|
|
78
81
|
|
|
79
82
|
prediction_array = np.zeros((num_frames, len(label_list)))
|
|
80
83
|
|
|
81
|
-
base_pred_qs = ImageClassificationAnnotation.objects.filter(
|
|
82
|
-
model_meta=model_meta,
|
|
83
|
-
frame__video_file=video_obj
|
|
84
|
-
)
|
|
84
|
+
base_pred_qs = ImageClassificationAnnotation.objects.filter(model_meta=model_meta, frame__video_file=video_obj)
|
|
85
85
|
|
|
86
86
|
for i, label in enumerate(label_list):
|
|
87
|
-
predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list(
|
|
88
|
-
"frame__frame_number", "confidence"
|
|
89
|
-
)
|
|
87
|
+
predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list("frame__frame_number", "confidence")
|
|
90
88
|
|
|
91
89
|
# Initialize with 0.5 (neutral confidence)
|
|
92
90
|
confidences = np.full(num_frames, 0.5)
|
|
@@ -96,14 +94,12 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
|
|
|
96
94
|
confidences[frame_num] = confidence
|
|
97
95
|
found_predictions = True
|
|
98
96
|
else:
|
|
99
|
-
logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames-1}). Skipping.")
|
|
97
|
+
logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames - 1}). Skipping.")
|
|
100
98
|
|
|
101
99
|
if not found_predictions:
|
|
102
100
|
logger.warning(f"No predictions found for label '{label.name}' in {video_obj}. Using default confidence.")
|
|
103
101
|
|
|
104
|
-
smooth_confidences = apply_running_mean_logic(
|
|
105
|
-
instance, confidences, window_size_in_seconds
|
|
106
|
-
)
|
|
102
|
+
smooth_confidences = apply_running_mean_logic(instance, confidences, window_size_in_seconds)
|
|
107
103
|
# Threshold smoothed confidences
|
|
108
104
|
binary_predictions = smooth_confidences > 0.5
|
|
109
105
|
prediction_array[:, i] = binary_predictions
|
|
@@ -116,6 +112,7 @@ def create_video_segments_for_label_logic(instance: "VideoPredictionMeta", segme
|
|
|
116
112
|
Creates LabelVideoSegment instances for the given label and segments.
|
|
117
113
|
"""
|
|
118
114
|
from ..other import InformationSource
|
|
115
|
+
|
|
119
116
|
video_obj = instance.get_video()
|
|
120
117
|
information_source, _ = InformationSource.objects.get_or_create(name="prediction")
|
|
121
118
|
|
|
@@ -131,11 +128,7 @@ def create_video_segments_for_label_logic(instance: "VideoPredictionMeta", segme
|
|
|
131
128
|
}
|
|
132
129
|
# Check for existence before creating the object instance
|
|
133
130
|
if not LabelVideoSegment.objects.filter(
|
|
134
|
-
video_file=video_obj,
|
|
135
|
-
prediction_meta=instance,
|
|
136
|
-
label=label,
|
|
137
|
-
start_frame_number=start_frame,
|
|
138
|
-
end_frame_number=end_frame
|
|
131
|
+
video_file=video_obj, prediction_meta=instance, label=label, start_frame_number=start_frame, end_frame_number=end_frame
|
|
139
132
|
).exists():
|
|
140
133
|
segments_to_create.append(LabelVideoSegment(**segment_data))
|
|
141
134
|
|
|
@@ -161,7 +154,7 @@ def create_video_segments_logic(instance: "VideoPredictionMeta", segment_length_
|
|
|
161
154
|
return
|
|
162
155
|
|
|
163
156
|
min_frame_length = int(segment_length_threshold_in_s * fps)
|
|
164
|
-
min_frame_length = max(min_frame_length, 1)
|
|
157
|
+
min_frame_length = max(min_frame_length, 1) # Ensure minimum length is at least 1
|
|
165
158
|
|
|
166
159
|
label_list = instance.get_label_list()
|
|
167
160
|
if not label_list:
|
|
@@ -171,8 +164,8 @@ def create_video_segments_logic(instance: "VideoPredictionMeta", segment_length_
|
|
|
171
164
|
prediction_array = instance.get_prediction_array()
|
|
172
165
|
if prediction_array is None:
|
|
173
166
|
logger.info(f"Prediction array not found for {instance}. Calculating...")
|
|
174
|
-
instance.calculate_prediction_array()
|
|
175
|
-
prediction_array = instance.get_prediction_array()
|
|
167
|
+
instance.calculate_prediction_array() # This will save the array internally
|
|
168
|
+
prediction_array = instance.get_prediction_array() # Fetch again
|
|
176
169
|
if prediction_array is None:
|
|
177
170
|
logger.error(f"Failed to get or calculate prediction array for {instance}. Cannot create segments.")
|
|
178
171
|
return
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Optional, List, Tuple
|
|
2
|
-
from django.db import models
|
|
3
1
|
import logging
|
|
2
|
+
import pickle
|
|
3
|
+
from typing import TYPE_CHECKING, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from django.db import models
|
|
4
7
|
|
|
5
8
|
from endoreg_db.models.label import LabelSet
|
|
6
9
|
|
|
7
10
|
from ..label.label_video_segment import (
|
|
8
11
|
LabelVideoSegment,
|
|
9
|
-
|
|
10
12
|
)
|
|
11
13
|
from ..utils import find_segments_in_prediction_array
|
|
12
14
|
|
|
13
|
-
import numpy as np
|
|
14
|
-
import pickle
|
|
15
|
-
|
|
16
15
|
logger = logging.getLogger(__name__)
|
|
17
16
|
|
|
18
17
|
DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
|
|
19
18
|
DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
|
|
20
19
|
|
|
21
20
|
if TYPE_CHECKING:
|
|
22
|
-
from endoreg_db.models import
|
|
21
|
+
from endoreg_db.models import Label, ModelMeta
|
|
22
|
+
|
|
23
23
|
from ..media.video.video_file import VideoFile
|
|
24
24
|
|
|
25
25
|
|
|
@@ -29,6 +29,7 @@ class VideoPredictionMeta(models.Model):
|
|
|
29
29
|
|
|
30
30
|
Must be associated with exactly one `VideoFile`.
|
|
31
31
|
"""
|
|
32
|
+
|
|
32
33
|
model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
|
|
33
34
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
34
35
|
date_modified = models.DateTimeField(auto_now=True)
|
|
@@ -43,18 +44,24 @@ class VideoPredictionMeta(models.Model):
|
|
|
43
44
|
)
|
|
44
45
|
|
|
45
46
|
if TYPE_CHECKING:
|
|
46
|
-
model_meta: "ModelMeta"
|
|
47
|
-
video_file: "VideoFile"
|
|
47
|
+
model_meta: models.ForeignKey["ModelMeta"]
|
|
48
|
+
video_file: models.ForeignKey["VideoFile|None"]
|
|
48
49
|
label_video_segments: "models.Manager[LabelVideoSegment]"
|
|
49
50
|
|
|
50
51
|
class Meta:
|
|
51
|
-
constraints = [
|
|
52
|
-
models.UniqueConstraint(fields=['model_meta', 'video_file'], name='unique_prediction_per_video_model')
|
|
53
|
-
]
|
|
52
|
+
constraints = [models.UniqueConstraint(fields=["model_meta", "video_file"], name="unique_prediction_per_video_model")]
|
|
54
53
|
indexes = [
|
|
55
54
|
models.Index(fields=["model_meta", "video_file"]),
|
|
56
55
|
]
|
|
57
56
|
|
|
57
|
+
@property
|
|
58
|
+
def video_file_safe(self) -> "VideoFile":
|
|
59
|
+
"""Returns the associated VideoFile instance."""
|
|
60
|
+
video_file = self.video_file
|
|
61
|
+
if not video_file:
|
|
62
|
+
raise ValueError("VideoPredictionMeta is not associated with a VideoFile.")
|
|
63
|
+
return video_file
|
|
64
|
+
|
|
58
65
|
def get_video(self) -> "VideoFile":
|
|
59
66
|
"""Returns the associated VideoFile instance."""
|
|
60
67
|
if self.video_file:
|
|
@@ -83,12 +90,12 @@ class VideoPredictionMeta(models.Model):
|
|
|
83
90
|
return labelset.get_labels_in_order()
|
|
84
91
|
return []
|
|
85
92
|
|
|
86
|
-
def save_prediction_array(self, prediction_array: np.
|
|
93
|
+
def save_prediction_array(self, prediction_array: np.typing.NDArray):
|
|
87
94
|
"""
|
|
88
95
|
Save the prediction array to the database.
|
|
89
96
|
"""
|
|
90
97
|
self.prediction_array = pickle.dumps(prediction_array)
|
|
91
|
-
self.save(update_fields=[
|
|
98
|
+
self.save(update_fields=["prediction_array", "date_modified"])
|
|
92
99
|
|
|
93
100
|
def get_prediction_array(self):
|
|
94
101
|
"""
|
|
@@ -103,7 +110,7 @@ class VideoPredictionMeta(models.Model):
|
|
|
103
110
|
logger.error(f"Error unpickling prediction array for {self}: {e}")
|
|
104
111
|
return None
|
|
105
112
|
|
|
106
|
-
def calculate_prediction_array(self, window_size_in_seconds: int = None):
|
|
113
|
+
def calculate_prediction_array(self, window_size_in_seconds: Optional[int] = None):
|
|
107
114
|
"""
|
|
108
115
|
Fetches all predictions for the associated video, labelset, and model meta,
|
|
109
116
|
applies smoothing, and saves the resulting binary prediction array.
|
|
@@ -125,15 +132,10 @@ class VideoPredictionMeta(models.Model):
|
|
|
125
132
|
|
|
126
133
|
prediction_array = np.zeros((num_frames, len(label_list)))
|
|
127
134
|
|
|
128
|
-
base_pred_qs = ImageClassificationAnnotation.objects.filter(
|
|
129
|
-
model_meta=model_meta,
|
|
130
|
-
frame__video_file=video_obj
|
|
131
|
-
)
|
|
135
|
+
base_pred_qs = ImageClassificationAnnotation.objects.filter(model_meta=model_meta, frame__video_file=video_obj)
|
|
132
136
|
|
|
133
137
|
for i, label in enumerate(label_list):
|
|
134
|
-
predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list(
|
|
135
|
-
"frame__frame_number", "float_value"
|
|
136
|
-
)
|
|
138
|
+
predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list("frame__frame_number", "float_value")
|
|
137
139
|
|
|
138
140
|
confidences = np.full(num_frames, 0.5)
|
|
139
141
|
found_predictions = False
|
|
@@ -142,21 +144,19 @@ class VideoPredictionMeta(models.Model):
|
|
|
142
144
|
confidences[frame_num] = confidence
|
|
143
145
|
found_predictions = True
|
|
144
146
|
else:
|
|
145
|
-
logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames-1}). Skipping.")
|
|
147
|
+
logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames - 1}). Skipping.")
|
|
146
148
|
|
|
147
149
|
if not found_predictions:
|
|
148
150
|
logger.warning(f"No predictions found for label '{label.name}' in {video_obj}. Using default confidence.")
|
|
149
151
|
|
|
150
|
-
smooth_confidences = self.apply_running_mean(
|
|
151
|
-
confidences, window_size_in_seconds
|
|
152
|
-
)
|
|
152
|
+
smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
|
|
153
153
|
binary_predictions = smooth_confidences > 0.5
|
|
154
154
|
prediction_array[:, i] = binary_predictions
|
|
155
155
|
|
|
156
156
|
self.save_prediction_array(prediction_array)
|
|
157
157
|
logger.info(f"Calculated and saved prediction array for {self}")
|
|
158
158
|
|
|
159
|
-
def apply_running_mean(self, confidence_array, window_size_in_seconds:
|
|
159
|
+
def apply_running_mean(self, confidence_array, window_size_in_seconds: Optional[float] = None):
|
|
160
160
|
"""
|
|
161
161
|
Apply a running mean filter to the confidence array for smoothing, assuming a padding
|
|
162
162
|
of 0.5 for the edges.
|
|
@@ -215,11 +215,7 @@ class VideoPredictionMeta(models.Model):
|
|
|
215
215
|
"video_file": video_obj,
|
|
216
216
|
}
|
|
217
217
|
if not LabelVideoSegment.objects.filter(
|
|
218
|
-
video_file=video_obj,
|
|
219
|
-
prediction_meta=self,
|
|
220
|
-
label=label,
|
|
221
|
-
start_frame_number=start_frame,
|
|
222
|
-
end_frame_number=end_frame
|
|
218
|
+
video_file=video_obj, prediction_meta=self, label=label, start_frame_number=start_frame, end_frame_number=end_frame
|
|
223
219
|
).exists():
|
|
224
220
|
segments_to_create.append(LabelVideoSegment(**segment_data))
|
|
225
221
|
|
|
@@ -229,7 +225,7 @@ class VideoPredictionMeta(models.Model):
|
|
|
229
225
|
else:
|
|
230
226
|
logger.info(f"No new video segments needed for label '{label.name}' in {video_obj}.")
|
|
231
227
|
|
|
232
|
-
def create_video_segments(self, segment_length_threshold_in_s: float = None):
|
|
228
|
+
def create_video_segments(self, segment_length_threshold_in_s: Optional[float] = None):
|
|
233
229
|
"""
|
|
234
230
|
Generates LabelVideoSegments based on the stored prediction array.
|
|
235
231
|
"""
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
"""Model for date value distribution"""
|
|
2
2
|
|
|
3
3
|
from datetime import date, timedelta
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import numpy as np
|
|
6
|
+
from django.db import models
|
|
6
7
|
|
|
7
8
|
from .base_value_distribution import BaseValueDistribution
|
|
8
9
|
|
|
10
|
+
|
|
9
11
|
class DateValueDistributionManager(models.Manager):
|
|
10
|
-
|
|
12
|
+
"""Object manager for DateValueDistribution"""
|
|
13
|
+
|
|
11
14
|
def get_by_natural_key(self, name):
|
|
12
|
-
|
|
15
|
+
"""Retrieve a DateValueDistribution by its natural key."""
|
|
13
16
|
return self.get(name=name)
|
|
14
17
|
|
|
15
18
|
|
|
@@ -20,16 +23,17 @@ class DateValueDistribution(BaseValueDistribution):
|
|
|
20
23
|
date_min, date_max, date_mean, date_std_dev or
|
|
21
24
|
timedelta_days_min, timedelta_days_max, timedelta_days_mean, timedelta_days_std_dev
|
|
22
25
|
"""
|
|
26
|
+
|
|
23
27
|
objects = DateValueDistributionManager()
|
|
24
28
|
name = models.CharField(max_length=100)
|
|
25
29
|
description = models.TextField(blank=True, null=True)
|
|
26
30
|
DISTRIBUTION_CHOICES = [
|
|
27
|
-
(
|
|
28
|
-
(
|
|
31
|
+
("uniform", "Uniform"),
|
|
32
|
+
("normal", "Normal"),
|
|
29
33
|
]
|
|
30
34
|
MODE_CHOICES = [
|
|
31
|
-
(
|
|
32
|
-
(
|
|
35
|
+
("date", "Date"),
|
|
36
|
+
("timedelta", "Timedelta"),
|
|
33
37
|
]
|
|
34
38
|
|
|
35
39
|
distribution_type = models.CharField(max_length=20, choices=DISTRIBUTION_CHOICES)
|
|
@@ -47,43 +51,99 @@ class DateValueDistribution(BaseValueDistribution):
|
|
|
47
51
|
timedelta_days_mean = models.IntegerField(blank=True, null=True)
|
|
48
52
|
timedelta_days_std_dev = models.IntegerField(blank=True, null=True)
|
|
49
53
|
|
|
54
|
+
# create *_safe properties for dates and timedeltas
|
|
55
|
+
@property
|
|
56
|
+
def date_min_safe(self):
|
|
57
|
+
_date = self.date_min
|
|
58
|
+
if _date is None:
|
|
59
|
+
raise ValueError("date_min is not set")
|
|
60
|
+
return _date
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def date_max_safe(self):
|
|
64
|
+
_date = self.date_max
|
|
65
|
+
if _date is None:
|
|
66
|
+
raise ValueError("date_max is not set")
|
|
67
|
+
return _date
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def date_mean_safe(self):
|
|
71
|
+
_date = self.date_mean
|
|
72
|
+
if _date is None:
|
|
73
|
+
raise ValueError("date_mean is not set")
|
|
74
|
+
return _date
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def date_std_dev_safe(self):
|
|
78
|
+
_std_dev = self.date_std_dev
|
|
79
|
+
if _std_dev is None:
|
|
80
|
+
raise ValueError("date_std_dev is not set")
|
|
81
|
+
return _std_dev
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def timedelta_days_min_safe(self):
|
|
85
|
+
_min = self.timedelta_days_min
|
|
86
|
+
if _min is None:
|
|
87
|
+
raise ValueError("timedelta_days_min is not set")
|
|
88
|
+
return _min
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def timedelta_days_max_safe(self):
|
|
92
|
+
_max = self.timedelta_days_max
|
|
93
|
+
if _max is None:
|
|
94
|
+
raise ValueError("timedelta_days_max is not set")
|
|
95
|
+
return _max
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def timedelta_days_mean_safe(self):
|
|
99
|
+
_mean = self.timedelta_days_mean
|
|
100
|
+
if _mean is None:
|
|
101
|
+
raise ValueError("timedelta_days_mean is not set")
|
|
102
|
+
return _mean
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def timedelta_days_std_dev_safe(self):
|
|
106
|
+
_std_dev = self.timedelta_days_std_dev
|
|
107
|
+
if _std_dev is None:
|
|
108
|
+
raise ValueError("timedelta_days_std_dev is not set")
|
|
109
|
+
return _std_dev
|
|
110
|
+
|
|
50
111
|
def generate_value(self):
|
|
51
|
-
if self.mode ==
|
|
112
|
+
if self.mode == "date":
|
|
52
113
|
return self._generate_date_value()
|
|
53
|
-
elif self.mode ==
|
|
114
|
+
elif self.mode == "timedelta":
|
|
54
115
|
return self._generate_timedelta_value()
|
|
55
116
|
else:
|
|
56
117
|
raise ValueError("Unsupported mode")
|
|
57
118
|
|
|
58
119
|
def _generate_date_value(self):
|
|
59
|
-
#UNTESTED
|
|
60
|
-
if self.distribution_type ==
|
|
61
|
-
start_date = self.
|
|
62
|
-
end_date = self.
|
|
120
|
+
# UNTESTED
|
|
121
|
+
if self.distribution_type == "uniform":
|
|
122
|
+
start_date = self.date_min_safe.toordinal()
|
|
123
|
+
end_date = self.date_max_safe.toordinal()
|
|
63
124
|
random_ordinal = np.random.randint(start_date, end_date)
|
|
64
125
|
return date.fromordinal(random_ordinal)
|
|
65
|
-
elif self.distribution_type ==
|
|
66
|
-
mean_ordinal = self.
|
|
67
|
-
std_dev_days = self.
|
|
126
|
+
elif self.distribution_type == "normal":
|
|
127
|
+
mean_ordinal = self.date_mean_safe.toordinal()
|
|
128
|
+
std_dev_days = self.date_std_dev_safe
|
|
68
129
|
random_ordinal = int(np.random.normal(mean_ordinal, std_dev_days))
|
|
69
|
-
random_ordinal = np.clip(random_ordinal, self.
|
|
130
|
+
random_ordinal = np.clip(random_ordinal, self.date_min_safe.toordinal(), self.date_max_safe.toordinal())
|
|
70
131
|
return date.fromordinal(random_ordinal)
|
|
71
132
|
else:
|
|
72
133
|
raise ValueError("Unsupported distribution type")
|
|
73
134
|
|
|
74
135
|
def _generate_timedelta_value(self):
|
|
75
|
-
if self.distribution_type ==
|
|
76
|
-
random_days = np.random.randint(self.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
random_days =
|
|
81
|
-
|
|
82
|
-
|
|
136
|
+
if self.distribution_type == "uniform":
|
|
137
|
+
random_days = np.random.randint(self.timedelta_days_min_safe, self.timedelta_days_max_safe + 1)
|
|
138
|
+
|
|
139
|
+
elif self.distribution_type == "normal":
|
|
140
|
+
random_days = int(np.random.normal(self.timedelta_days_mean_safe, self.timedelta_days_std_dev_safe))
|
|
141
|
+
random_days = np.clip(random_days, self.timedelta_days_min_safe, self.timedelta_days_max_safe)
|
|
142
|
+
|
|
83
143
|
else:
|
|
84
144
|
raise ValueError("Unsupported distribution type")
|
|
85
|
-
|
|
145
|
+
|
|
86
146
|
current_date = date.today()
|
|
87
147
|
generated_date = current_date - timedelta(days=random_days)
|
|
88
|
-
|
|
89
|
-
return
|
|
148
|
+
|
|
149
|
+
return generated_date
|
|
@@ -1,29 +1,45 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
import numpy as np
|
|
2
|
+
from django.db import models
|
|
3
|
+
|
|
3
4
|
from .base_value_distribution import BaseValueDistribution
|
|
4
5
|
|
|
6
|
+
|
|
5
7
|
class MultipleCategoricalValueDistributionManager(models.Manager):
|
|
6
8
|
def get_by_natural_key(self, name):
|
|
7
9
|
return self.get(name=name)
|
|
8
10
|
|
|
11
|
+
|
|
9
12
|
class MultipleCategoricalValueDistribution(BaseValueDistribution):
|
|
10
13
|
"""
|
|
11
14
|
Multiple categorical value distribution model.
|
|
12
15
|
Assigns a specific number or varying number of values based on probabilities.
|
|
13
16
|
"""
|
|
17
|
+
|
|
14
18
|
objects = MultipleCategoricalValueDistributionManager()
|
|
15
19
|
categories = models.JSONField() # { "category": "probability", ... }
|
|
16
20
|
min_count = models.IntegerField()
|
|
17
21
|
max_count = models.IntegerField()
|
|
18
|
-
count_distribution_type = models.CharField(max_length=20, choices=[(
|
|
22
|
+
count_distribution_type = models.CharField(max_length=20, choices=[("uniform", "Uniform"), ("normal", "Normal")])
|
|
19
23
|
count_mean = models.FloatField(null=True, blank=True)
|
|
20
24
|
count_std_dev = models.FloatField(null=True, blank=True)
|
|
21
25
|
|
|
26
|
+
@property
|
|
27
|
+
def count_mean_safe(self):
|
|
28
|
+
if self.count_mean is None:
|
|
29
|
+
raise ValueError("count_mean is not set")
|
|
30
|
+
return self.count_mean
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def count_std_dev_safe(self):
|
|
34
|
+
if self.count_std_dev is None:
|
|
35
|
+
raise ValueError("count_std_dev is not set")
|
|
36
|
+
return self.count_std_dev
|
|
37
|
+
|
|
22
38
|
def generate_value(self):
|
|
23
|
-
if self.count_distribution_type ==
|
|
39
|
+
if self.count_distribution_type == "uniform":
|
|
24
40
|
count = np.random.randint(self.min_count, self.max_count + 1)
|
|
25
|
-
elif self.count_distribution_type ==
|
|
26
|
-
count = int(np.random.normal(self.
|
|
41
|
+
elif self.count_distribution_type == "normal":
|
|
42
|
+
count = int(np.random.normal(self.count_mean_safe, self.count_std_dev_safe))
|
|
27
43
|
count = np.clip(count, self.min_count, self.max_count)
|
|
28
44
|
else:
|
|
29
45
|
raise ValueError("Unsupported count distribution type")
|