mobiedantic 0.1.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.
mobiedantic/__init__.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from mobiedantic.generated import Dataset as DatasetSchema
|
|
7
|
+
from mobiedantic.generated import ImageDisplay, ImageDisplay1, MergedGrid, Name, Source
|
|
8
|
+
from mobiedantic.generated import Project as ProjectSchema
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Dataset:
|
|
12
|
+
path: Path
|
|
13
|
+
model: DatasetSchema = None
|
|
14
|
+
|
|
15
|
+
def __init__(self, path: Path) -> None:
|
|
16
|
+
self.path = Path(path)
|
|
17
|
+
if self.path.exists() and not self.path.is_dir():
|
|
18
|
+
message = "'path' needs to point to a directory."
|
|
19
|
+
raise ValueError(message)
|
|
20
|
+
|
|
21
|
+
def save(self, *, create_directory: bool = True):
|
|
22
|
+
if self.model is None:
|
|
23
|
+
message = 'Dataset not initialized.'
|
|
24
|
+
raise ValueError(message)
|
|
25
|
+
if not self.path.exists() and not create_directory:
|
|
26
|
+
message = "Dataset folder doesn't exist yet and may not be created."
|
|
27
|
+
raise ValueError(message)
|
|
28
|
+
self.path.mkdir(exist_ok=True)
|
|
29
|
+
with open(self.path / 'dataset.json', 'w') as dataset_file:
|
|
30
|
+
dataset_file.write(
|
|
31
|
+
json.dumps(
|
|
32
|
+
self.model.model_dump(exclude_none=True, by_alias=True), indent=2
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def load(self):
|
|
37
|
+
dataset_path = self.path / 'dataset.json'
|
|
38
|
+
if not dataset_path.exists():
|
|
39
|
+
message = f'Dataset file not found: {dataset_path}'
|
|
40
|
+
raise ValueError(message)
|
|
41
|
+
with open(dataset_path) as dataset_file:
|
|
42
|
+
data = json.loads(dataset_file.read())
|
|
43
|
+
self.model = DatasetSchema(**data)
|
|
44
|
+
|
|
45
|
+
def set_model(self, model: DatasetSchema):
|
|
46
|
+
self.model = model
|
|
47
|
+
|
|
48
|
+
def initialize_with_paths(
|
|
49
|
+
self,
|
|
50
|
+
path_dict: dict[str, Path],
|
|
51
|
+
*,
|
|
52
|
+
is2d: bool,
|
|
53
|
+
channel_index: int = 0,
|
|
54
|
+
data_format: str = 'ome.zarr',
|
|
55
|
+
) -> None:
|
|
56
|
+
sources = {}
|
|
57
|
+
for name in path_dict:
|
|
58
|
+
try:
|
|
59
|
+
source_path = {
|
|
60
|
+
'channel': channel_index,
|
|
61
|
+
'relativePath': str(
|
|
62
|
+
Path(path_dict[name]).relative_to(
|
|
63
|
+
self.path.parent, walk_up=True
|
|
64
|
+
)
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
except (ValueError, TypeError):
|
|
68
|
+
source_path = {
|
|
69
|
+
'channel': channel_index,
|
|
70
|
+
'absolutePath': str(Path(path_dict[name]).absolute()),
|
|
71
|
+
}
|
|
72
|
+
data = {
|
|
73
|
+
'image': {
|
|
74
|
+
'imageData': {
|
|
75
|
+
data_format: source_path,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
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,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def add_merged_grid(
|
|
88
|
+
self,
|
|
89
|
+
name: str,
|
|
90
|
+
sources: list[str],
|
|
91
|
+
positions: list[tuple[int, int]] | None = None,
|
|
92
|
+
*,
|
|
93
|
+
view_name: str = 'default',
|
|
94
|
+
) -> None:
|
|
95
|
+
if self.model.views[view_name].sourceTransforms is None:
|
|
96
|
+
self.model.views[view_name].sourceTransforms = []
|
|
97
|
+
self.model.views[view_name].sourceTransforms.append(
|
|
98
|
+
MergedGrid(
|
|
99
|
+
mergedGrid={
|
|
100
|
+
'sources': sources,
|
|
101
|
+
'positions': positions,
|
|
102
|
+
'mergedGridSourceName': name,
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
if self.model.views[view_name].sourceDisplays is None:
|
|
107
|
+
self.model.views[view_name].sourceDisplays = []
|
|
108
|
+
self.model.views[view_name].sourceDisplays.append(
|
|
109
|
+
ImageDisplay(
|
|
110
|
+
imageDisplay=ImageDisplay1(
|
|
111
|
+
name=name,
|
|
112
|
+
color='white',
|
|
113
|
+
opacity=1.0,
|
|
114
|
+
contrastLimits=[0, 255], # TODO: get from histograms/data
|
|
115
|
+
sources=[name],
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# @classmethod
|
|
121
|
+
# def create(cls, path: Path, *, is2d: bool) -> "Dataset":
|
|
122
|
+
# empty_schema = DatasetSchema(
|
|
123
|
+
# is2D=is2d,
|
|
124
|
+
# )
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class Project:
|
|
128
|
+
path: Path
|
|
129
|
+
model: ProjectSchema = None
|
|
130
|
+
|
|
131
|
+
def __init__(self, path: Path) -> None:
|
|
132
|
+
self.path = Path(path)
|
|
133
|
+
|
|
134
|
+
def initialize_model(self, description: str) -> None:
|
|
135
|
+
self.model = ProjectSchema(
|
|
136
|
+
datasets=[], defaultDataset='', description=description, specVersion='0.3.0'
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def new_dataset(
|
|
140
|
+
self, name: str, *, make_default: bool = False, overwrite: bool = True
|
|
141
|
+
) -> Dataset:
|
|
142
|
+
if self.model is None:
|
|
143
|
+
message = 'Project not initialized.'
|
|
144
|
+
raise ValueError(message)
|
|
145
|
+
if len(self.model.datasets) == 0:
|
|
146
|
+
make_default = True
|
|
147
|
+
dataset_folder = self.path / name
|
|
148
|
+
dataset_folder.mkdir(exist_ok=overwrite, parents=True)
|
|
149
|
+
self.model.datasets.append(Name(name))
|
|
150
|
+
if make_default:
|
|
151
|
+
self.model.defaultDataset = name
|
|
152
|
+
return Dataset(path=dataset_folder)
|
|
153
|
+
|
|
154
|
+
def save(self, *, create_directory: bool = True):
|
|
155
|
+
if self.model is None:
|
|
156
|
+
message = 'Project not initialized.'
|
|
157
|
+
raise ValueError(message)
|
|
158
|
+
if not self.path.exists() and not create_directory:
|
|
159
|
+
message = "Project folder doesn't exist yet and may not be created."
|
|
160
|
+
raise ValueError(message)
|
|
161
|
+
self.path.mkdir(exist_ok=True)
|
|
162
|
+
with open(self.path / 'project.json', 'w') as project_file:
|
|
163
|
+
project_file.write(
|
|
164
|
+
json.dumps(
|
|
165
|
+
self.model.model_dump(exclude_none=True, by_alias=True), indent=2
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# @classmethod
|
|
170
|
+
# def create(cls, path: Path) -> "Project":
|