endoreg-db 0.8.3.8__py3-none-any.whl → 0.8.4.0__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.

@@ -50,11 +50,17 @@ class Command(BaseCommand):
50
50
 
51
51
  try:
52
52
  # Download the model weights
53
- weights_path = hf_hub_download(repo_id=model_id, filename="pytorch_model.bin", local_dir="/tmp")
53
+ weights_path = hf_hub_download(
54
+ repo_id=model_id,
55
+ filename="colo_segmentation_RegNetX800MF_base.ckpt",
56
+ local_dir="/tmp",
57
+ )
54
58
  self.stdout.write(f"Downloaded weights to: {weights_path}")
55
59
 
56
60
  # Get or create AI model
57
- ai_model, created = AiModel.objects.get_or_create(name=model_name, defaults={"description": f"Model from {model_id}"})
61
+ ai_model, created = AiModel.objects.get_or_create(
62
+ name=model_name, defaults={"description": f"Model from {model_id}"}
63
+ )
58
64
  if created:
59
65
  self.stdout.write(f"Created AI model: {ai_model.name}")
60
66
 
@@ -62,7 +68,9 @@ class Command(BaseCommand):
62
68
  try:
63
69
  labelset = LabelSet.objects.get(name=labelset_name)
64
70
  except LabelSet.DoesNotExist:
65
- self.stdout.write(self.style.ERROR(f"LabelSet '{labelset_name}' not found"))
71
+ self.stdout.write(
72
+ self.style.ERROR(f"LabelSet '{labelset_name}' not found")
73
+ )
66
74
  return
67
75
 
68
76
  # Create ModelMeta
@@ -86,13 +94,19 @@ class Command(BaseCommand):
86
94
 
87
95
  # Save the weights file to the model
88
96
  with open(weights_path, "rb") as f:
89
- model_meta.weights.save(f"{model_name}_v{version}_pytorch_model.bin", ContentFile(f.read()))
97
+ model_meta.weights.save(
98
+ f"{model_name}_v{version}_pytorch_model.bin", ContentFile(f.read())
99
+ )
90
100
 
91
101
  # Set as active meta
92
102
  ai_model.active_meta = model_meta
93
103
  ai_model.save()
94
104
 
95
- self.stdout.write(self.style.SUCCESS(f"Successfully {'created' if created else 'updated'} ModelMeta: {model_meta}"))
105
+ self.stdout.write(
106
+ self.style.SUCCESS(
107
+ f"Successfully {'created' if created else 'updated'} ModelMeta: {model_meta}"
108
+ )
109
+ )
96
110
 
97
111
  except Exception as e:
98
112
  self.stdout.write(self.style.ERROR(f"Error creating ModelMeta: {e}"))
@@ -1,21 +1,21 @@
1
1
  import shutil
2
+ from logging import getLogger
2
3
  from pathlib import Path
3
- from typing import Optional, TYPE_CHECKING, Any, Type
4
- from huggingface_hub import hf_hub_download
4
+ from typing import TYPE_CHECKING, Any, Optional, Type
5
+
5
6
  from django.db import transaction
7
+ from huggingface_hub import hf_hub_download
6
8
 
7
9
  # Assuming ModelMeta, AiModel, LabelSet are importable from the correct locations
8
10
  # Adjust imports based on your project structure if necessary
9
11
  from ..administration.ai.ai_model import AiModel
10
12
  from ..label.label_set import LabelSet
11
- from ..utils import WEIGHTS_DIR, STORAGE_DIR
12
-
13
- from logging import getLogger
13
+ from ..utils import STORAGE_DIR, WEIGHTS_DIR
14
14
 
15
15
  logger = getLogger("ai_model")
16
16
 
17
17
  if TYPE_CHECKING:
18
- from .model_meta import ModelMeta # Import ModelMeta for type hinting
18
+ from .model_meta import ModelMeta # Import ModelMeta for type hinting
19
19
 
20
20
 
21
21
  def get_latest_version_number_logic(
@@ -29,13 +29,13 @@ def get_latest_version_number_logic(
29
29
  """
30
30
  versions_qs = cls.objects.filter(
31
31
  name=meta_name, model__name=model_name
32
- ).values_list('version', flat=True)
32
+ ).values_list("version", flat=True)
33
33
 
34
34
  max_v = 0
35
35
  found_numeric_version = False
36
36
 
37
37
  for v_str in versions_qs:
38
- if v_str is None: # Skip None versions
38
+ if v_str is None: # Skip None versions
39
39
  continue
40
40
  try:
41
41
  v_int = int(v_str)
@@ -47,13 +47,13 @@ def get_latest_version_number_logic(
47
47
  f"Warning: Could not parse version string '{v_str}' as an integer for "
48
48
  f"meta_name='{meta_name}', model_name='{model_name}' while determining the max version."
49
49
  )
50
-
50
+
51
51
  return max_v if found_numeric_version else 0
52
52
 
53
53
 
54
54
  @transaction.atomic
55
55
  def create_from_file_logic(
56
- cls: Type["ModelMeta"], # cls is ModelMeta
56
+ cls: Type["ModelMeta"], # cls is ModelMeta
57
57
  meta_name: str,
58
58
  model_name: str,
59
59
  labelset_name: str,
@@ -94,11 +94,14 @@ def create_from_file_logic(
94
94
  )
95
95
  elif existing and bump_if_exists:
96
96
  target_version = str(latest_version_num + 1)
97
- logger.info(f"Bumping version for {meta_name}/{model_name} to {target_version}")
97
+ logger.info(
98
+ f"Bumping version for {meta_name}/{model_name} to {target_version}"
99
+ )
98
100
  else:
99
101
  target_version = str(latest_version_num + 1)
100
- logger.info(f"Setting next version for {meta_name}/{model_name} to {target_version}")
101
-
102
+ logger.info(
103
+ f"Setting next version for {meta_name}/{model_name} to {target_version}"
104
+ )
102
105
 
103
106
  # --- Prepare Weights File ---
104
107
  source_weights_path = Path(weights_file).resolve()
@@ -108,7 +111,10 @@ def create_from_file_logic(
108
111
  # Construct destination path within MEDIA_ROOT/WEIGHTS_DIR
109
112
  weights_filename = source_weights_path.name
110
113
  # Relative path for the FileField upload_to
111
- relative_dest_path = Path(WEIGHTS_DIR.relative_to(STORAGE_DIR)) / f"{meta_name}_v{target_version}_{weights_filename}"
114
+ relative_dest_path = (
115
+ Path(WEIGHTS_DIR.relative_to(STORAGE_DIR))
116
+ / f"{meta_name}_v{target_version}_{weights_filename}"
117
+ )
112
118
  # Full path for shutil.copy
113
119
  full_dest_path = STORAGE_DIR / relative_dest_path
114
120
 
@@ -125,8 +131,8 @@ def create_from_file_logic(
125
131
  # --- Create/Update ModelMeta Instance ---
126
132
  defaults = {
127
133
  "labelset": label_set,
128
- "weights": relative_dest_path.as_posix(), # Store relative path for FileField
129
- **kwargs, # Pass through other fields like activation, mean, std, etc.
134
+ "weights": relative_dest_path.as_posix(), # Store relative path for FileField
135
+ **kwargs, # Pass through other fields like activation, mean, std, etc.
130
136
  }
131
137
 
132
138
  # Remove None values from defaults to avoid overriding model defaults unnecessarily
@@ -152,35 +158,39 @@ def create_from_file_logic(
152
158
 
153
159
  return model_meta
154
160
 
161
+
155
162
  # --- Add other logic functions referenced by ModelMeta here ---
156
163
  # (get_latest_version_number_logic, get_activation_function_logic, etc.)
157
164
  # Placeholder for get_activation_function_logic
158
165
  def get_activation_function_logic(activation_name: str):
159
- import torch.nn as nn # Import locally as it's specific to this function
166
+ import torch.nn as nn # Import locally as it's specific to this function
167
+
160
168
  if activation_name.lower() == "sigmoid":
161
169
  return nn.Sigmoid()
162
170
  elif activation_name.lower() == "softmax":
163
171
  # Note: Softmax usually requires specifying the dimension
164
- return nn.Softmax(dim=1) # Assuming dim=1 (channels) is common
172
+ return nn.Softmax(dim=1) # Assuming dim=1 (channels) is common
165
173
  elif activation_name.lower() == "none":
166
174
  return nn.Identity()
167
175
  else:
168
176
  # Consider adding more activations or raising an error
169
177
  raise ValueError(f"Unsupported activation function: {activation_name}")
170
178
 
179
+
171
180
  # Placeholder for get_inference_dataset_config_logic
172
181
  def get_inference_dataset_config_logic(model_meta: "ModelMeta") -> dict:
173
182
  # This would typically extract relevant fields from model_meta
174
183
  # for configuring a dataset during inference
175
184
  return {
176
- "mean": [float(x) for x in model_meta.mean.split(',')],
177
- "std": [float(x) for x in model_meta.std.split(',')],
178
- "size_y": model_meta.size_y, # Add size_y key
179
- "size_x": model_meta.size_x, # Add size_x key
180
- "axes": [int(x) for x in model_meta.axes.split(',')],
185
+ "mean": [float(x) for x in model_meta.mean.split(",")],
186
+ "std": [float(x) for x in model_meta.std.split(",")],
187
+ "size_y": model_meta.size_y, # Add size_y key
188
+ "size_x": model_meta.size_x, # Add size_x key
189
+ "axes": [int(x) for x in model_meta.axes.split(",")],
181
190
  # Add other relevant config like normalization type, etc.
182
191
  }
183
192
 
193
+
184
194
  # Placeholder for get_config_dict_logic
185
195
  def get_config_dict_logic(model_meta: "ModelMeta") -> dict:
186
196
  # Returns a dictionary representation of the model's configuration
@@ -202,6 +212,7 @@ def get_config_dict_logic(model_meta: "ModelMeta") -> dict:
202
212
  # Add any other relevant fields
203
213
  }
204
214
 
215
+
205
216
  # Placeholder for get_model_meta_by_name_version_logic
206
217
  def get_model_meta_by_name_version_logic(
207
218
  cls: Type["ModelMeta"],
@@ -227,17 +238,24 @@ def get_model_meta_by_name_version_logic(
227
238
  ) from exc
228
239
  else:
229
240
  # Get latest version
230
- latest = cls.objects.filter(name=meta_name, model=ai_model).order_by("-date_created").first()
241
+ latest = (
242
+ cls.objects.filter(name=meta_name, model=ai_model)
243
+ .order_by("-date_created")
244
+ .first()
245
+ )
231
246
  if latest:
232
247
  return latest
233
248
  else:
234
249
  raise cls.DoesNotExist(
235
250
  f"No ModelMeta found for '{meta_name}' and model '{model_name}'."
236
251
  )
237
-
238
- from huggingface_hub import model_info
252
+
253
+
239
254
  import re
240
255
 
256
+ from huggingface_hub import model_info
257
+
258
+
241
259
  def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
242
260
  """
243
261
  Infers default model metadata (activation, normalization, input size)
@@ -248,7 +266,9 @@ def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
248
266
  """
249
267
 
250
268
  if not (info := model_info(model_id)):
251
- logger.info(f"Could not retrieve model info for {model_id}, using ColoReg segmentation defaults.")
269
+ logger.info(
270
+ f"Could not retrieve model info for {model_id}, using ColoReg segmentation defaults."
271
+ )
252
272
  return {
253
273
  "name": "wg-lux/colo_segmentation_RegNetX800MF_base",
254
274
  "activation": "sigmoid",
@@ -295,18 +315,29 @@ def infer_default_model_meta_from_hf(model_id: str) -> dict[str, Any]:
295
315
  "size_y": size_y,
296
316
  "description": f"Inferred defaults for {model_id}",
297
317
  }
298
-
299
- def setup_default_from_huggingface_logic(cls, model_id: str, labelset_name: str | None = None):
318
+
319
+
320
+ def setup_default_from_huggingface_logic(
321
+ cls, model_id: str, labelset_name: str | None = None
322
+ ):
300
323
  """
301
324
  Downloads model weights from Hugging Face and auto-fills ModelMeta fields.
302
325
  """
303
326
  meta = infer_default_model_meta_from_hf(model_id)
304
327
 
305
328
  # Download weights
306
- weights_path = hf_hub_download(repo_id=model_id, filename="pytorch_model.bin", local_dir=WEIGHTS_DIR)
329
+ weights_path = hf_hub_download(
330
+ repo_id=model_id,
331
+ filename="colo_segmentation_RegNetX800MF_base.ckpt",
332
+ local_dir=WEIGHTS_DIR,
333
+ )
307
334
 
308
335
  ai_model, _ = AiModel.objects.get_or_create(name=meta["name"])
309
- labelset = LabelSet.objects.first() if not labelset_name else LabelSet.objects.get(name=labelset_name)
336
+ labelset = (
337
+ LabelSet.objects.first()
338
+ if not labelset_name
339
+ else LabelSet.objects.get(name=labelset_name)
340
+ )
310
341
 
311
342
  return create_from_file_logic(
312
343
  cls,
@@ -55,7 +55,18 @@ class VideoImportService():
55
55
  self.project_root = Path(__file__).parent.parent.parent.parent
56
56
 
57
57
  # Track processed files to prevent duplicates
58
- self.processed_files = set(str(Path(ANONYM_VIDEO_DIR) / file) for file in os.listdir(ANONYM_VIDEO_DIR))
58
+ try:
59
+ # Ensure anonym_video directory exists before listing files
60
+ anonym_video_dir = Path(ANONYM_VIDEO_DIR)
61
+ if anonym_video_dir.exists():
62
+ self.processed_files = set(str(anonym_video_dir / file) for file in os.listdir(ANONYM_VIDEO_DIR))
63
+ else:
64
+ logger.info(f"Creating anonym_videos directory: {anonym_video_dir}")
65
+ anonym_video_dir.mkdir(parents=True, exist_ok=True)
66
+ self.processed_files = set()
67
+ except Exception as e:
68
+ logger.warning(f"Failed to initialize processed files tracking: {e}")
69
+ self.processed_files = set()
59
70
 
60
71
  # Central video instance and processing context
61
72
  self.current_video: Optional[VideoFile] = None
@@ -146,6 +157,9 @@ class VideoImportService():
146
157
  High-level helper that orchestrates the complete video import and anonymization process.
147
158
  Uses the central video instance pattern for improved state management.
148
159
  """
160
+ # DEFENSIVE: Initialize processing_context immediately to prevent KeyError crashes
161
+ self.processing_context = {'file_path': Path(file_path)}
162
+
149
163
  try:
150
164
  # Initialize processing context
151
165
  self._initialize_processing_context(file_path, center_name, processor_name,
@@ -182,7 +196,12 @@ class VideoImportService():
182
196
  return self.current_video
183
197
 
184
198
  except Exception as e:
185
- self.logger.error(f"Video import and anonymization failed for {file_path}: {e}")
199
+ # Safe file path access - handles cases where processing_context wasn't initialized
200
+ safe_file_path = getattr(self, 'processing_context', {}).get('file_path', file_path)
201
+ # Debug: Log context state for troubleshooting
202
+ context_keys = list(getattr(self, 'processing_context', {}).keys())
203
+ self.logger.debug(f"Context keys during error: {context_keys}")
204
+ self.logger.error(f"Video import and anonymization failed for {safe_file_path}: {e}")
186
205
  self._cleanup_on_error()
187
206
  raise
188
207
  finally:
@@ -969,6 +988,10 @@ class VideoImportService():
969
988
  This method is always called in the finally block of import_and_anonymize()
970
989
  to ensure the file lock is released even if processing fails.
971
990
  """
991
+ # DEFENSIVE: Ensure processing_context exists before accessing it
992
+ if not hasattr(self, 'processing_context'):
993
+ self.processing_context = {}
994
+
972
995
  try:
973
996
  # Release file lock if it was acquired
974
997
  lock_context = self.processing_context.get('_lock_context')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: endoreg-db
3
- Version: 0.8.3.8
3
+ Version: 0.8.4.0
4
4
  Summary: EndoReg Db Django App
5
5
  Project-URL: Homepage, https://info.coloreg.de
6
6
  Project-URL: Repository, https://github.com/wg-lux/endoreg-db
@@ -248,7 +248,7 @@ endoreg_db/management/__init__.py,sha256=3dsK9Mizq1veuWTcvSOyWMFT9VI8wtyk-P2K9Ri
248
248
  endoreg_db/management/commands/__init__.py,sha256=Ch0jwQfNpOSr4O5KKMfYJ93dsesk1Afb-JtbRVyFXZs,21
249
249
  endoreg_db/management/commands/anonymize_video.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
250
  endoreg_db/management/commands/check_auth.py,sha256=TPiYeCZ5QcqIvR33xhbqXunO2nrcNAmHb_izoMTqgpg,5390
251
- endoreg_db/management/commands/create_model_meta_from_huggingface.py,sha256=enZiNBi3wKLnOwdCp6nV3EDLrkK50KVEn6urgblNVjw,3621
251
+ endoreg_db/management/commands/create_model_meta_from_huggingface.py,sha256=NeTAl35RLI4Fad5V1W3ohyzuOl0LEzevlVRyLLeXrJM,3881
252
252
  endoreg_db/management/commands/create_multilabel_model_meta.py,sha256=qeoyqcF2CWcnhniVRrlYbmJmwNwyZb-VQ0pjkr6arJU,7566
253
253
  endoreg_db/management/commands/fix_missing_patient_data.py,sha256=5TPUTOQwI2fVh3Zd88o4ne0R8N_V98k0GZsI1gW0kGM,7766
254
254
  endoreg_db/management/commands/fix_video_paths.py,sha256=7LLwc38oX3B_tYWbLJA43Li_KBO3m5Lyw0CF6YqN5rU,7145
@@ -464,7 +464,7 @@ endoreg_db/models/medical/risk/risk_type.py,sha256=kEugcaWSTEWH_Vxq4dcF80Iv1L4_K
464
464
  endoreg_db/models/metadata/__init__.py,sha256=8I6oLj3YTmeaPGJpL0AWG5gLwp38QzrEggxSkTisv7c,474
465
465
  endoreg_db/models/metadata/frame_ocr_result.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
466
466
  endoreg_db/models/metadata/model_meta.py,sha256=F_r-PTLeNi4J-4EaGCQkGIguhdl7Bwba7_i56ZAjc-4,7589
467
- endoreg_db/models/metadata/model_meta_logic.py,sha256=27mqScxUTJXNUVc6CqAs5dXjspEsh0TWPmlxdJVulGc,12015
467
+ endoreg_db/models/metadata/model_meta_logic.py,sha256=6w1YX8hVq40UXbVN1fvDO9OljwekBZaDVHEjVZecoV8,12252
468
468
  endoreg_db/models/metadata/pdf_meta.py,sha256=BTmpSgqxmPKi0apcNjyrZAS4AFKCPXVdBd6VBeyyv6E,3174
469
469
  endoreg_db/models/metadata/sensitive_meta.py,sha256=ekLHrW-b5uYcjfkRd0EW5ncx5ef8Bu-K6msDkpWCAbk,13034
470
470
  endoreg_db/models/metadata/sensitive_meta_logic.py,sha256=by3eCW8CgglK1SHiDOepHhTOGaugswxJhkH0BZp7-gs,33909
@@ -602,7 +602,7 @@ endoreg_db/services/pseudonym_service.py,sha256=CJhbtRa6K6SPbphgCZgEMi8AFQtB18CU
602
602
  endoreg_db/services/requirements_object.py,sha256=290zf8AEbVtCoHhW4Jr7_ud-RvrqYmb1Nz9UBHtTnc0,6164
603
603
  endoreg_db/services/segment_sync.py,sha256=YgHvIHkbW4mqCu0ACf3zjRSZnNfxWwt4gh5syUVXuE0,6400
604
604
  endoreg_db/services/storage_aware_video_processor.py,sha256=kKFK64vXLeBSVkp1YJonU3gFDTeXZ8C4qb9QZZB99SE,13420
605
- endoreg_db/services/video_import.py,sha256=PNAHHZHzge2TYDaZP63CL-sslj01CxFky6sEi6Twavg,46045
605
+ endoreg_db/services/video_import.py,sha256=5a73s0Au0kgZFbrsD4WUqmDAqhQmuf9_wqs79SI-byE,47356
606
606
  endoreg_db/tasks/upload_tasks.py,sha256=OJq7DhNwcbWdXzHY8jz5c51BCVkPN5gSWOz-6Fx6W5M,7799
607
607
  endoreg_db/tasks/video_ingest.py,sha256=kxFuYkHijINV0VabQKCFVpJRv6eCAw07tviONurDgg8,5265
608
608
  endoreg_db/tasks/video_processing_tasks.py,sha256=rZ7Kr49bAR4Q-vALO2SURebrhcJ5hSFGwjF4aULrOao,14089
@@ -786,7 +786,7 @@ endoreg_db/views/video/video_meta.py,sha256=C1wBMTtQb_yzEUrhFGAy2UHEWMk_CbU75WXX
786
786
  endoreg_db/views/video/video_processing_history.py,sha256=mhFuS8RG5GV8E-lTtuD0qrq-bIpnUFp8vy9aERfC-J8,770
787
787
  endoreg_db/views/video/video_remove_frames.py,sha256=2FmvNrSPM0fUXiBxINN6vBUUDCqDlBkNcGR3WsLDgKo,1696
788
788
  endoreg_db/views/video/video_stream.py,sha256=kLyuf0ORTmsLeYUQkTQ6iRYqlIQozWhMMR3Lhfe_trk,12148
789
- endoreg_db-0.8.3.8.dist-info/METADATA,sha256=4evIJXXr-HVMvN07sn2wZ0MXR3LujkKoOPF7os_3Bbg,14758
790
- endoreg_db-0.8.3.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
- endoreg_db-0.8.3.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
792
- endoreg_db-0.8.3.8.dist-info/RECORD,,
789
+ endoreg_db-0.8.4.0.dist-info/METADATA,sha256=VbEZv_ib_RgBN6I8T17X0e49fU7YYrZOBe24nL4u7ig,14758
790
+ endoreg_db-0.8.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
+ endoreg_db-0.8.4.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
792
+ endoreg_db-0.8.4.0.dist-info/RECORD,,