careamics 0.0.4.1__py3-none-any.whl → 0.0.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 careamics might be problematic. Click here for more details.

Files changed (43) hide show
  1. careamics/careamist.py +235 -25
  2. careamics/cli/conf.py +19 -30
  3. careamics/cli/main.py +111 -10
  4. careamics/cli/utils.py +29 -0
  5. careamics/config/__init__.py +2 -0
  6. careamics/config/architectures/lvae_model.py +104 -21
  7. careamics/config/configuration_factory.py +49 -45
  8. careamics/config/configuration_model.py +2 -2
  9. careamics/config/likelihood_model.py +7 -6
  10. careamics/config/loss_model.py +56 -0
  11. careamics/config/nm_model.py +24 -24
  12. careamics/config/vae_algorithm_model.py +14 -13
  13. careamics/dataset/dataset_utils/running_stats.py +22 -23
  14. careamics/lightning/lightning_module.py +58 -27
  15. careamics/lightning/train_data_module.py +15 -1
  16. careamics/losses/loss_factory.py +1 -85
  17. careamics/losses/lvae/losses.py +223 -164
  18. careamics/lvae_training/calibration.py +184 -0
  19. careamics/lvae_training/dataset/config.py +2 -2
  20. careamics/lvae_training/dataset/multich_dataset.py +11 -19
  21. careamics/lvae_training/dataset/multifile_dataset.py +3 -2
  22. careamics/lvae_training/dataset/types.py +15 -26
  23. careamics/lvae_training/dataset/utils/index_manager.py +4 -4
  24. careamics/lvae_training/eval_utils.py +125 -213
  25. careamics/model_io/bioimage/_readme_factory.py +25 -33
  26. careamics/model_io/bioimage/cover_factory.py +171 -0
  27. careamics/model_io/bioimage/model_description.py +35 -22
  28. careamics/model_io/bmz_io.py +36 -25
  29. careamics/models/layers.py +6 -4
  30. careamics/models/lvae/layers.py +348 -975
  31. careamics/models/lvae/likelihoods.py +10 -8
  32. careamics/models/lvae/lvae.py +214 -272
  33. careamics/models/lvae/noise_models.py +179 -112
  34. careamics/models/lvae/stochastic.py +393 -0
  35. careamics/models/lvae/utils.py +82 -73
  36. careamics/utils/lightning_utils.py +57 -0
  37. careamics/utils/serializers.py +2 -0
  38. careamics/utils/torch_utils.py +1 -1
  39. {careamics-0.0.4.1.dist-info → careamics-0.0.5.dist-info}/METADATA +12 -9
  40. {careamics-0.0.4.1.dist-info → careamics-0.0.5.dist-info}/RECORD +43 -37
  41. {careamics-0.0.4.1.dist-info → careamics-0.0.5.dist-info}/WHEEL +1 -1
  42. {careamics-0.0.4.1.dist-info → careamics-0.0.5.dist-info}/entry_points.txt +0 -0
  43. {careamics-0.0.4.1.dist-info → careamics-0.0.5.dist-info}/licenses/LICENSE +0 -0
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
  from typing import List, Optional, Tuple, Union
5
5
 
6
6
  import numpy as np
