endoreg-db 0.8.3.3__py3-none-any.whl → 0.8.6.5__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/data/ai_model_meta/default_multilabel_classification.yaml +23 -1
- endoreg_db/data/setup_config.yaml +38 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +1 -2
- endoreg_db/management/commands/load_ai_model_data.py +18 -15
- endoreg_db/management/commands/setup_endoreg_db.py +218 -33
- endoreg_db/models/media/pdf/raw_pdf.py +241 -97
- endoreg_db/models/media/video/pipe_1.py +30 -33
- endoreg_db/models/media/video/video_file.py +300 -187
- endoreg_db/models/medical/hardware/endoscopy_processor.py +10 -1
- endoreg_db/models/metadata/model_meta_logic.py +34 -45
- endoreg_db/models/metadata/sensitive_meta_logic.py +555 -150
- endoreg_db/serializers/__init__.py +26 -55
- endoreg_db/serializers/misc/__init__.py +1 -1
- endoreg_db/serializers/misc/file_overview.py +65 -35
- endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/lookup_service.py +228 -58
- endoreg_db/services/lookup_store.py +174 -30
- endoreg_db/services/pdf_import.py +585 -282
- endoreg_db/services/video_import.py +493 -240
- endoreg_db/urls/__init__.py +36 -23
- endoreg_db/urls/label_video_segments.py +2 -0
- endoreg_db/urls/media.py +103 -66
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/views/__init__.py +5 -3
- endoreg_db/views/media/pdf_media.py +3 -1
- endoreg_db/views/media/video_media.py +1 -1
- endoreg_db/views/media/video_segments.py +187 -259
- endoreg_db/views/pdf/__init__.py +5 -8
- endoreg_db/views/pdf/pdf_stream.py +186 -0
- endoreg_db/views/pdf/reimport.py +110 -94
- endoreg_db/views/requirement/lookup.py +171 -287
- endoreg_db/views/video/__init__.py +0 -2
- endoreg_db/views/video/video_examination_viewset.py +202 -289
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/METADATA +1 -2
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/RECORD +38 -37
- endoreg_db/views/pdf/pdf_media.py +0 -239
- endoreg_db/views/pdf/pdf_stream_views.py +0 -127
- endoreg_db/views/video/video_media.py +0 -158
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -160,7 +160,7 @@ class EndoscopyProcessor(models.Model):
|
|
|
160
160
|
"height": self.endoscope_sn_height,
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
def get_rois(self) -> dict[
|
|
163
|
+
def get_rois(self) -> dict[str, dict[str, int | None] | None]:
|
|
164
164
|
return {
|
|
165
165
|
"endoscope_image": self.get_roi_endoscope_image(),
|
|
166
166
|
"examination_date": self.get_roi_examination_date(),
|
|
@@ -171,3 +171,12 @@ class EndoscopyProcessor(models.Model):
|
|
|
171
171
|
"endoscope_type": self.get_roi_endoscope_type(),
|
|
172
172
|
"endoscope_sn": self.get_roi_endoscopy_sn(),
|
|
173
173
|
}
|
|
174
|
+
|
|
175
|
+
def get_sensitive_rois(self) -> dict[str, dict[str, int | None] | None]:
|
|
176
|
+
return {
|
|
177
|
+
"examination_date": self.get_roi_examination_date(),
|
|
178
|
+
"examination_time": self.get_roi_examination_time(),
|
|
179
|
+
"patient_first_name": self.get_roi_patient_first_name(),
|
|
180
|
+
"patient_last_name": self.get_roi_patient_last_name(),
|
|
181
|
+
"patient_dob": self.get_roi_patient_dob(),
|
|
182
|
+
}
|
|
@@ -3,6 +3,7 @@ from logging import getLogger
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import TYPE_CHECKING, Any, Optional, Type
|
|
5
5
|
|
|
6
|
+
from django.core.files import File
|
|
6
7
|
from django.db import transaction
|
|
7
8
|
from huggingface_hub import hf_hub_download
|
|
8
9
|
|
|
@@ -18,18 +19,21 @@ if TYPE_CHECKING:
|
|
|
18
19
|
from .model_meta import ModelMeta # Import ModelMeta for type hinting
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
def _get_model_meta_class():
|
|
23
|
+
"""Lazy import to avoid circular imports"""
|
|
24
|
+
from .model_meta import ModelMeta
|
|
25
|
+
|
|
26
|
+
return ModelMeta
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_latest_version_number_logic(cls: Type["ModelMeta"], meta_name: str, model_name: str) -> int:
|
|
24
30
|
"""
|
|
25
31
|
Finds the highest numerical version for a given meta_name and model_name.
|
|
26
32
|
Iterates through all versions, attempts to parse them as integers,
|
|
27
33
|
and returns the maximum integer found. If no numeric versions are found,
|
|
28
34
|
returns 0.
|
|
29
35
|
"""
|
|
30
|
-
versions_qs = cls.objects.filter(
|
|
31
|
-
name=meta_name, model__name=model_name
|
|
32
|
-
).values_list("version", flat=True)
|
|
36
|
+
versions_qs = cls.objects.filter(name=meta_name, model__name=model_name).values_list("version", flat=True)
|
|
33
37
|
|
|
34
38
|
max_v = 0
|
|
35
39
|
found_numeric_version = False
|
|
@@ -84,24 +88,17 @@ def create_from_file_logic(
|
|
|
84
88
|
|
|
85
89
|
if requested_version:
|
|
86
90
|
target_version = str(requested_version)
|
|
87
|
-
existing = cls.objects.filter(
|
|
88
|
-
name=meta_name, model=ai_model, version=target_version
|
|
89
|
-
).first()
|
|
91
|
+
existing = cls.objects.filter(name=meta_name, model=ai_model, version=target_version).first()
|
|
90
92
|
if existing and not bump_if_exists:
|
|
91
93
|
raise ValueError(
|
|
92
|
-
f"ModelMeta '{meta_name}' version '{target_version}' for model '{model_name}' "
|
|
93
|
-
f"already exists. Use bump_if_exists=True to increment."
|
|
94
|
+
f"ModelMeta '{meta_name}' version '{target_version}' for model '{model_name}' already exists. Use bump_if_exists=True to increment."
|
|
94
95
|
)
|
|
95
96
|
elif existing and bump_if_exists:
|
|
96
97
|
target_version = str(latest_version_num + 1)
|
|
97
|
-
logger.info(
|
|
98
|
-
f"Bumping version for {meta_name}/{model_name} to {target_version}"
|
|
99
|
-
)
|
|
98
|
+
logger.info(f"Bumping version for {meta_name}/{model_name} to {target_version}")
|
|
100
99
|
else:
|
|
101
100
|
target_version = str(latest_version_num + 1)
|
|
102
|
-
logger.info(
|
|
103
|
-
f"Setting next version for {meta_name}/{model_name} to {target_version}"
|
|
104
|
-
)
|
|
101
|
+
logger.info(f"Setting next version for {meta_name}/{model_name} to {target_version}")
|
|
105
102
|
|
|
106
103
|
# --- Prepare Weights File ---
|
|
107
104
|
source_weights_path = Path(weights_file).resolve()
|
|
@@ -111,10 +108,7 @@ def create_from_file_logic(
|
|
|
111
108
|
# Construct destination path within MEDIA_ROOT/WEIGHTS_DIR
|
|
112
109
|
weights_filename = source_weights_path.name
|
|
113
110
|
# Relative path for the FileField upload_to
|
|
114
|
-
relative_dest_path = (
|
|
115
|
-
Path(WEIGHTS_DIR.relative_to(STORAGE_DIR))
|
|
116
|
-
/ f"{meta_name}_v{target_version}_{weights_filename}"
|
|
117
|
-
)
|
|
111
|
+
relative_dest_path = Path(WEIGHTS_DIR.relative_to(STORAGE_DIR)) / f"{meta_name}_v{target_version}_{weights_filename}"
|
|
118
112
|
# Full path for shutil.copy
|
|
119
113
|
full_dest_path = STORAGE_DIR / relative_dest_path
|
|
120
114
|
|
|
@@ -153,8 +147,8 @@ def create_from_file_logic(
|
|
|
153
147
|
# --- Optionally update AiModel's active_meta ---
|
|
154
148
|
# You might want to add logic here to automatically set the newly created/updated
|
|
155
149
|
# meta as the active one for the AiModel, e.g.:
|
|
156
|
-
|
|
157
|
-
|
|
150
|
+
ai_model.active_meta = model_meta
|
|
151
|
+
ai_model.save()
|
|
158
152
|
|
|
159
153
|
return model_meta
|
|
160
154
|
|
|
@@ -233,22 +227,14 @@ def get_model_meta_by_name_version_logic(
|
|
|
233
227
|
try:
|
|
234
228
|
return cls.objects.get(name=meta_name, model=ai_model, version=version)
|
|
235
229
|
except Exception as exc:
|
|
236
|
-
raise cls.DoesNotExist(
|
|
237
|
-
f"ModelMeta '{meta_name}' version '{version}' for model '{model_name}' not found."
|
|
238
|
-
) from exc
|
|
230
|
+
raise cls.DoesNotExist(f"ModelMeta '{meta_name}' version '{version}' for model '{model_name}' not found.") from exc
|
|
239
231
|
else:
|
|
240
232
|
# Get latest version
|
|
241
|
-
latest = (
|
|
242
|
-
cls.objects.filter(name=meta_name, model=ai_model)
|
|
243
|
-
.order_by("-date_created")
|
|
244
|
-
.first()
|
|
245
|
-
)
|
|
233
|
+
latest = cls.objects.filter(name=meta_name, model=ai_model).order_by("-date_created").first()
|
|
246
234
|
if latest:
|
|
247
235
|
return latest
|
|
248
236
|
else:
|
|
249
|
-
raise cls.DoesNotExist(
|
|
250
|
-
f"No ModelMeta found for '{meta_name}' and model '{model_name}'."
|
|
251
|
-
)
|
|
237
|
+
raise cls.DoesNotExist(f"No ModelMeta found for '{meta_name}' and model '{model_name}'.")
|
|
252
238
|
|
|
253
239
|
|
|
254
240
|
import re
|
|
@@ -266,9 +252,7 @@ def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
|
|
|
266
252
|
"""
|
|
267
253
|
|
|
268
254
|
if not (info := model_info(model_id)):
|
|
269
|
-
logger.info(
|
|
270
|
-
f"Could not retrieve model info for {model_id}, using ColoReg segmentation defaults."
|
|
271
|
-
)
|
|
255
|
+
logger.info(f"Could not retrieve model info for {model_id}, using ColoReg segmentation defaults.")
|
|
272
256
|
return {
|
|
273
257
|
"name": "wg-lux/colo_segmentation_RegNetX800MF_base",
|
|
274
258
|
"activation": "sigmoid",
|
|
@@ -317,9 +301,7 @@ def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
|
|
|
317
301
|
}
|
|
318
302
|
|
|
319
303
|
|
|
320
|
-
def setup_default_from_huggingface_logic(
|
|
321
|
-
cls, model_id: str, labelset_name: str | None = None
|
|
322
|
-
):
|
|
304
|
+
def setup_default_from_huggingface_logic(cls, model_id: str, labelset_name: str | None = None):
|
|
323
305
|
"""
|
|
324
306
|
Downloads model weights from Hugging Face and auto-fills ModelMeta fields.
|
|
325
307
|
"""
|
|
@@ -333,11 +315,18 @@ def setup_default_from_huggingface_logic(
|
|
|
333
315
|
)
|
|
334
316
|
|
|
335
317
|
ai_model, _ = AiModel.objects.get_or_create(name=meta["name"])
|
|
336
|
-
|
|
337
|
-
LabelSet.objects.first()
|
|
338
|
-
if not
|
|
339
|
-
|
|
340
|
-
|
|
318
|
+
if not labelset_name:
|
|
319
|
+
labelset = LabelSet.objects.first()
|
|
320
|
+
if not labelset:
|
|
321
|
+
raise ValueError("No labelset found and no labelset_name provided")
|
|
322
|
+
else:
|
|
323
|
+
labelset = LabelSet.objects.get(name=labelset_name)
|
|
324
|
+
|
|
325
|
+
ModelMeta = _get_model_meta_class()
|
|
326
|
+
model_meta = ModelMeta.objects.filter(name=meta["name"], model=ai_model).first()
|
|
327
|
+
if model_meta:
|
|
328
|
+
logger.info(f"ModelMeta {meta['name']} for model {ai_model.name} already exists. Skipping creation.")
|
|
329
|
+
return model_meta
|
|
341
330
|
|
|
342
331
|
return create_from_file_logic(
|
|
343
332
|
cls,
|