mobiedantic 0.1.0__tar.gz → 0.2.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mobiedantic
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Project-URL: Documentation, https://github.com/fmi-faim/mobiedantic#readme
5
5
  Project-URL: Issues, https://github.com/fmi-faim/mobiedantic/issues
6
6
  Project-URL: Source, https://github.com/fmi-faim/mobiedantic
@@ -583,7 +583,6 @@ environments:
583
583
  - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.23.0-py312h331e495_0.conda
584
584
  - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda
585
585
  - pypi: https://files.pythonhosted.org/packages/a0/92/f788d908543faad645c794cc080b221f8c90139b96611ab72911918e29c8/hatch_conda-0.5.2-py3-none-any.whl
586
- - pypi: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl
587
586
  - pypi: .
588
587
  win-64:
589
588
  - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_0.conda
@@ -812,7 +811,7 @@ environments:
812
811
  - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py312h7606c53_0.conda
813
812
  - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.6-h0ea2cb4_0.conda
814
813
  - pypi: https://files.pythonhosted.org/packages/a0/92/f788d908543faad645c794cc080b221f8c90139b96611ab72911918e29c8/hatch_conda-0.5.2-py3-none-any.whl
815
- - pypi: https://files.pythonhosted.org/packages/c3/39/ef4a4737cb78500fc0e3290efea12f484f0d9c666976dd3888f11d4be87c/uv-0.2.25-py3-none-macosx_10_12_x86_64.whl
814
+ - pypi: https://files.pythonhosted.org/packages/a9/ea/75cd14c055777f21d036466bcf4d7afb49b73f7592d13747d4df1800a22a/uv-0.2.25-py3-none-win_amd64.whl
816
815
  - pypi: .
817
816
  mobie:
818
817
  channels:
@@ -8264,7 +8263,17 @@ packages:
8264
8263
  timestamp: 1716276077462
8265
8264
  - kind: pypi
8266
8265
  name: mobiedantic
8267
- version: 0.1.dev15+g2b75ef1.d20240719
8266
+ version: 0.1.1.dev1+g7443af1
8267
+ path: .
8268
+ sha256: ee4f165f9d96378272ddb8bf328f59cfd946894ea2ecc99f5db005acf8be3fee
8269
+ requires_dist:
8270
+ - pydantic
8271
+ - hatch-conda<0.6,>=0.5.2 ; extra == 'hatch'
8272
+ requires_python: '>=3.8'
8273
+ editable: true
8274
+ - kind: pypi
8275
+ name: mobiedantic
8276
+ version: 0.1.1.dev1+g86b62e8.d20240722
8268
8277
  path: .
8269
8278
  sha256: ee4f165f9d96378272ddb8bf328f59cfd946894ea2ecc99f5db005acf8be3fee
8270
8279
  requires_dist:
@@ -12164,14 +12173,8 @@ packages:
12164
12173
  - kind: pypi
12165
12174
  name: uv
12166
12175
  version: 0.2.25
12167
- url: https://files.pythonhosted.org/packages/c3/39/ef4a4737cb78500fc0e3290efea12f484f0d9c666976dd3888f11d4be87c/uv-0.2.25-py3-none-macosx_10_12_x86_64.whl
12168
- sha256: cc1187c0487529c9e0af750a855b540e21f5675c685c0fa400658eb9dc164739
12169
- requires_python: '>=3.8'
12170
- - kind: pypi
12171
- name: uv
12172
- version: 0.2.26
12173
- url: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl
12174
- sha256: fd3e850921f0d51d093aaeb76d190829eefdc0345439b8f6c06103a0463cc451
12176
+ url: https://files.pythonhosted.org/packages/a9/ea/75cd14c055777f21d036466bcf4d7afb49b73f7592d13747d4df1800a22a/uv-0.2.25-py3-none-win_amd64.whl
12177
+ sha256: 42bb27b5f502087aff68b54a1b8e4b72e93fd6552120eb8cc14a36d204c49ce7
12175
12178
  requires_python: '>=3.8'
12176
12179
  - kind: conda
12177
12180
  name: uv
@@ -54,6 +54,26 @@ class Dataset:
54
54
  data_format: str = 'ome.zarr',
55
55
  ) -> None:
56
56
  sources = {}
57
+ self._update_sources(
58
+ sources=sources,
59
+ path_dict=path_dict,
60
+ channel_index=channel_index,
61
+ data_format=data_format,
62
+ )
63
+ views_dict = {'default': {'uiSelectionGroup': 'view', 'isExclusive': True}}
64
+ self.model = DatasetSchema(
65
+ is2D=is2d,
66
+ sources=sources,
67
+ views=views_dict,
68
+ )
69
+
70
+ def _update_sources(
71
+ self,
72
+ sources: dict[str, Source],
73
+ path_dict: dict[str, Path],
74
+ channel_index: int = 0,
75
+ data_format: str = 'ome.zarr',
76
+ ):
57
77
  for name in path_dict:
