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.

Files changed (268) hide show
  1. endoreg_db/admin.py +90 -1
  2. endoreg_db/case_generator/case_generator.py +159 -0
  3. endoreg_db/case_generator/lab_sample_factory.py +33 -0
  4. endoreg_db/case_generator/utils.py +30 -0
  5. endoreg_db/data/__init__.py +50 -4
  6. endoreg_db/data/ai_model/data.yaml +7 -0
  7. endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
  8. endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
  9. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
  10. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  11. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  12. endoreg_db/data/center/data.yaml +35 -5
  13. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  14. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  15. endoreg_db/data/endoscope/data.yaml +93 -0
  16. endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
  17. endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
  18. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
  19. endoreg_db/data/finding/data.yaml +141 -0
  20. endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
  21. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  22. endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
  23. endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
  24. endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
  25. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
  26. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
  27. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
  28. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
  29. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
  30. endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
  31. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
  32. endoreg_db/data/finding_type/data.yaml +30 -0
  33. endoreg_db/data/gender/data.yaml +17 -0
  34. endoreg_db/data/lab_value/cardiac_enzymes.yaml +7 -1
  35. endoreg_db/data/lab_value/coagulation.yaml +6 -1
  36. endoreg_db/data/lab_value/electrolytes.yaml +39 -1
  37. endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
  38. endoreg_db/data/lab_value/hematology.yaml +17 -2
  39. endoreg_db/data/lab_value/hormones.yaml +6 -0
  40. endoreg_db/data/lab_value/lipids.yaml +12 -3
  41. endoreg_db/data/lab_value/misc.yaml +5 -2
  42. endoreg_db/data/lab_value/renal_function.yaml +2 -1
  43. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  44. endoreg_db/data/lx_client_type/base.yaml +30 -0
  45. endoreg_db/data/lx_permission/base.yaml +24 -0
  46. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  47. endoreg_db/data/medication_indication/anticoagulation.yaml +44 -49
  48. endoreg_db/data/names_first/first_names.yaml +51 -0
  49. endoreg_db/data/names_last/last_names.yaml +51 -0
  50. endoreg_db/data/network_device/data.yaml +30 -0
  51. endoreg_db/data/organ/data.yaml +29 -0
  52. endoreg_db/data/pdf_type/data.yaml +2 -1
  53. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
  54. endoreg_db/forms/__init__.py +3 -1
  55. endoreg_db/forms/examination_form.py +11 -0
  56. endoreg_db/forms/patient_finding_intervention_form.py +19 -0
  57. endoreg_db/forms/patient_form.py +26 -0
  58. endoreg_db/management/commands/__init__.py +0 -0
  59. endoreg_db/management/commands/load_ai_model_data.py +57 -23
  60. endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
  61. endoreg_db/management/commands/load_base_db_data.py +160 -118
  62. endoreg_db/management/commands/{load_endoscope_type_data.py → load_contraindication_data.py} +3 -7
  63. endoreg_db/management/commands/load_disease_data.py +29 -7
  64. endoreg_db/management/commands/load_endoscope_data.py +68 -0
  65. endoreg_db/management/commands/load_examination_indication_data.py +65 -0
  66. endoreg_db/management/commands/load_finding_data.py +171 -0
  67. endoreg_db/management/commands/load_lab_value_data.py +3 -3
  68. endoreg_db/management/commands/load_lx_data.py +64 -0
  69. endoreg_db/management/commands/load_medication_data.py +83 -21
  70. endoreg_db/management/commands/load_name_data.py +37 -0
  71. endoreg_db/management/commands/{load_endoscopy_processor_data.py → load_organ_data.py} +7 -9
  72. endoreg_db/migrations/0001_initial.py +1206 -728
  73. endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
  74. endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
  75. endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
  76. endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
  77. endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
  78. endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
  79. endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
  80. endoreg_db/models/__init__.py +331 -28
  81. endoreg_db/models/ai_model/__init__.py +1 -0
  82. endoreg_db/models/ai_model/ai_model.py +103 -0
  83. endoreg_db/models/ai_model/lightning/__init__.py +3 -0
  84. endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
  85. endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
  86. endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
  87. endoreg_db/models/ai_model/lightning/predict.py +172 -0
  88. endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
  89. endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
  90. endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
  91. endoreg_db/models/ai_model/model_meta.py +232 -6
  92. endoreg_db/models/ai_model/model_type.py +13 -3
  93. endoreg_db/models/annotation/__init__.py +31 -2
  94. endoreg_db/models/annotation/anonymized_image_annotation.py +73 -18
  95. endoreg_db/models/annotation/binary_classification_annotation_task.py +94 -57
  96. endoreg_db/models/annotation/image_classification.py +73 -14
  97. endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
  98. endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
  99. endoreg_db/models/case/__init__.py +1 -0
  100. endoreg_db/models/{persons/patient/case → case}/case.py +4 -0
  101. endoreg_db/models/case_template/__init__.py +10 -1
  102. endoreg_db/models/case_template/case_template.py +57 -13
  103. endoreg_db/models/case_template/case_template_rule.py +5 -5
  104. endoreg_db/models/case_template/case_template_rule_value.py +19 -4
  105. endoreg_db/models/center/__init__.py +7 -0
  106. endoreg_db/models/center/center.py +31 -5
  107. endoreg_db/models/center/center_product.py +0 -1
  108. endoreg_db/models/center/center_resource.py +16 -2
  109. endoreg_db/models/center/center_waste.py +6 -1
  110. endoreg_db/models/contraindication/__init__.py +21 -0
  111. endoreg_db/models/data_file/__init__.py +38 -5
  112. endoreg_db/models/data_file/base_classes/__init__.py +6 -1
  113. endoreg_db/models/data_file/base_classes/abstract_frame.py +64 -15
  114. endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
  115. endoreg_db/models/data_file/base_classes/abstract_video.py +744 -138
  116. endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
  117. endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
  118. endoreg_db/models/data_file/base_classes/utils.py +80 -0
  119. endoreg_db/models/data_file/frame.py +22 -38
  120. endoreg_db/models/data_file/import_classes/__init__.py +4 -18
  121. endoreg_db/models/data_file/import_classes/raw_pdf.py +162 -90
  122. endoreg_db/models/data_file/import_classes/raw_video.py +239 -294
  123. endoreg_db/models/data_file/metadata/__init__.py +10 -0
  124. endoreg_db/models/data_file/metadata/pdf_meta.py +4 -0
  125. endoreg_db/models/data_file/metadata/sensitive_meta.py +265 -6
  126. endoreg_db/models/data_file/metadata/video_meta.py +116 -50
  127. endoreg_db/models/data_file/report_file.py +30 -63
  128. endoreg_db/models/data_file/video/__init__.py +6 -2
  129. endoreg_db/models/data_file/video/video.py +187 -16
  130. endoreg_db/models/data_file/video_segment.py +162 -55
  131. endoreg_db/models/disease.py +25 -2
  132. endoreg_db/models/emission/__init__.py +5 -1
  133. endoreg_db/models/emission/emission_factor.py +71 -6
  134. endoreg_db/models/event.py +51 -0
  135. endoreg_db/models/examination/__init__.py +6 -1
  136. endoreg_db/models/examination/examination.py +53 -12
  137. endoreg_db/models/examination/examination_indication.py +170 -0
  138. endoreg_db/models/examination/examination_time.py +31 -5
  139. endoreg_db/models/examination/examination_time_type.py +28 -4
  140. endoreg_db/models/examination/examination_type.py +28 -6
  141. endoreg_db/models/finding/__init__.py +11 -0
  142. endoreg_db/models/finding/finding.py +75 -0
  143. endoreg_db/models/finding/finding_intervention.py +60 -0
  144. endoreg_db/models/finding/finding_location_classification.py +94 -0
  145. endoreg_db/models/finding/finding_morphology_classification.py +89 -0
  146. endoreg_db/models/finding/finding_type.py +22 -0
  147. endoreg_db/models/hardware/endoscope.py +16 -0
  148. endoreg_db/models/hardware/endoscopy_processor.py +31 -19
  149. endoreg_db/models/label/label.py +35 -7
  150. endoreg_db/models/laboratory/lab_value.py +12 -3
  151. endoreg_db/models/logging/__init__.py +8 -1
  152. endoreg_db/models/lx/__init__.py +4 -0
  153. endoreg_db/models/lx/client.py +57 -0
  154. endoreg_db/models/lx/identity.py +34 -0
  155. endoreg_db/models/lx/permission.py +18 -0
  156. endoreg_db/models/lx/user.py +16 -0
  157. endoreg_db/models/medication/__init__.py +19 -1
  158. endoreg_db/models/medication/medication.py +7 -122
  159. endoreg_db/models/medication/medication_indication.py +50 -0
  160. endoreg_db/models/medication/medication_indication_type.py +34 -0
  161. endoreg_db/models/medication/medication_intake_time.py +26 -0
  162. endoreg_db/models/medication/medication_schedule.py +37 -0
  163. endoreg_db/models/network/__init__.py +7 -1
  164. endoreg_db/models/network/network_device.py +13 -8
  165. endoreg_db/models/organ/__init__.py +38 -0
  166. endoreg_db/models/other/__init__.py +19 -1
  167. endoreg_db/models/other/distribution/__init__.py +44 -0
  168. endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
  169. endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
  170. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
  171. endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
  172. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
  173. endoreg_db/models/other/distribution.py +1 -211
  174. endoreg_db/models/other/material.py +4 -0
  175. endoreg_db/models/other/transport_route.py +2 -1
  176. endoreg_db/models/patient/__init__.py +24 -0
  177. endoreg_db/models/patient/patient_examination.py +182 -0
  178. endoreg_db/models/patient/patient_finding.py +143 -0
  179. endoreg_db/models/patient/patient_finding_intervention.py +26 -0
  180. endoreg_db/models/patient/patient_finding_location.py +120 -0
  181. endoreg_db/models/patient/patient_finding_morphology.py +166 -0
  182. endoreg_db/models/persons/__init__.py +29 -2
  183. endoreg_db/models/persons/examiner/examiner.py +48 -4
  184. endoreg_db/models/persons/patient/__init__.py +1 -1
  185. endoreg_db/models/persons/patient/patient.py +227 -54
  186. endoreg_db/models/persons/patient/patient_disease.py +6 -0
  187. endoreg_db/models/persons/patient/patient_event.py +31 -1
  188. endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
  189. endoreg_db/models/persons/patient/patient_lab_sample.py +4 -2
  190. endoreg_db/models/persons/patient/patient_lab_value.py +37 -16
  191. endoreg_db/models/persons/patient/patient_medication.py +27 -12
  192. endoreg_db/models/persons/patient/patient_medication_schedule.py +62 -2
  193. endoreg_db/models/prediction/__init__.py +7 -1
  194. endoreg_db/models/prediction/image_classification.py +20 -6
  195. endoreg_db/models/prediction/video_prediction_meta.py +151 -89
  196. endoreg_db/models/product/__init__.py +10 -1
  197. endoreg_db/models/product/product.py +15 -2
  198. endoreg_db/models/product/product_group.py +8 -0
  199. endoreg_db/models/product/product_material.py +4 -0
  200. endoreg_db/models/product/product_weight.py +12 -0
  201. endoreg_db/models/product/reference_product.py +19 -3
  202. endoreg_db/models/quiz/__init__.py +8 -1
  203. endoreg_db/models/report_reader/__init__.py +6 -1
  204. endoreg_db/serializers/__init__.py +1 -1
  205. endoreg_db/serializers/annotation.py +2 -5
  206. endoreg_db/serializers/frame.py +1 -5
  207. endoreg_db/serializers/patient.py +26 -3
  208. endoreg_db/serializers/prediction.py +2 -7
  209. endoreg_db/serializers/raw_video_meta_validation.py +13 -0
  210. endoreg_db/serializers/video.py +6 -13
  211. endoreg_db/serializers/video_segmentation.py +492 -0
  212. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  213. endoreg_db/templates/admin/start_examination.html +12 -0
  214. endoreg_db/templates/timeline.html +176 -0
  215. endoreg_db/urls.py +173 -0
  216. endoreg_db/utils/__init__.py +36 -1
  217. endoreg_db/utils/dataloader.py +45 -19
  218. endoreg_db/utils/dates.py +39 -0
  219. endoreg_db/utils/hashs.py +122 -4
  220. endoreg_db/utils/names.py +74 -0
  221. endoreg_db/utils/parse_and_generate_yaml.py +46 -0
  222. endoreg_db/utils/pydantic_models/__init__.py +6 -0
  223. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  224. endoreg_db/utils/validate_endo_roi.py +19 -0
  225. endoreg_db/utils/validate_subcategory_dict.py +91 -0
  226. endoreg_db/utils/video/__init__.py +13 -0
  227. endoreg_db/utils/video/extract_frames.py +121 -0
  228. endoreg_db/utils/video/transcode_videofile.py +111 -0
  229. endoreg_db/views/__init__.py +2 -0
  230. endoreg_db/views/csrf.py +7 -0
  231. endoreg_db/views/patient_views.py +90 -0
  232. endoreg_db/views/raw_video_meta_validation_views.py +38 -0
  233. endoreg_db/views/report_views.py +96 -0
  234. endoreg_db/views/video_segmentation_views.py +149 -0
  235. endoreg_db/views/views_for_timeline.py +46 -0
  236. endoreg_db/views.py +0 -3
  237. endoreg_db-0.6.1.dist-info/METADATA +151 -0
  238. endoreg_db-0.6.1.dist-info/RECORD +420 -0
  239. {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/WHEEL +1 -1
  240. endoreg_db/data/active_model/data.yaml +0 -3
  241. endoreg_db/data/label/label-set/data.yaml +0 -18
  242. endoreg_db/management/commands/delete_legacy_images.py +0 -19
  243. endoreg_db/management/commands/delete_legacy_videos.py +0 -17
  244. endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
  245. endoreg_db/management/commands/import_legacy_images.py +0 -94
  246. endoreg_db/management/commands/import_legacy_videos.py +0 -76
  247. endoreg_db/management/commands/load_label_data.py +0 -67
  248. endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
  249. endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
  250. endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
  251. endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
  252. endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
  253. endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
  254. endoreg_db/migrations/0008_networkdevicelogentry_aglnet_ip_and_more.py +0 -28
  255. endoreg_db/migrations/0009_alter_networkdevicelogentry_vpn_service_status.py +0 -18
  256. endoreg_db/migrations/0010_remove_networkdevicelogentry_hostname.py +0 -17
  257. endoreg_db/models/legacy_data/__init__.py +0 -3
  258. endoreg_db/models/legacy_data/image.py +0 -34
  259. endoreg_db/models/patient_examination/__init__.py +0 -35
  260. endoreg_db/utils/video_metadata.py +0 -87
  261. endoreg_db-0.5.3.dist-info/METADATA +0 -28
  262. endoreg_db-0.5.3.dist-info/RECORD +0 -319
  263. /endoreg_db/{models/persons/patient/case → case_generator}/__init__.py +0 -0
  264. /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
  265. /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
  266. /endoreg_db/{data/distribution/numeric/.init → management/__init__.py} +0 -0
  267. /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
  268. {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
@@ -1 +1,36 @@
1
- from .dataloader import load_model_data_from_yaml
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
+ ]