7
+ from bioimageio.spec._internal.io import resolve_and_extract
7
8
  from bioimageio.spec.model.v0_5 import (
8
9
  ArchitectureFromLibraryDescr,
9
10
  Author,
@@ -186,6 +187,7 @@ def create_model_description(
186
187
  config: Configuration,
187
188
  name: str,
188
189
  general_description: str,
190
+ data_description: str,
189
191
  authors: List[Author],
190
192
  inputs: Union[Path, str],
191
193
  outputs: Union[Path, str],
@@ -194,8 +196,9 @@ def create_model_description(
194
196
  careamics_version: str,
195
197
  config_path: Union[Path, str],
196
198
  env_path: Union[Path, str],
199
+ covers: list[Union[Path, str]],
197
200
  channel_names: Optional[List[str]] = None,
198
- data_description: Optional[str] = None,
201
+ model_version: str = "0.1.0",
199
202
  ) -> ModelDescr:
200
203
  """Create model description.
201
204
 
@@ -207,6 +210,8 @@ def create_model_description(
207
210
  Name of the model.
208
211
  general_description : str
209
212
  General description of the model.
213
+ data_description : str
214
+ Description of the data the model was trained on.
210
215
  authors : List[Author]
211
216
  Authors of the model.
212
217
  inputs : Union[Path, str]
@@ -223,10 +228,12 @@ def create_model_description(
223
228
  Path to model configuration.
224
229
  env_path : Union[Path, str]
225
230
  Path to environment file.
231
+ covers : list of pathlib.Path or str
232
+ Paths to cover images.
226
233
  channel_names : Optional[List[str]], optional
227
234
  Channel names, by default None.
228
- data_description : Optional[str], optional
229
- Description of the data, by default None.
235
+ model_version : str, default "0.1.0"
236
+ Model version.
230
237
 
231
238
  Returns
232
239
  -------
@@ -280,25 +287,27 @@ def create_model_description(
280
287
  "https://careamics.github.io/latest/",
281
288
  ],
282
289
  license="BSD-3-Clause",
283
- version="0.1.0",
284
- weights=weights_descr,
285
- attachments=[FileDescr(source=config_path)],
286
- cite=config.get_algorithm_citations(),
287
- config={ # conversion from float32 to float64 creates small differences...
290
+ config={
288
291
  "bioimageio": {
289
292
  "test_kwargs": {
290
293
  "pytorch_state_dict": {
291
- "decimals": 0, # ...so we relax the constraints on the decimals
294
+ "absolute_tolerance": 1e-2,
295
+ "relative_tolerance": 1e-2,
292
296
  }
293
297
  }
294
298
  }
295
299
  },
300
+ version=model_version,
301
+ weights=weights_descr,
302
+ attachments=[FileDescr(source=config_path)],
303
+ cite=config.get_algorithm_citations(),
304
+ covers=covers,
296
305
  )
297
306
 
298
307
  return model
299
308
 
300
309
 
301
- def extract_model_path(model_desc: ModelDescr) -> Tuple[Path, Path]:
310
+ def extract_model_path(model_desc: ModelDescr) -> tuple[Path, Path]:
302
311
  """Return the relative path to the weights and configuration files.
303
312
 
304
313
  Parameters
@@ -308,20 +317,24 @@ def extract_model_path(model_desc: ModelDescr) -> Tuple[Path, Path]:
308
317
 
309
318
  Returns
310
319
  -------
311
- Tuple[Path, Path]
320
+ tuple of (path, path)
312
321
  Weights and configuration paths.
313
322
  """
314
- weights_path = model_desc.weights.pytorch_state_dict.source.path
315
-
316
- if len(model_desc.attachments) == 1:
317
- config_path = model_desc.attachments[0].source.path
323
+ if model_desc.weights.pytorch_state_dict is None:
324
+ raise ValueError("No model weights found in model description.")
325
+ weights_path = resolve_and_extract(
326
+ model_desc.weights.pytorch_state_dict.source
327
+ ).path
328
+
329
+ for file in model_desc.attachments:
330
+ file_path = file.source if isinstance(file.source, Path) else file.source.path
331
+ if file_path is None:
332
+ continue
333
+ file_path = Path(file_path)
334
+ if file_path.name == "careamics.yaml":
335
+ config_path = resolve_and_extract(file.source).path
336
+ break
318
337
  else:
319
- for file in model_desc.attachments:
320
- if file.source.path.suffix == ".yml":
321
- config_path = file.source.path
322
- break
323
-
324
- if config_path is None:
325
- raise ValueError("Configuration file not found.")
338
+ raise ValueError("Configuration file not found.")
326
339
 
327
340
  return weights_path, config_path
@@ -6,8 +6,9 @@ from typing import List, Optional, Tuple, Union
6
6
 
7
7
  import numpy as np
8
8
  import pkg_resources
9
- from bioimageio.core import load_description, test_model
9
+ from bioimageio.core import load_model_description, test_model
10
10
  from bioimageio.spec import ValidationSummary, save_bioimageio_package
11
+ from pydantic import HttpUrl
11
12
  from torch import __version__ as PYTORCH_VERSION
12
13
  from torch import load, save
13
14
  from torchvision import __version__ as TORCHVISION_VERSION
@@ -20,8 +21,8 @@ from .bioimage import (
20
21
  create_env_text,
21
22
  create_model_description,
22
23
  extract_model_path,
23
- get_unzip_path,
24
24
  )
25
+ from .bioimage.cover_factory import create_cover
25
26
 
26
27
 
27
28
  def _export_state_dict(
@@ -85,11 +86,13 @@ def export_to_bmz(
85
86
  path_to_archive: Union[Path, str],
86
87
  model_name: str,
87
88
  general_description: str,
89
+ data_description: str,
88
90
  authors: List[dict],
89
91
  input_array: np.ndarray,
90
92
  output_array: np.ndarray,
93
+ covers: Optional[list[Union[Path, str]]] = None,
91
94
  channel_names: Optional[List[str]] = None,
92
- data_description: Optional[str] = None,
95
+ model_version: str = "0.1.0",
93
96
  ) -> None:
94
97
  """Export the model to BioImage Model Zoo format.
95
98
 
@@ -110,16 +113,20 @@ def export_to_bmz(
110
113
  Model name.
111
114
  general_description : str
112
115
  General description of the model.
116
+ data_description : str
117
+ Description of the data the model was trained on.
113
118
  authors : List[dict]
114
119
  Authors of the model.
115
120
  input_array : np.ndarray
116
121
  Input array, should not have been normalized.
117
122
  output_array : np.ndarray
118
123
  Output array, should have been denormalized.
124
+ covers : list of pathlib.Path or str, default=None
125
+ Paths to the cover images.
119
126
  channel_names : Optional[List[str]], optional
120
127
  Channel names, by default None.
121
- data_description : Optional[str], optional
122
- Description of the data, by default None.
128
+ model_version : str, default="0.1.0"
129
+ Model version.
123
130
 
124
131
  Raises
125
132
  ------
@@ -161,16 +168,21 @@ def export_to_bmz(
161
168
  np.save(outputs, output_array)
162
169
 
163
170
  # export configuration
164
- config_path = save_configuration(config, temp_path)
171
+ config_path = save_configuration(config, temp_path / "careamics.yaml")
165
172
 
166
173
  # export model state dictionary
167
174
  weight_path = _export_state_dict(model, temp_path / "weights.pth")
168
175
 
176
+ # export cover if necesary
177
+ if covers is None:
178
+ covers = [create_cover(temp_path, input_array, output_array)]
179
+
169
180
  # create model description
170
181
  model_description = create_model_description(
171
182
  config=config,
172
183
  name=model_name,
173
184
  general_description=general_description,
185
+ data_description=data_description,
174
186
  authors=authors,
175
187
  inputs=inputs,
176
188
  outputs=outputs,
@@ -179,12 +191,18 @@ def export_to_bmz(
179
191
  careamics_version=careamics_version,
180
192
  config_path=config_path,
181
193
  env_path=env_path,
194
+ covers=covers,
182
195
  channel_names=channel_names,
183
- data_description=data_description,
196
+ model_version=model_version,
184
197
  )
185
198
 
186
199
  # test model description
187
- summary: ValidationSummary = test_model(model_description)
200
+ test_kwargs = (
201
+ model_description.config.get("bioimageio", {})
202
+ .get("test_kwargs", {})
203
+ .get("pytorch_state_dict", {})
204
+ )
205
+ summary: ValidationSummary = test_model(model_description, **test_kwargs)
188
206
  if summary.status == "failed":
189
207
  raise ValueError(f"Model description test failed: {summary}")
190
208
 
@@ -193,41 +211,34 @@ def export_to_bmz(
193
211
 
194
212
 
195
213
  def load_from_bmz(
196
- path: Union[Path, str]
214
+ path: Union[Path, str, HttpUrl]
197
215
  ) -> Tuple[Union[FCNModule, VAEModule], Configuration]:
198
216
  """Load a model from a BioImage Model Zoo archive.
199
217
 
200
218
  Parameters
201
219
  ----------
202
- path : Union[Path, str]
203
- Path to the BioImage Model Zoo archive.
220
+ path : Path, str or HttpUrl
221
+ Path to the BioImage Model Zoo archive. A Http URL must point to a downloadable
222
+ location.
204
223
 
205
224
  Returns
206
225
  -------
207
- Tuple[CAREamicsKiln, Configuration]
208
- CAREamics model and configuration.
226
+ FCNModel or VAEModel
227
+ The loaded CAREamics model.
228
+ Configuration
229
+ The loaded CAREamics configuration.
209
230
 
210
231
  Raises
211
232
  ------
212
233
  ValueError
213
234
  If the path is not a zip file.
214
235
  """
215
- path = Path(path)
216
-
217
- if path.suffix != ".zip":
218
- raise ValueError(f"Path must be a bioimage.io zip file, got {path}.")
219
-
220
236
  # load description, this creates an unzipped folder next to the archive
221
- model_desc = load_description(path)
237
+ model_desc = load_model_description(path)
222
238
 
223
- # extract relative paths
239
+ # extract paths
224
240
  weights_path, config_path = extract_model_path(model_desc)
225
241
 
226
- # create folder path and absolute paths
227
- unzip_path = get_unzip_path(path)
228
- weights_path = unzip_path / weights_path
229
- config_path = unzip_path / config_path
230
-
231
242
  # load configuration
232
243
  config = load_configuration(config_path)
233
244
 
@@ -459,7 +459,8 @@ class MaxBlurPool(nn.Module):
459
459
  self.stride = stride
460
460
  self.max_pool_size = max_pool_size
461
461
  self.ceil_mode = ceil_mode
462
- self.kernel = _get_pascal_kernel_nd(kernel_size, norm=True, dim=self.dim)
462
+ kernel = _get_pascal_kernel_nd(kernel_size, norm=True, dim=self.dim)
463
+ self.register_buffer("kernel", kernel, persistent=False)
463
464
 
464
465
  def forward(self, x: torch.Tensor) -> torch.Tensor:
465
466
  """Forward pass of the function.
@@ -474,11 +475,12 @@ class MaxBlurPool(nn.Module):
474
475
  torch.Tensor
475
476
  Output tensor.
476
477
  """
477
- self.kernel = torch.as_tensor(self.kernel, device=x.device, dtype=x.dtype)
478
+ kernel = self.kernel.to(dtype=x.dtype)
479
+ num_channels = int(x.size(1))
478
480
  if self.dim == 2:
479
481
  return _max_blur_pool_by_kernel2d(
480
482
  x,
481
- self.kernel.repeat((x.size(1), 1, 1, 1)),
483
+ kernel.repeat((num_channels, 1, 1, 1)),
482
484
  self.stride,
483
485
  self.max_pool_size,
484
486
  self.ceil_mode,
@@ -486,7 +488,7 @@ class MaxBlurPool(nn.Module):
486
488
  else:
487
489
  return _max_blur_pool_by_kernel3d(
488
490
  x,
489
- self.kernel.repeat((x.size(1), 1, 1, 1, 1)),
491
+ kernel.repeat((num_channels, 1, 1, 1, 1)),
490
492
  self.stride,
491
493
  self.max_pool_size,
492
494
  self.ceil_mode,