58
78
  try:
59
79
  source_path = {
@@ -77,11 +97,19 @@ class Dataset:
77
97
  }
78
98
  }
79
99
  sources[name] = Source(**data)
80
- views_dict = {'default': {'uiSelectionGroup': 'view', 'isExclusive': True}}
81
- self.model = DatasetSchema(
82
- is2D=is2d,
83
- sources=sources,
84
- views=views_dict,
100
+
101
+ def add_sources(
102
+ self,
103
+ path_dict: dict[str, Path],
104
+ *,
105
+ channel_index: int = 0,
106
+ data_format: str = 'ome.zarr',
107
+ ):
108
+ self._update_sources(
109
+ sources=self.model.sources,
110
+ path_dict=path_dict,
111
+ channel_index=channel_index,
112
+ data_format=data_format,
85
113
  )
86
114
 
87
115
  def add_merged_grid(
@@ -151,6 +179,15 @@ class Project:
151
179
  self.model.defaultDataset = name
152
180
  return Dataset(path=dataset_folder)
153
181
 
182
+ def load(self):
183
+ project_path = self.path / 'project.json'
184
+ if not project_path.exists():
185
+ message = f'Project file not found: {project_path}'
186
+ raise ValueError(message)
187
+ with open(project_path) as project_file:
188
+ data = json.loads(project_file.read())
189
+ self.model = ProjectSchema(**data)
190
+
154
191
  def save(self, *, create_directory: bool = True):
155
192
  if self.model is None:
156
193
  message = 'Project not initialized.'
@@ -0,0 +1,145 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+
5
+ from mobiedantic import Dataset, Project
6
+
7
+
8
+ def test_project(tmp_path):
9
+ project = Project(tmp_path)
10
+ project.initialize_model(description='Test project')
11
+ project.new_dataset('Dataset_1')
12
+ project.save()
13
+ assert (tmp_path / 'project.json').exists()
14
+ assert len(project.model.datasets) == 1
15
+
16
+
17
+ def test_dataset(tmp_path):
18
+ project = Project(tmp_path)
19
+ project.initialize_model(description='Testing datasets')
20
+ dataset1: Dataset = project.new_dataset('Dataset_1')
21
+ sources1 = {
22
+ 'A01': Path('../../non-existent.zarr/A/01/0'),
23
+ 'A02': Path('../../non-existent.zarr/A/02/0'),
24
+ }
25
+ dataset1.initialize_with_paths(
26
+ path_dict=sources1,
27
+ is2d=True,
28
+ channel_index=0,
29
+ )
30
+ dataset1.add_merged_grid(
31
+ name='Merged_grid_view',
32
+ sources=list(sources1),
33
+ )
34
+ assert len(dataset1.model.views['default'].sourceDisplays) == 1
35
+ assert (
36
+ dataset1.model.views['default'].sourceDisplays[0].imageDisplay.name.root
37
+ == 'Merged_grid_view'
38
+ )
39
+ assert len(dataset1.model.views['default'].sourceTransforms) == 1
40
+ assert (
41
+ dataset1.model.views['default']
42
+ .sourceTransforms[0]
43
+ .mergedGrid.mergedGridSourceName.root
44
+ == 'Merged_grid_view'
45
+ )
46
+ assert (
47
+ len(dataset1.model.views['default'].sourceTransforms[0].mergedGrid.sources) == 2
48
+ )
49
+ sources2 = {
50
+ 'C01': Path('../../non-existent.zarr/C/01/0'),
51
+ 'C02': Path('../../non-existent.zarr/C/02/0'),
52
+ }
53
+ dataset1.add_sources(
54
+ path_dict=sources2,
55
+ channel_index=0,
56
+ data_format='ome.zarr',
57
+ )
58
+ dataset1.add_merged_grid(
59
+ name='Merged_grid_view_2',
60
+ sources=list(sources2),
61
+ )
62
+ assert len(dataset1.model.sources) == 4
63
+ assert len(dataset1.model.views['default'].sourceDisplays) == 2
64
+ assert (
65
+ dataset1.model.views['default'].sourceDisplays[1].imageDisplay.name.root
66
+ == 'Merged_grid_view_2'
67
+ )
68
+ assert len(dataset1.model.views['default'].sourceTransforms) == 2
69
+ assert (
70
+ dataset1.model.views['default']
71
+ .sourceTransforms[1]
72
+ .mergedGrid.mergedGridSourceName.root
73
+ == 'Merged_grid_view_2'
74
+ )
75
+ assert (
76
+ len(dataset1.model.views['default'].sourceTransforms[1].mergedGrid.sources) == 2
77
+ )
78
+ project.new_dataset('Dataset_2')
79
+ assert len(project.model.datasets) == 2
80
+
81
+
82
+ def test_save_and_load(tmp_path):
83
+ project = Project(tmp_path)
84
+ project.initialize_model(description='Testing saving and loading')
85
+ dataset_name = 'dataset1'
86
+ dataset = project.new_dataset(dataset_name)
87
+ sources = {
88
+ 'A01': '/path/to/source',
89
+ }
90
+ dataset.initialize_with_paths(
91
+ path_dict=sources,
92
+ is2d=True,
93
+ )
94
+ dataset.save()
95
+ project.save()
96
+
97
+ project_loaded = Project(tmp_path)
98
+ project_loaded.load()
99
+
100
+ assert project.model == project_loaded.model
101
+
102
+ dataset_loaded = Dataset(tmp_path / dataset_name)
103
+ dataset_loaded.load()
104
+
105
+ assert dataset.model == dataset_loaded.model
106
+
107
+
108
+ def test_dataset_errors(tmp_path):
109
+ filename = 'dataset.json'
110
+ with open(tmp_path / filename, 'w'):
111
+ pass
112
+ with pytest.raises(ValueError, match="'path' needs to point to a directory"):
113
+ Dataset(path=(tmp_path / filename))
114
+ dataset_dir = tmp_path / 'dataset'
115
+ dataset = Dataset(path=dataset_dir)
116
+ with pytest.raises(ValueError, match='Dataset not initialized.'):
117
+ dataset.save()
118
+ sources = {
119
+ 'A01': '/path/to/source',
120
+ }
121
+ dataset.initialize_with_paths(
122
+ path_dict=sources,
123
+ is2d=True,
124
+ )
125
+ with pytest.raises(
126
+ ValueError, match="Dataset folder doesn't exist yet and may not be created."
127
+ ):
128
+ dataset.save(create_directory=False)
129
+ with pytest.raises(ValueError, match='Dataset file not found'):
130
+ dataset.load()
131
+
132
+
133
+ def test_project_errors(tmp_path):
134
+ project = Project(tmp_path / 'non-existent_subfolder')
135
+ with pytest.raises(ValueError, match='Project not initialized'):
136
+ project.save()
137
+ with pytest.raises(ValueError, match='Project file not found'):
138
+ project.load()
139
+ with pytest.raises(ValueError, match='Project not initialized'):
140
+ project.new_dataset('dataset1')
141
+ project.initialize_model(description='Test raising errors.')
142
+ with pytest.raises(
143
+ ValueError, match="Project folder doesn't exist yet and may not be created."
144
+ ):
145
+ project.save(create_directory=False)
@@ -1,57 +0,0 @@
1
- from pathlib import Path
2
-
3
- from mobiedantic import Project
4
-
5
-
6
- def test_project(tmp_path):
7
- project = Project(tmp_path)
8
- project.initialize_model(description='Test project')
9
- project.new_dataset('Dataset_1')
10
- project.save()
11
- assert (tmp_path / 'project.json').exists()
12
- assert len(project.model.datasets) == 1
13
-
14
-
15
- def test_dataset(tmp_path):
16
- project = Project(tmp_path)
17
- project.initialize_model(description='Testing datasets')
18
- dataset1 = project.new_dataset('Dataset_1')
19
- sources1 = {
20
- 'A01': Path('../../non-existent.zarr/A/01/0'),
21
- 'A02': Path('../../non-existent.zarr/A/02/0'),
22
- }
23
- dataset1.initialize_with_paths(
24
- path_dict=sources1,
25
- is2d=True,
26
- channel_index=0,
27
- )
28
- dataset1.add_merged_grid(
29
- name='Merged_grid_view',
30
- sources=list(sources1),
31
- )
32
- assert len(dataset1.model.views['default'].sourceDisplays) == 1
33
- assert (
34
- dataset1.model.views['default'].sourceDisplays[0].imageDisplay.name.root
35
- == 'Merged_grid_view'
36
- )
37
- assert len(dataset1.model.views['default'].sourceTransforms) == 1
38
- assert (
39
- dataset1.model.views['default']
40
- .sourceTransforms[0]
41
- .mergedGrid.mergedGridSourceName.root
42
- == 'Merged_grid_view'
43
- )
44
- assert (
45
- len(dataset1.model.views['default'].sourceTransforms[0].mergedGrid.sources) == 2
46
- )
47
-
48
- dataset2 = project.new_dataset('Dataset_2')
49
- sources2 = {
50
- 'C01': Path('../../non-existent.zarr/C/01/0'),
51
- 'C02': Path('../../non-existent.zarr/C/02/0'),
52
- }
53
- dataset2.initialize_with_paths(
54
- path_dict=sources2,
55
- is2d=False,
56
- channel_index=0,
57
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes