endoreg-db 0.5.3__py3-none-any.whl → 0.6.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 +90 -1
- endoreg_db/case_generator/case_generator.py +159 -0
- endoreg_db/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/case_generator/utils.py +30 -0
- endoreg_db/data/__init__.py +50 -4
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
- endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
- endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
- endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
- endoreg_db/data/center/data.yaml +35 -5
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/finding/data.yaml +141 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
- endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
- endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
- endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +30 -0
- endoreg_db/data/gender/data.yaml +17 -0
- endoreg_db/data/lab_value/cardiac_enzymes.yaml +7 -1
- endoreg_db/data/lab_value/coagulation.yaml +6 -1
- endoreg_db/data/lab_value/electrolytes.yaml +39 -1
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
- endoreg_db/data/lab_value/hematology.yaml +17 -2
- endoreg_db/data/lab_value/hormones.yaml +6 -0
- endoreg_db/data/lab_value/lipids.yaml +12 -3
- endoreg_db/data/lab_value/misc.yaml +5 -2
- endoreg_db/data/lab_value/renal_function.yaml +2 -1
- endoreg_db/data/lx_client_tag/base.yaml +54 -0
- endoreg_db/data/lx_client_type/base.yaml +30 -0
- endoreg_db/data/lx_permission/base.yaml +24 -0
- endoreg_db/data/lx_permission/endoreg.yaml +52 -0
- endoreg_db/data/medication_indication/anticoagulation.yaml +44 -49
- endoreg_db/data/names_first/first_names.yaml +51 -0
- endoreg_db/data/names_last/last_names.yaml +51 -0
- endoreg_db/data/network_device/data.yaml +30 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/pdf_type/data.yaml +2 -1
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
- endoreg_db/forms/__init__.py +3 -1
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +19 -0
- endoreg_db/forms/patient_form.py +26 -0
- endoreg_db/management/commands/__init__.py +0 -0
- endoreg_db/management/commands/load_ai_model_data.py +57 -23
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +160 -118
- endoreg_db/management/commands/{load_endoscope_type_data.py → load_contraindication_data.py} +3 -7
- endoreg_db/management/commands/load_disease_data.py +29 -7
- endoreg_db/management/commands/load_endoscope_data.py +68 -0
- endoreg_db/management/commands/load_examination_indication_data.py +65 -0
- endoreg_db/management/commands/load_finding_data.py +171 -0
- endoreg_db/management/commands/load_lab_value_data.py +3 -3
- endoreg_db/management/commands/load_lx_data.py +64 -0
- endoreg_db/management/commands/load_medication_data.py +83 -21
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/{load_endoscopy_processor_data.py → load_organ_data.py} +7 -9
- endoreg_db/migrations/0001_initial.py +1206 -728
- endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
- endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
- endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
- endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
- endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
- endoreg_db/models/__init__.py +331 -28
- endoreg_db/models/ai_model/__init__.py +1 -0
- endoreg_db/models/ai_model/ai_model.py +103 -0
- endoreg_db/models/ai_model/lightning/__init__.py +3 -0
- endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
- endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
- endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
- endoreg_db/models/ai_model/lightning/predict.py +172 -0
- endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
- endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
- endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
- endoreg_db/models/ai_model/model_meta.py +232 -6
- endoreg_db/models/ai_model/model_type.py +13 -3
- endoreg_db/models/annotation/__init__.py +31 -2
- endoreg_db/models/annotation/anonymized_image_annotation.py +73 -18
- endoreg_db/models/annotation/binary_classification_annotation_task.py +94 -57
- endoreg_db/models/annotation/image_classification.py +73 -14
- endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
- endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
- endoreg_db/models/case/__init__.py +1 -0
- endoreg_db/models/{persons/patient/case → case}/case.py +4 -0
- endoreg_db/models/case_template/__init__.py +10 -1
- endoreg_db/models/case_template/case_template.py +57 -13
- endoreg_db/models/case_template/case_template_rule.py +5 -5
- endoreg_db/models/case_template/case_template_rule_value.py +19 -4
- endoreg_db/models/center/__init__.py +7 -0
- endoreg_db/models/center/center.py +31 -5
- endoreg_db/models/center/center_product.py +0 -1
- endoreg_db/models/center/center_resource.py +16 -2
- endoreg_db/models/center/center_waste.py +6 -1
- endoreg_db/models/contraindication/__init__.py +21 -0
- endoreg_db/models/data_file/__init__.py +38 -5
- endoreg_db/models/data_file/base_classes/__init__.py +6 -1
- endoreg_db/models/data_file/base_classes/abstract_frame.py +64 -15
- endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
- endoreg_db/models/data_file/base_classes/abstract_video.py +744 -138
- endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
- endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
- endoreg_db/models/data_file/base_classes/utils.py +80 -0
- endoreg_db/models/data_file/frame.py +22 -38
- endoreg_db/models/data_file/import_classes/__init__.py +4 -18
- endoreg_db/models/data_file/import_classes/raw_pdf.py +162 -90
- endoreg_db/models/data_file/import_classes/raw_video.py +239 -294
- endoreg_db/models/data_file/metadata/__init__.py +10 -0
- endoreg_db/models/data_file/metadata/pdf_meta.py +4 -0
- endoreg_db/models/data_file/metadata/sensitive_meta.py +265 -6
- endoreg_db/models/data_file/metadata/video_meta.py +116 -50
- endoreg_db/models/data_file/report_file.py +30 -63
- endoreg_db/models/data_file/video/__init__.py +6 -2
- endoreg_db/models/data_file/video/video.py +187 -16
- endoreg_db/models/data_file/video_segment.py +162 -55
- endoreg_db/models/disease.py +25 -2
- endoreg_db/models/emission/__init__.py +5 -1
- endoreg_db/models/emission/emission_factor.py +71 -6
- endoreg_db/models/event.py +51 -0
- endoreg_db/models/examination/__init__.py +6 -1
- endoreg_db/models/examination/examination.py +53 -12
- endoreg_db/models/examination/examination_indication.py +170 -0
- endoreg_db/models/examination/examination_time.py +31 -5
- endoreg_db/models/examination/examination_time_type.py +28 -4
- endoreg_db/models/examination/examination_type.py +28 -6
- endoreg_db/models/finding/__init__.py +11 -0
- endoreg_db/models/finding/finding.py +75 -0
- endoreg_db/models/finding/finding_intervention.py +60 -0
- endoreg_db/models/finding/finding_location_classification.py +94 -0
- endoreg_db/models/finding/finding_morphology_classification.py +89 -0
- endoreg_db/models/finding/finding_type.py +22 -0
- endoreg_db/models/hardware/endoscope.py +16 -0
- endoreg_db/models/hardware/endoscopy_processor.py +31 -19
- endoreg_db/models/label/label.py +35 -7
- endoreg_db/models/laboratory/lab_value.py +12 -3
- endoreg_db/models/logging/__init__.py +8 -1
- endoreg_db/models/lx/__init__.py +4 -0
- endoreg_db/models/lx/client.py +57 -0
- endoreg_db/models/lx/identity.py +34 -0
- endoreg_db/models/lx/permission.py +18 -0
- endoreg_db/models/lx/user.py +16 -0
- endoreg_db/models/medication/__init__.py +19 -1
- endoreg_db/models/medication/medication.py +7 -122
- endoreg_db/models/medication/medication_indication.py +50 -0
- endoreg_db/models/medication/medication_indication_type.py +34 -0
- endoreg_db/models/medication/medication_intake_time.py +26 -0
- endoreg_db/models/medication/medication_schedule.py +37 -0
- endoreg_db/models/network/__init__.py +7 -1
- endoreg_db/models/network/network_device.py +13 -8
- endoreg_db/models/organ/__init__.py +38 -0
- endoreg_db/models/other/__init__.py +19 -1
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/distribution.py +1 -211
- endoreg_db/models/other/material.py +4 -0
- endoreg_db/models/other/transport_route.py +2 -1
- endoreg_db/models/patient/__init__.py +24 -0
- endoreg_db/models/patient/patient_examination.py +182 -0
- endoreg_db/models/patient/patient_finding.py +143 -0
- endoreg_db/models/patient/patient_finding_intervention.py +26 -0
- endoreg_db/models/patient/patient_finding_location.py +120 -0
- endoreg_db/models/patient/patient_finding_morphology.py +166 -0
- endoreg_db/models/persons/__init__.py +29 -2
- endoreg_db/models/persons/examiner/examiner.py +48 -4
- endoreg_db/models/persons/patient/__init__.py +1 -1
- endoreg_db/models/persons/patient/patient.py +227 -54
- endoreg_db/models/persons/patient/patient_disease.py +6 -0
- endoreg_db/models/persons/patient/patient_event.py +31 -1
- endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
- endoreg_db/models/persons/patient/patient_lab_sample.py +4 -2
- endoreg_db/models/persons/patient/patient_lab_value.py +37 -16
- endoreg_db/models/persons/patient/patient_medication.py +27 -12
- endoreg_db/models/persons/patient/patient_medication_schedule.py +62 -2
- endoreg_db/models/prediction/__init__.py +7 -1
- endoreg_db/models/prediction/image_classification.py +20 -6
- endoreg_db/models/prediction/video_prediction_meta.py +151 -89
- endoreg_db/models/product/__init__.py +10 -1
- endoreg_db/models/product/product.py +15 -2
- endoreg_db/models/product/product_group.py +8 -0
- endoreg_db/models/product/product_material.py +4 -0
- endoreg_db/models/product/product_weight.py +12 -0
- endoreg_db/models/product/reference_product.py +19 -3
- endoreg_db/models/quiz/__init__.py +8 -1
- endoreg_db/models/report_reader/__init__.py +6 -1
- endoreg_db/serializers/__init__.py +1 -1
- endoreg_db/serializers/annotation.py +2 -5
- endoreg_db/serializers/frame.py +1 -5
- endoreg_db/serializers/patient.py +26 -3
- endoreg_db/serializers/prediction.py +2 -7
- endoreg_db/serializers/raw_video_meta_validation.py +13 -0
- endoreg_db/serializers/video.py +6 -13
- endoreg_db/serializers/video_segmentation.py +492 -0
- endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
- endoreg_db/templates/admin/start_examination.html +12 -0
- endoreg_db/templates/timeline.html +176 -0
- endoreg_db/urls.py +173 -0
- endoreg_db/utils/__init__.py +36 -1
- endoreg_db/utils/dataloader.py +45 -19
- endoreg_db/utils/dates.py +39 -0
- endoreg_db/utils/hashs.py +122 -4
- endoreg_db/utils/names.py +74 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/video/__init__.py +13 -0
- endoreg_db/utils/video/extract_frames.py +121 -0
- endoreg_db/utils/video/transcode_videofile.py +111 -0
- endoreg_db/views/__init__.py +2 -0
- endoreg_db/views/csrf.py +7 -0
- endoreg_db/views/patient_views.py +90 -0
- endoreg_db/views/raw_video_meta_validation_views.py +38 -0
- endoreg_db/views/report_views.py +96 -0
- endoreg_db/views/video_segmentation_views.py +149 -0
- endoreg_db/views/views_for_timeline.py +46 -0
- endoreg_db/views.py +0 -3
- endoreg_db-0.6.1.dist-info/METADATA +151 -0
- endoreg_db-0.6.1.dist-info/RECORD +420 -0
- {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/WHEEL +1 -1
- endoreg_db/data/active_model/data.yaml +0 -3
- endoreg_db/data/label/label-set/data.yaml +0 -18
- endoreg_db/management/commands/delete_legacy_images.py +0 -19
- endoreg_db/management/commands/delete_legacy_videos.py +0 -17
- endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
- endoreg_db/management/commands/import_legacy_images.py +0 -94
- endoreg_db/management/commands/import_legacy_videos.py +0 -76
- endoreg_db/management/commands/load_label_data.py +0 -67
- endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
- endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
- endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
- endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
- endoreg_db/migrations/0008_networkdevicelogentry_aglnet_ip_and_more.py +0 -28
- endoreg_db/migrations/0009_alter_networkdevicelogentry_vpn_service_status.py +0 -18
- endoreg_db/migrations/0010_remove_networkdevicelogentry_hostname.py +0 -17
- endoreg_db/models/legacy_data/__init__.py +0 -3
- endoreg_db/models/legacy_data/image.py +0 -34
- endoreg_db/models/patient_examination/__init__.py +0 -35
- endoreg_db/utils/video_metadata.py +0 -87
- endoreg_db-0.5.3.dist-info/METADATA +0 -28
- endoreg_db-0.5.3.dist-info/RECORD +0 -319
- /endoreg_db/{models/persons/patient/case → case_generator}/__init__.py +0 -0
- /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
- /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
- /endoreg_db/{data/distribution/numeric/.init → management/__init__.py} +0 -0
- /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
- {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
{% extends "admin/base_site.html" %}
|
|
2
|
+
{% block content %}
|
|
3
|
+
|
|
4
|
+
<h2>Patient Finding Intervention</h2>
|
|
5
|
+
|
|
6
|
+
<form method="POST" id="intervention-form">
|
|
7
|
+
{% csrf_token %}
|
|
8
|
+
|
|
9
|
+
<!-- Patient Selection -->
|
|
10
|
+
<div>
|
|
11
|
+
<label>Select Patient:</label><br>
|
|
12
|
+
<select name="patient" id="patient-dropdown">
|
|
13
|
+
<option value="">-- Select Patient --</option>
|
|
14
|
+
{% for patient in patients %}
|
|
15
|
+
<option value="{{ patient.id }}">{{ patient.first_name }} {{ patient.last_name }}</option>
|
|
16
|
+
{% endfor %}
|
|
17
|
+
</select>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
|
|
22
|
+
<!-- Examination Selection -->
|
|
23
|
+
<div>
|
|
24
|
+
<label>Select Examination:</label><br>
|
|
25
|
+
<select name="examination" id="examination-dropdown">
|
|
26
|
+
<option value="">-- Select Examination --</option>
|
|
27
|
+
{% for examination in examinations %}
|
|
28
|
+
<option value="{{ examination.id }}">{{ examination.name }}</option>
|
|
29
|
+
{% endfor %}
|
|
30
|
+
</select>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<br>
|
|
34
|
+
|
|
35
|
+
<!-- Finding Selection -->
|
|
36
|
+
<div>
|
|
37
|
+
<label>Select Finding:</label><br>
|
|
38
|
+
<select name="finding" id="finding-dropdown">
|
|
39
|
+
<option value="">-- Select Finding --</option>
|
|
40
|
+
{% for finding in findings %}
|
|
41
|
+
<option value="{{ finding.id }}">{{ finding.name }}</option>
|
|
42
|
+
{% endfor %}
|
|
43
|
+
</select>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<br>
|
|
47
|
+
|
|
48
|
+
<!-- Select Location -->
|
|
49
|
+
<div>
|
|
50
|
+
<label>Select Location:</label><br>
|
|
51
|
+
<select name="location" id="location-dropdown" onchange="updateFormAction(this)">
|
|
52
|
+
<option value="">-- Select Location --</option>
|
|
53
|
+
{% for location in locations %}
|
|
54
|
+
<option value="{{ location.id }}" {% if location.id == selected_location %}selected{% endif %}>
|
|
55
|
+
{{ location.name }}
|
|
56
|
+
</option>
|
|
57
|
+
{% endfor %}
|
|
58
|
+
</select>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<br>
|
|
62
|
+
|
|
63
|
+
<!-- Select Location Choice -->
|
|
64
|
+
<div>
|
|
65
|
+
<label>Select Location Choice:</label><br>
|
|
66
|
+
<select name="location_choice" id="location-choice-dropdown">
|
|
67
|
+
<option value="">-- Select Location Choice --</option>
|
|
68
|
+
{% for choice in location_choices %}
|
|
69
|
+
<option value="{{ choice.id }}">{{ choice.name }}</option>
|
|
70
|
+
{% endfor %}
|
|
71
|
+
</select>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<br>
|
|
75
|
+
|
|
76
|
+
<!-- Select Morphology -->
|
|
77
|
+
<!-- Select Morphology (FindingMorphologyClassification) -->
|
|
78
|
+
<div>
|
|
79
|
+
<label>Select Morphology:</label><br>
|
|
80
|
+
<select name="morphology" id="morphology-dropdown">
|
|
81
|
+
<option value="">-- Select Morphology --</option>
|
|
82
|
+
{% for morphology in morphologies %}
|
|
83
|
+
<option value="{{ morphology.id }}">{{ morphology.name }}</option>
|
|
84
|
+
{% endfor %}
|
|
85
|
+
</select>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<br>
|
|
89
|
+
|
|
90
|
+
<!-- Select Morphology Choice (FindingMorphologyClassificationChoice) -->
|
|
91
|
+
<div>
|
|
92
|
+
<label>Select Morphology Choice:</label><br>
|
|
93
|
+
<select name="morphology_choice" id="morphology-choice-dropdown">
|
|
94
|
+
<option value="">-- Select Morphology Choice --</option>
|
|
95
|
+
{% for choice in morphology_choices %}
|
|
96
|
+
<option value="{{ choice.id }}">{{ choice.name }}</option>
|
|
97
|
+
{% endfor %}
|
|
98
|
+
</select>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
<br>
|
|
103
|
+
|
|
104
|
+
<!-- Select Finding Interventions -->
|
|
105
|
+
<div>
|
|
106
|
+
<label>Select Finding Interventions:</label><br>
|
|
107
|
+
<select name="finding_intervention" id="finding-intervention-dropdown">
|
|
108
|
+
<option value="">-- Select Finding Intervention --</option>
|
|
109
|
+
{% for intervention in finding_interventions %}
|
|
110
|
+
<option value="{{ intervention.id }}">{{ intervention.name }}</option>
|
|
111
|
+
{% endfor %}
|
|
112
|
+
</select>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<br>
|
|
116
|
+
|
|
117
|
+
<div>
|
|
118
|
+
<button type="button" id="generate-report-btn">Generate Report</button>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<!-- Display Report Section -->
|
|
122
|
+
<div id="report-section" style="display:none; margin-top: 20px;">
|
|
123
|
+
<h3>Generated Report</h3>
|
|
124
|
+
<p><strong>Patient:</strong> <span id="report-patient"></span></p>
|
|
125
|
+
<p><strong>Examination:</strong> <span id="report-examination"></span></p>
|
|
126
|
+
<p><strong>Finding:</strong> <span id="report-finding"></span></p>
|
|
127
|
+
<p><strong>Location:</strong> <span id="report-location"></span></p>
|
|
128
|
+
<p><strong>Location Choice:</strong> <span id="report-location-choice"></span></p>
|
|
129
|
+
<p><strong>Morphology:</strong> <span id="report-morphology"></span></p>
|
|
130
|
+
<p><strong>Morphology Choice:</strong> <span id="report-morphology-choice"></span></p>
|
|
131
|
+
<p><strong>Finding Intervention:</strong> <span id="report-finding-intervention"></span></p>
|
|
132
|
+
|
|
133
|
+
<button id="download-report-btn">Download Report</button>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
</form>
|
|
137
|
+
|
|
138
|
+
<script>
|
|
139
|
+
document.getElementById("location-dropdown").addEventListener("change", function() {
|
|
140
|
+
let locationId = this.value;
|
|
141
|
+
let locationChoiceDropdown = document.getElementById("location-choice-dropdown");
|
|
142
|
+
|
|
143
|
+
// Reset dropdown
|
|
144
|
+
locationChoiceDropdown.innerHTML = '<option value="">-- Select Location Choice --</option>';
|
|
145
|
+
|
|
146
|
+
// Fetch Choices Only If a Location is Selected
|
|
147
|
+
if (locationId) {
|
|
148
|
+
fetch(`/endoreg_db/get-location-choices/${locationId}/`)
|
|
149
|
+
.then(response => response.json())
|
|
150
|
+
.then(data => {
|
|
151
|
+
if (data.location_choices.length === 0) {
|
|
152
|
+
locationChoiceDropdown.innerHTML = `<option value="default">Rectum</option>`; // Default Value
|
|
153
|
+
} else {
|
|
154
|
+
data.location_choices.forEach(choice => {
|
|
155
|
+
locationChoiceDropdown.innerHTML += `<option value="${choice.id}">${choice.name}</option>`;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
.catch(error => {
|
|
160
|
+
console.error("Error loading location choices:", error);
|
|
161
|
+
alert("Error: Could not fetch location choices.");
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
locationChoiceDropdown.innerHTML = `<option value="default">Rectum</option>`; // Default Value
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
</script>
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
<script>
|
|
171
|
+
document.getElementById("generate-report-btn").addEventListener("click", function() {
|
|
172
|
+
let getText = (id, defaultValue = "Not Selected") => {
|
|
173
|
+
let element = document.getElementById(id);
|
|
174
|
+
return element.selectedOptions.length > 0 ? element.selectedOptions[0].text.trim() : defaultValue;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
document.getElementById("report-patient").textContent = getText("patient-dropdown");
|
|
178
|
+
document.getElementById("report-examination").textContent = getText("examination-dropdown");
|
|
179
|
+
document.getElementById("report-finding").textContent = getText("finding-dropdown");
|
|
180
|
+
document.getElementById("report-location").textContent = getText("location-dropdown");
|
|
181
|
+
document.getElementById("report-location-choice").textContent = getText("location-choice-dropdown", "Rectum");
|
|
182
|
+
document.getElementById("report-morphology").textContent = getText("morphology-dropdown");
|
|
183
|
+
document.getElementById("report-morphology-choice").textContent = getText("morphology-choice-dropdown");
|
|
184
|
+
document.getElementById("report-finding-intervention").textContent = getText("finding-intervention-dropdown");
|
|
185
|
+
|
|
186
|
+
document.getElementById("report-section").style.display = "block";
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
document.getElementById("download-report-btn").addEventListener("click", function() {
|
|
190
|
+
let reportContent = `
|
|
191
|
+
Patient: ${document.getElementById("report-patient").textContent}
|
|
192
|
+
Examination: ${document.getElementById("report-examination").textContent}
|
|
193
|
+
Finding: ${document.getElementById("report-finding").textContent}
|
|
194
|
+
Location: ${document.getElementById("report-location").textContent}
|
|
195
|
+
Location Choice: ${document.getElementById("report-location-choice").textContent}
|
|
196
|
+
Morphology: ${document.getElementById("report-morphology").textContent}
|
|
197
|
+
Morphology Choice: ${document.getElementById("report-morphology-choice").textContent}
|
|
198
|
+
Finding Intervention: ${document.getElementById("report-finding-intervention").textContent}
|
|
199
|
+
`;
|
|
200
|
+
|
|
201
|
+
let blob = new Blob([reportContent], { type: "text/plain" });
|
|
202
|
+
let link = document.createElement("a");
|
|
203
|
+
link.href = URL.createObjectURL(blob);
|
|
204
|
+
link.download = "Patient_Finding_Report.txt";
|
|
205
|
+
document.body.appendChild(link);
|
|
206
|
+
link.click();
|
|
207
|
+
document.body.removeChild(link);
|
|
208
|
+
});
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<script>
|
|
212
|
+
document.getElementById("morphology-dropdown").addEventListener("change", function() {
|
|
213
|
+
let morphologyId = this.value;
|
|
214
|
+
let morphologyChoiceDropdown = document.getElementById("morphology-choice-dropdown");
|
|
215
|
+
|
|
216
|
+
// Reset Morphology Choice Dropdown
|
|
217
|
+
morphologyChoiceDropdown.innerHTML = '<option value="">-- Select Morphology Choice --</option>';
|
|
218
|
+
|
|
219
|
+
// Fetch Choices Only If a Morphology is Selected
|
|
220
|
+
if (morphologyId) {
|
|
221
|
+
fetch(`/endoreg_db/get-morphology-choices/${morphologyId}/`)
|
|
222
|
+
.then(response => {
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
225
|
+
}
|
|
226
|
+
return response.json();
|
|
227
|
+
})
|
|
228
|
+
.then(data => {
|
|
229
|
+
if (data.error) {
|
|
230
|
+
console.error("Server Error:", data.error);
|
|
231
|
+
alert("Error: " + data.error);
|
|
232
|
+
} else {
|
|
233
|
+
if (data.morphology_choices.length === 0) {
|
|
234
|
+
morphologyChoiceDropdown.innerHTML = `<option value="default">No Choices Available</option>`; // Default Value
|
|
235
|
+
} else {
|
|
236
|
+
data.morphology_choices.forEach(choice => {
|
|
237
|
+
morphologyChoiceDropdown.innerHTML += `<option value="${choice.id}">${choice.name}</option>`;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
.catch(error => {
|
|
243
|
+
console.error("Error loading morphology choices:", error);
|
|
244
|
+
alert("Error: Could not fetch morphology choices.");
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
{% endblock %}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- start_examination.html -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Start Examination</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<h1>Hello World</h1>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>Frames Timeline (Outside Label)</title>
|
|
5
|
+
<style>
|
|
6
|
+
body { font-family: Arial, sans-serif; text-align: center; margin: 20px; }
|
|
7
|
+
video { width: 80%; margin-bottom: 20px; }
|
|
8
|
+
|
|
9
|
+
/* Timeline Container */
|
|
10
|
+
.timeline-container {
|
|
11
|
+
position: relative;
|
|
12
|
+
width: 80%;
|
|
13
|
+
height: 50px;
|
|
14
|
+
margin: auto;
|
|
15
|
+
background: #f0f0f0;
|
|
16
|
+
border-radius: 5px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Timeline Bar */
|
|
20
|
+
.timeline-bar {
|
|
21
|
+
width: 100%;
|
|
22
|
+
height: 8px;
|
|
23
|
+
background-color: #ccc;
|
|
24
|
+
position: absolute;
|
|
25
|
+
top: 50%;
|
|
26
|
+
transform: translateY(-50%);
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Red Highlight for Outside Label Segments */
|
|
31
|
+
.segment-box {
|
|
32
|
+
position: absolute;
|
|
33
|
+
height: 8px;
|
|
34
|
+
background-color: rgba(255, 0, 0, 0.7);
|
|
35
|
+
border-radius: 4px;
|
|
36
|
+
top: 50%;
|
|
37
|
+
transform: translateY(-50%);
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Draggable Vertical Markers */
|
|
42
|
+
.frame-marker {
|
|
43
|
+
position: absolute;
|
|
44
|
+
width: 6px;
|
|
45
|
+
height: 20px;
|
|
46
|
+
background-color: blue;
|
|
47
|
+
cursor: grab;
|
|
48
|
+
top: 50%;
|
|
49
|
+
transform: translate(-50%, -50%);
|
|
50
|
+
border-radius: 3px;
|
|
51
|
+
transition: background-color 0.2s;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.frame-marker:hover {
|
|
55
|
+
background-color: red;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.frame-marker:active {
|
|
59
|
+
cursor: grabbing;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
</style>
|
|
63
|
+
</head>
|
|
64
|
+
<body>
|
|
65
|
+
<h2>Frames Timeline (Outside Label)</h2>
|
|
66
|
+
|
|
67
|
+
<video id="videoPlayer" controls>
|
|
68
|
+
<source src="{{ video_url }}" type="video/mp4">
|
|
69
|
+
Your browser does not support the video tag.
|
|
70
|
+
</video>
|
|
71
|
+
|
|
72
|
+
<div class="timeline-container">
|
|
73
|
+
<div class="timeline-bar"></div>
|
|
74
|
+
<div id="segments"></div> <!-- Highlighted segments -->
|
|
75
|
+
<div id="frameMarkers"></div> <!-- Start & End markers -->
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<script>
|
|
79
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
80
|
+
const segments = JSON.parse('{{ segments|safe }}'); // Get "outside" label segments
|
|
81
|
+
const video = document.getElementById("videoPlayer");
|
|
82
|
+
const timelineContainer = document.querySelector(".timeline-container");
|
|
83
|
+
const segmentsContainer = document.getElementById("segments");
|
|
84
|
+
const frameMarkersContainer = document.getElementById("frameMarkers");
|
|
85
|
+
|
|
86
|
+
let videoDuration = {{ video_duration|default:1 }}; // Ensure valid duration
|
|
87
|
+
|
|
88
|
+
console.log("Loaded Segments:", segments);
|
|
89
|
+
console.log("Video Duration:", videoDuration);
|
|
90
|
+
|
|
91
|
+
if (segments.length === 0) {
|
|
92
|
+
console.warn("No segments available!");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Create segment boxes
|
|
97
|
+
segments.forEach(segment => {
|
|
98
|
+
const segmentDiv = document.createElement("div");
|
|
99
|
+
segmentDiv.classList.add("segment-box");
|
|
100
|
+
|
|
101
|
+
// Convert times to percentage positions
|
|
102
|
+
let startPercent = (segment.start_time / videoDuration) * 100;
|
|
103
|
+
let endPercent = (segment.end_time / videoDuration) * 100;
|
|
104
|
+
let widthPercent = endPercent - startPercent;
|
|
105
|
+
|
|
106
|
+
// Ensure last segment does not go beyond 100%
|
|
107
|
+
startPercent = Math.min(100, startPercent);
|
|
108
|
+
endPercent = Math.min(100, endPercent);
|
|
109
|
+
widthPercent = Math.max(0, endPercent - startPercent);
|
|
110
|
+
|
|
111
|
+
segmentDiv.style.left = startPercent + "%";
|
|
112
|
+
segmentDiv.style.width = widthPercent + "%";
|
|
113
|
+
|
|
114
|
+
// Clicking on segment seeks video
|
|
115
|
+
segmentDiv.addEventListener("click", function () {
|
|
116
|
+
video.currentTime = segment.start_time;
|
|
117
|
+
video.play();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
segmentsContainer.appendChild(segmentDiv);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Create draggable markers
|
|
124
|
+
segments.forEach(segment => {
|
|
125
|
+
["start_time", "end_time"].forEach(timeType => {
|
|
126
|
+
const marker = document.createElement("div");
|
|
127
|
+
marker.classList.add("frame-marker");
|
|
128
|
+
|
|
129
|
+
// Position marker
|
|
130
|
+
let percent = (segment[timeType] / videoDuration) * 100;
|
|
131
|
+
percent = Math.min(100, Math.max(0, percent)); // Keep within bounds
|
|
132
|
+
marker.style.left = percent + "%";
|
|
133
|
+
|
|
134
|
+
// Store initial marker time
|
|
135
|
+
marker.dataset.time = segment[timeType];
|
|
136
|
+
|
|
137
|
+
// Enable dragging
|
|
138
|
+
let isDragging = false;
|
|
139
|
+
|
|
140
|
+
marker.addEventListener("pointerdown", (event) => {
|
|
141
|
+
isDragging = true;
|
|
142
|
+
marker.style.cursor = "grabbing";
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
document.addEventListener("pointermove", (event) => {
|
|
147
|
+
if (!isDragging) return;
|
|
148
|
+
|
|
149
|
+
const rect = timelineContainer.getBoundingClientRect();
|
|
150
|
+
const offsetX = event.clientX - rect.left;
|
|
151
|
+
let percentX = (offsetX / rect.width) * 100;
|
|
152
|
+
|
|
153
|
+
// Keep marker within bounds (0-100%)
|
|
154
|
+
percentX = Math.min(100, Math.max(0, percentX));
|
|
155
|
+
|
|
156
|
+
const newTime = (percentX / 100) * videoDuration;
|
|
157
|
+
|
|
158
|
+
marker.style.left = percentX + "%";
|
|
159
|
+
video.currentTime = newTime;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
document.addEventListener("pointerup", () => {
|
|
163
|
+
if (isDragging) {
|
|
164
|
+
isDragging = false;
|
|
165
|
+
marker.style.cursor = "grab";
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
frameMarkersContainer.appendChild(marker);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
});
|
|
174
|
+
</script>
|
|
175
|
+
</body>
|
|
176
|
+
</html>
|
endoreg_db/urls.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from django.urls import path, include
|
|
2
|
+
from rest_framework.routers import DefaultRouter
|
|
3
|
+
from .views.patient_views import (
|
|
4
|
+
PatientViewSet,
|
|
5
|
+
start_examination,
|
|
6
|
+
get_location_choices,
|
|
7
|
+
get_morphology_choices,
|
|
8
|
+
)
|
|
9
|
+
from .views.csrf import csrf_token_view
|
|
10
|
+
#from .views.feature_selection_view import FetchSingleFramePredictionView // its implemented in ando-ai other project need to add here
|
|
11
|
+
from .views.video_segmentation_views import VideoView, VideoLabelView,UpdateLabelSegmentsView
|
|
12
|
+
from .views.views_for_timeline import video_timeline_view
|
|
13
|
+
from .views.raw_video_meta_validation_views import VideoFileForMetaView
|
|
14
|
+
router = DefaultRouter()
|
|
15
|
+
router.register(r'patients', PatientViewSet)
|
|
16
|
+
|
|
17
|
+
urlpatterns = [
|
|
18
|
+
path('start-examination/', start_examination, name="start_examination"),
|
|
19
|
+
path('get-location-choices/<int:location_id>/', get_location_choices, name="get_location_choices"),
|
|
20
|
+
path('get-morphology-choices/<int:morphology_id>/', get_morphology_choices, name="get_morphology_choices"),
|
|
21
|
+
path('api/', include(router.urls)),
|
|
22
|
+
path('api/conf/', csrf_token_view, name='csrf_token'),
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#--------------------------------------VIDEO SEGMENTATION END POINTS--------------------------------------
|
|
27
|
+
|
|
28
|
+
# The dropdown contains video names and their corresponding IDs, which are retrieved from the database(RawVideoFile). Additionally, this route(api/videos) also fetches labels along with their names and IDs from the label table.
|
|
29
|
+
# We will modify this implementation later as per our requirements.
|
|
30
|
+
#Based on the selected video ID, relevant data will be fetched from the database, and the video, along with its associated details,
|
|
31
|
+
# will be displayed on the frontend using route(api/video/<int:video_id>/).
|
|
32
|
+
# once label is selected from the dropdown,using its name, details can be fetched from rawvideofile using route("api/video/<int:video_id>/label/<str:label_name>/)
|
|
33
|
+
#If editing is required, a form will be available for each label. This form dynamically updates when the selected label changes. It will display all segments associated with the selected label, each with a delete option. Below these segments, there may be a button for adding more segments.
|
|
34
|
+
#If any values in the form are modified, the updated data will be saved in the database table.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Fetch all videos for the dropdown
|
|
40
|
+
# Fetch all available videos (for the video selection dropdown in frontend)
|
|
41
|
+
# Usage in frontend: Call this API to get a list of available videos.
|
|
42
|
+
# Example request: GET /api/videos/
|
|
43
|
+
# Response: Returns a JSON list of videos (id, file path, video_url, sequences, label_names).
|
|
44
|
+
# it also fetch the label from teh label table
|
|
45
|
+
path("api/videos/", VideoView.as_view(), name="video_list"),
|
|
46
|
+
|
|
47
|
+
#need to change this route
|
|
48
|
+
#path('api/prediction/', FetchSingleFramePredictionView.as_view(), name='fetch-single-frame-prediction'),#.as_view() converts the class-based view into a function that Django can use for routing.
|
|
49
|
+
|
|
50
|
+
# Fetch video details + labels based on selected video
|
|
51
|
+
# Usage in frontend: Call this when a user selects a video from the dropdown.
|
|
52
|
+
# Example request: GET /api/video/1/
|
|
53
|
+
# Response: Returns metadata, file path, video URL, sequences, and available label names.
|
|
54
|
+
# Frontend should use this api for `label_names`, to display label selection (dropdown or tabs).
|
|
55
|
+
path("api/video/<int:video_id>/", VideoView.as_view(), name="video_handler"),
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Fetch time segments along with frame predictions and filenames for a selected label
|
|
59
|
+
#
|
|
60
|
+
# **Usage in frontend:**
|
|
61
|
+
# - Call this API when a user selects a label from the dropdown in the timeline.
|
|
62
|
+
# - The API returns time segments (start & end times in seconds) where the label appears in the video.
|
|
63
|
+
# - Each segment includes frame-wise predictions and the corresponding frame filenames.
|
|
64
|
+
#
|
|
65
|
+
# **Example request:**
|
|
66
|
+
# GET /api/video/1/label/outside/
|
|
67
|
+
#
|
|
68
|
+
# **Example response:**
|
|
69
|
+
# {
|
|
70
|
+
# "label": "outside",
|
|
71
|
+
# "time_segments": [
|
|
72
|
+
# { "segment_start": 0,
|
|
73
|
+
# "segment_end": 463,
|
|
74
|
+
# "start_time": 0.0,
|
|
75
|
+
# "end_time": 9.26,
|
|
76
|
+
# "frames": {
|
|
77
|
+
# "0": {
|
|
78
|
+
# "frame_filename": "frame_0000000.jpg",
|
|
79
|
+
# "frame_file_path": "/home/admin/test-data/video_frames/abc123/frame_0000000.jpg",
|
|
80
|
+
# "predictions": {
|
|
81
|
+
# "appendix": 0.0150,
|
|
82
|
+
# and others
|
|
83
|
+
# }
|
|
84
|
+
# },
|
|
85
|
+
# "1": {
|
|
86
|
+
# "frame_filename": "frame_0000001.jpg",
|
|
87
|
+
# "frame_file_path": "/home/admin/test-data/video_frames/abc123/frame_0000001.jpg",
|
|
88
|
+
# "predictions": {
|
|
89
|
+
# "appendix": 0.0124,
|
|
90
|
+
# and otehrs
|
|
91
|
+
# }}}}]}
|
|
92
|
+
#
|
|
93
|
+
# start_time and end_time are in seconds, converted from frame indices.
|
|
94
|
+
# frames contains all frames in the segment with:
|
|
95
|
+
# frame_filename (e.g., frame_0000001.jpg)
|
|
96
|
+
# frame_file_path (full path for easy access)
|
|
97
|
+
# predictions (frame-wise probability scores for each category)
|
|
98
|
+
#we need label name for this not id as we donot have id in rawvideofile table
|
|
99
|
+
path("api/video/<int:video_id>/label/<str:label_name>/", VideoLabelView.as_view(), name="video_label_times"),
|
|
100
|
+
|
|
101
|
+
# Update or create label segments for a specific video and label
|
|
102
|
+
# - Call this API when a user updates the start and end frames of a label segment(adding new , deleting or changing the values).
|
|
103
|
+
# - The API will:
|
|
104
|
+
# - **Update** existing segments if they match the given `video_id` and `label_id`.
|
|
105
|
+
# - **Create** new segments if they do not already exist.
|
|
106
|
+
# - **Delete** segments from the database if they were removed from the frontend.
|
|
107
|
+
# - This ensures that the database reflects exactly what is sent from the frontend.
|
|
108
|
+
#
|
|
109
|
+
# **Example request (Updating segments for label ID 12 in video ID 1):**
|
|
110
|
+
# PUT /api/video/1/label/12/update_segments/
|
|
111
|
+
#
|
|
112
|
+
# **Request body (JSON):**
|
|
113
|
+
# {
|
|
114
|
+
# "video_id": 1,
|
|
115
|
+
# "label_id": 12,
|
|
116
|
+
# "segments": [
|
|
117
|
+
# {
|
|
118
|
+
# "start_frame_number": 0,
|
|
119
|
+
# "end_frame_number": 463
|
|
120
|
+
# },{
|
|
121
|
+
# "start_frame_number": 500,
|
|
122
|
+
# "end_frame_number": 700
|
|
123
|
+
# }]}
|
|
124
|
+
#
|
|
125
|
+
# **Expected response (If successful):**
|
|
126
|
+
# {
|
|
127
|
+
# "updated_segments": [
|
|
128
|
+
# {
|
|
129
|
+
# "id": 1,
|
|
130
|
+
# "video_id": 1,
|
|
131
|
+
# "label_id": 12,
|
|
132
|
+
# "start_frame_number": 0,
|
|
133
|
+
# "end_frame_number": 463
|
|
134
|
+
# }
|
|
135
|
+
# ],
|
|
136
|
+
# "new_segments": [
|
|
137
|
+
# {
|
|
138
|
+
# "id": 2,
|
|
139
|
+
# "video_id": 1,
|
|
140
|
+
# "label_id": 12,
|
|
141
|
+
# "start_frame_number": 500,
|
|
142
|
+
# "end_frame_number": 700
|
|
143
|
+
# }
|
|
144
|
+
# ],
|
|
145
|
+
# "deleted_segments": 1 # Number of deleted segments if any were removed
|
|
146
|
+
# }
|
|
147
|
+
|
|
148
|
+
# **Frontend Integration:**
|
|
149
|
+
# - Vue.js should send this request when the user **saves changes** to segments.
|
|
150
|
+
# - The **"Add Segment"** button should allow users to add new segments dynamically.
|
|
151
|
+
# - The **"Delete Segment"** button should remove segments from the list before submitting.
|
|
152
|
+
# - The request should be triggered via an `axios.put` call:
|
|
153
|
+
#
|
|
154
|
+
path("api/video/<int:video_id>/label/<int:label_id>/update_segments/", UpdateLabelSegmentsView.as_view(), name="update_label_segments"),
|
|
155
|
+
|
|
156
|
+
#----------------------------------END--VIDEO SEGMENTATION SECTION-------------------------------
|
|
157
|
+
#this is for to test the timeline
|
|
158
|
+
#need to delete this url and also endoreg_db_production/endoreg_db/views/views_for_timeline.py and endoreg_db_production/endoreg_db/templates/timeline.html
|
|
159
|
+
path('video/<int:video_id>/timeline/', video_timeline_view, name='video_timeline'),
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# const url = lastId ? `http://localhost:8000/api/video/meta/?last_id=${lastId}` : "http://localhost:8000/api/video/meta/";
|
|
165
|
+
path("api/video/sensitivemeta/", VideoFileForMetaView.as_view(), name="video_meta"), # Single endpoint for both first and next video
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
#https://biigle.de/manual/tutorials/videos/navigating-timeline#for time line example
|
endoreg_db/utils/__init__.py
CHANGED
|
@@ -1 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
"""Module for utility classes and functions."""
|
|
2
|
+
|
|
3
|
+
from .dataloader import load_model_data_from_yaml
|
|
4
|
+
from .parse_and_generate_yaml import collect_center_names
|
|
5
|
+
from .validate_endo_roi import validate_endo_roi
|
|
6
|
+
from .pydantic_models import DbConfig
|
|
7
|
+
from .dates import random_day_by_month_year, random_day_by_year
|
|
8
|
+
from .hashs import (
|
|
9
|
+
get_hash_string,
|
|
10
|
+
get_pdf_hash,
|
|
11
|
+
get_examiner_hash,
|
|
12
|
+
get_video_hash,
|
|
13
|
+
get_patient_examination_hash,
|
|
14
|
+
)
|
|
15
|
+
from .names import (
|
|
16
|
+
create_mock_patient_name,
|
|
17
|
+
create_mock_examiner_name,
|
|
18
|
+
guess_name_gender,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"load_model_data_from_yaml",
|
|
23
|
+
"collect_center_names",
|
|
24
|
+
"validate_endo_roi",
|
|
25
|
+
"get_examiner_hash",
|
|
26
|
+
"DbConfig",
|
|
27
|
+
"random_day_by_month_year",
|
|
28
|
+
"random_day_by_year",
|
|
29
|
+
"get_hash_string",
|
|
30
|
+
"create_mock_examiner_name",
|
|
31
|
+
"create_mock_patient_name",
|
|
32
|
+
"guess_name_gender",
|
|
33
|
+
"get_pdf_hash",
|
|
34
|
+
"get_video_hash",
|
|
35
|
+
"get_patient_examination_hash",
|
|
36
|
+
]
|