multiview-stitcher 0.1.44__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.
- multiview_stitcher/__init__.py +6 -0
- multiview_stitcher/_benchmarks/__init__.py +0 -0
- multiview_stitcher/_benchmarks/test_core.py +199 -0
- multiview_stitcher/_tests/__init__.py +0 -0
- multiview_stitcher/_tests/_create_test_params.ipynb +218 -0
- multiview_stitcher/_tests/quickstart/0_data_preparation.py +33 -0
- multiview_stitcher/_tests/quickstart/1_registration.py +13 -0
- multiview_stitcher/_tests/quickstart/2_fusion.py +12 -0
- multiview_stitcher/_tests/quickstart/3_fusion_large.py +20 -0
- multiview_stitcher/_tests/test_bench.py +318 -0
- multiview_stitcher/_tests/test_fusion.py +404 -0
- multiview_stitcher/_tests/test_integration.py +89 -0
- multiview_stitcher/_tests/test_io.py +60 -0
- multiview_stitcher/_tests/test_msi_utils.py +164 -0
- multiview_stitcher/_tests/test_mv_graph.py +228 -0
- multiview_stitcher/_tests/test_ngff_utils.py +225 -0
- multiview_stitcher/_tests/test_param_utils.py +24 -0
- multiview_stitcher/_tests/test_quickstart.py +52 -0
- multiview_stitcher/_tests/test_registration.py +786 -0
- multiview_stitcher/_tests/test_sample_data.py +41 -0
- multiview_stitcher/_tests/test_spatial_image_utils.py +50 -0
- multiview_stitcher/_tests/test_vis_utils.py +164 -0
- multiview_stitcher/_tests/test_weights.py +131 -0
- multiview_stitcher/_version.py +34 -0
- multiview_stitcher/czi_utils.py +492 -0
- multiview_stitcher/czifile_patch.py +137 -0
- multiview_stitcher/fusion.py +1220 -0
- multiview_stitcher/io.py +405 -0
- multiview_stitcher/misc_utils.py +86 -0
- multiview_stitcher/msi_utils.py +418 -0
- multiview_stitcher/mv_graph.py +1059 -0
- multiview_stitcher/ngff_utils.py +673 -0
- multiview_stitcher/param_utils.py +214 -0
- multiview_stitcher/registration.py +2364 -0
- multiview_stitcher/sample_data.py +152 -0
- multiview_stitcher/spatial_image_utils.py +444 -0
- multiview_stitcher/test-datasets/mosaic_test.czi +0 -0
- multiview_stitcher/transformation.py +107 -0
- multiview_stitcher/transforms.py +168 -0
- multiview_stitcher/vis_utils.py +710 -0
- multiview_stitcher/weights.py +246 -0
- multiview_stitcher-0.1.44.dist-info/METADATA +314 -0
- multiview_stitcher-0.1.44.dist-info/RECORD +46 -0
- multiview_stitcher-0.1.44.dist-info/WHEEL +5 -0
- multiview_stitcher-0.1.44.dist-info/licenses/LICENSE +28 -0
- multiview_stitcher-0.1.44.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import multiview_stitcher.spatial_image_utils as si_utils
|
|
6
|
+
from multiview_stitcher import (
|
|
7
|
+
fusion,
|
|
8
|
+
msi_utils,
|
|
9
|
+
param_utils,
|
|
10
|
+
registration,
|
|
11
|
+
sample_data,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# to be used in the future when we have test data to be cached
|
|
15
|
+
# @pytest.fixture(scope="session")
|
|
16
|
+
# def testdata_dir_path() -> Path:
|
|
17
|
+
# TEST_DIR = Path(__file__).parent
|
|
18
|
+
# if not TEST_DIR.exists():
|
|
19
|
+
# raise FileNotFoundError(f"Test data directory not found: {TEST_DIR}")
|
|
20
|
+
# return TEST_DIR / "data/"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def create_input(
|
|
24
|
+
test_params=None,
|
|
25
|
+
tmp_dir="/tmp/test_benchmarking",
|
|
26
|
+
):
|
|
27
|
+
"""
|
|
28
|
+
Test that the circumvent_dask_for_zarr_backed_input flag works as expected.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# create minimal example grid with overlap
|
|
32
|
+
if test_params is None:
|
|
33
|
+
test_params = {
|
|
34
|
+
"t": 1,
|
|
35
|
+
"c": 1,
|
|
36
|
+
"ndim": 3,
|
|
37
|
+
"input_chunking": 50,
|
|
38
|
+
"tiles_x": 3,
|
|
39
|
+
"tiles_y": 3,
|
|
40
|
+
"tile_size": 100,
|
|
41
|
+
"overlap": 20,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ndim = test_params["ndim"]
|
|
45
|
+
sims = sample_data.generate_tiled_dataset(
|
|
46
|
+
ndim=ndim,
|
|
47
|
+
overlap=test_params["overlap"],
|
|
48
|
+
N_c=test_params["c"],
|
|
49
|
+
N_t=test_params["t"],
|
|
50
|
+
tile_size=test_params["tile_size"],
|
|
51
|
+
tiles_x=test_params["tiles_x"],
|
|
52
|
+
tiles_y=test_params["tiles_y"],
|
|
53
|
+
tiles_z=1,
|
|
54
|
+
spacing_x=1,
|
|
55
|
+
spacing_y=1,
|
|
56
|
+
spacing_z=1,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# rechunk and jiggle input data
|
|
60
|
+
for sim in sims:
|
|
61
|
+
sim.data = sim.data.rechunk(test_params["input_chunking"])
|
|
62
|
+
p = param_utils.affine_to_xaffine(
|
|
63
|
+
param_utils.random_affine(
|
|
64
|
+
ndim=ndim,
|
|
65
|
+
rotation_scale=0,
|
|
66
|
+
scale_scale=0,
|
|
67
|
+
translation_scale=10,
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
si_utils.set_sim_affine(sim, p, transform_key="random")
|
|
71
|
+
|
|
72
|
+
# persist input data to zarr
|
|
73
|
+
for iview in range(len(sims)):
|
|
74
|
+
msi_utils.multiscale_spatial_image_to_zarr(
|
|
75
|
+
msi_utils.get_msim_from_sim(sims[iview], scale_factors=[]),
|
|
76
|
+
os.path.join(tmp_dir, f"msim_view_{iview}.zarr"),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def fuse_zarr_to_zarr(
|
|
83
|
+
tmp_input_dir,
|
|
84
|
+
):
|
|
85
|
+
input_filepaths = sorted(
|
|
86
|
+
[
|
|
87
|
+
os.path.join(tmp_input_dir, f)
|
|
88
|
+
for f in os.listdir(tmp_input_dir)
|
|
89
|
+
if "fused" not in f
|
|
90
|
+
]
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
msims = [
|
|
94
|
+
msi_utils.multiscale_spatial_image_from_zarr(fp)
|
|
95
|
+
for fp in input_filepaths
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
sims = [msi_utils.get_sim_from_msim(msim) for msim in msims]
|
|
99
|
+
|
|
100
|
+
sdims = si_utils.get_spatial_dims_from_sim(sims[0])
|
|
101
|
+
|
|
102
|
+
fused_sim = fusion.fuse(
|
|
103
|
+
sims,
|
|
104
|
+
transform_key="random",
|
|
105
|
+
output_chunksize={dim: 100 for dim in sdims},
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
109
|
+
fused_sim.data.to_zarr(
|
|
110
|
+
os.path.join(tmp_dir, "fused_sim.zarr"),
|
|
111
|
+
overwrite=True,
|
|
112
|
+
return_stored=True,
|
|
113
|
+
compute=True,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_fusion(
|
|
120
|
+
benchmark,
|
|
121
|
+
):
|
|
122
|
+
test_params = {
|
|
123
|
+
"t": 1,
|
|
124
|
+
"c": 1,
|
|
125
|
+
"ndim": 3,
|
|
126
|
+
"input_chunking": 50,
|
|
127
|
+
"tiles_x": 3,
|
|
128
|
+
"tiles_y": 3,
|
|
129
|
+
"tile_size": 100,
|
|
130
|
+
"overlap": 20,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
134
|
+
testdata_dir_path = Path(tmpdir)
|
|
135
|
+
|
|
136
|
+
create_input(
|
|
137
|
+
tmp_dir=testdata_dir_path,
|
|
138
|
+
test_params=test_params,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# benchmark something
|
|
142
|
+
benchmark.pedantic(
|
|
143
|
+
fuse_zarr_to_zarr,
|
|
144
|
+
args=(testdata_dir_path,),
|
|
145
|
+
iterations=1,
|
|
146
|
+
rounds=3,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def register_zarrs(
|
|
151
|
+
tmp_dir,
|
|
152
|
+
):
|
|
153
|
+
input_filepaths = sorted(
|
|
154
|
+
[os.path.join(tmp_dir, f) for f in os.listdir(tmp_dir)]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
msims = [
|
|
158
|
+
msi_utils.multiscale_spatial_image_from_zarr(fp)
|
|
159
|
+
for fp in input_filepaths
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
registration.register(
|
|
163
|
+
msims,
|
|
164
|
+
transform_key="random",
|
|
165
|
+
reg_channel_index=0,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_registration(
|
|
172
|
+
benchmark,
|
|
173
|
+
):
|
|
174
|
+
test_params = {
|
|
175
|
+
"t": 1,
|
|
176
|
+
"c": 1,
|
|
177
|
+
"ndim": 2,
|
|
178
|
+
"input_chunking": 50,
|
|
179
|
+
"tiles_x": 2,
|
|
180
|
+
"tiles_y": 2,
|
|
181
|
+
"tile_size": 100,
|
|
182
|
+
"overlap": 20,
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
186
|
+
testdata_dir_path = Path(tmpdir)
|
|
187
|
+
|
|
188
|
+
create_input(
|
|
189
|
+
tmp_dir=testdata_dir_path,
|
|
190
|
+
test_params=test_params,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# benchmark something
|
|
194
|
+
benchmark.pedantic(
|
|
195
|
+
register_zarrs,
|
|
196
|
+
args=(testdata_dir_path,),
|
|
197
|
+
iterations=1,
|
|
198
|
+
rounds=3,
|
|
199
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Obtain ground truth params for test datasets\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Convenience notebook for creating ground truth parameters for test datasets."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": 1,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [
|
|
17
|
+
{
|
|
18
|
+
"data": {
|
|
19
|
+
"text/plain": [
|
|
20
|
+
"<module 'multiview_stitcher._tests.test_bench' from '/Users/malbert/software/multiview-stitcher/src/multiview_stitcher/_tests/test_bench.py'>"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"execution_count": 1,
|
|
24
|
+
"metadata": {},
|
|
25
|
+
"output_type": "execute_result"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"source": [
|
|
29
|
+
"from pathlib import Path\n",
|
|
30
|
+
"\n",
|
|
31
|
+
"from multiview_stitcher._tests import test_bench\n",
|
|
32
|
+
"from multiview_stitcher import vis_utils, io\n",
|
|
33
|
+
"\n",
|
|
34
|
+
"import dask.diagnostics\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"import importlib\n",
|
|
37
|
+
"importlib.reload(test_bench)"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"cell_type": "code",
|
|
42
|
+
"execution_count": 9,
|
|
43
|
+
"metadata": {},
|
|
44
|
+
"outputs": [
|
|
45
|
+
{
|
|
46
|
+
"name": "stdout",
|
|
47
|
+
"output_type": "stream",
|
|
48
|
+
"text": [
|
|
49
|
+
"/Users/malbert/software/multiview-stitcher/image-datasets/test_bench_data\n"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"data": {
|
|
54
|
+
"image/png": "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B9Xrk729PbRabb2vp6GxtbWFjY2NxfXb2F9zvLcaEmtra9jb21tUn4HbnyXNmjWzuH4DgKOjY433uSW8Djz79y5yc3Ph4+ODrKwseHh4qF0ONSEGgwEXLlxA27Ztm+zZj0T3o9FoYGtrC41Go3Yp9YKhehdCCJSWlsLR0bHJDjwRkRo0Gk2T/lxlqBIREUnC/U9ERESSMFSJiIgkYagSERFJwlAlIiKShKFKREQkCUOViIhIEoYqERGRJAxVIiIiSRiqREREkjBUiYiIJGGoEhERScJQJSIikoShSkREJAlDlYiISBKGKhERkSQMVSIiIkkYqkRERJIwVImIiCRhqBIREUnCUCUiIpKEoUpERCQJQ5WIiEgShioREZEkDFUiIiJJGKpERESSMFSJiIgkYagSERFJwlAlIiKShKFKREQkCUOViIhIEoYqERGRJAxVIiIiSRiqREREkjBUiYiIJGGoEhERScJQJSIikoShSkREJAlDlYiISBKGKhERkSQMVSIiIkkYqkRERJIwVImIiCRhqBIREUnCUCUiIpKEoUpERCQJQ5WIiEgShioREZEkDFUiIiJJGKpERESSMFSJiIgkYagSERFJwlAlIiKShKFKREQkCUOViIhIEoYqERGRJAxVIiIiSRiqREREkjBUiYiIJGGoEhERScJQJSIikoShSkREJAlDlYiISBKGKhERkSQMVSIiIkkYqkRERJIwVImIiCRhqBIREUnCUCUiIpKEoUpERCQJQ5WIiEgShioREZEkDFUiIiJJGKpERESSMFSJiIgkYagSERFJwlAlIiKShKFKREQkCUOViIhIEoYqERGRJAxVIiIiSRiqREREkjBUiYiIJPl/nMQKk7yoi08AAAAASUVORK5CYII=",
|
|
55
|
+
"text/plain": [
|
|
56
|
+
"<Figure size 640x480 with 1 Axes>"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"metadata": {},
|
|
60
|
+
"output_type": "display_data"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"data": {
|
|
64
|
+
"text/plain": [
|
|
65
|
+
"(<Figure size 640x480 with 1 Axes>, <Axes3D: ylabel='x [μm]', zlabel='y [μm]'>)"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"execution_count": 9,
|
|
69
|
+
"metadata": {},
|
|
70
|
+
"output_type": "execute_result"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"source": [
|
|
74
|
+
"print(test_bench.test_bench_data_dir)\n",
|
|
75
|
+
"\n",
|
|
76
|
+
"dataset = test_bench.datasets[2]\n",
|
|
77
|
+
"msims = test_bench.get_msims_from_dataset(dataset)\n",
|
|
78
|
+
"\n",
|
|
79
|
+
"vis_utils.plot_positions(msims, io.METADATA_TRANSFORM_KEY, use_positional_colors=False)"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"cell_type": "markdown",
|
|
84
|
+
"metadata": {},
|
|
85
|
+
"source": [
|
|
86
|
+
"## Registration"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"cell_type": "code",
|
|
91
|
+
"execution_count": 10,
|
|
92
|
+
"metadata": {},
|
|
93
|
+
"outputs": [
|
|
94
|
+
{
|
|
95
|
+
"name": "stdout",
|
|
96
|
+
"output_type": "stream",
|
|
97
|
+
"text": [
|
|
98
|
+
"[########################################] | 100% Completed | 1.58 ss\n",
|
|
99
|
+
"[########################################] | 100% Completed | 5.12 sms\n"
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"source": [
|
|
104
|
+
"with dask.diagnostics.ProgressBar():\n",
|
|
105
|
+
" params = test_bench.register_dataset(msims, dataset)"
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"cell_type": "markdown",
|
|
110
|
+
"metadata": {},
|
|
111
|
+
"source": [
|
|
112
|
+
"## Visualization"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"cell_type": "code",
|
|
117
|
+
"execution_count": 7,
|
|
118
|
+
"metadata": {},
|
|
119
|
+
"outputs": [],
|
|
120
|
+
"source": [
|
|
121
|
+
"# napari\n",
|
|
122
|
+
"\n",
|
|
123
|
+
"from napari_stitcher import viewer_utils\n",
|
|
124
|
+
"import napari\n",
|
|
125
|
+
"\n",
|
|
126
|
+
"viewer = napari.Viewer(ndisplay=2)\n",
|
|
127
|
+
"lds = viewer_utils.create_image_layer_tuples_from_msims(\n",
|
|
128
|
+
" msims,\n",
|
|
129
|
+
" transform_key='reg_0',\n",
|
|
130
|
+
" n_colors=4,\n",
|
|
131
|
+
" # contrast_limits=[0, 1000],\n",
|
|
132
|
+
" )\n",
|
|
133
|
+
"viewer_utils.add_image_layer_tuples_to_viewer(viewer, lds, manage_viewer_transformations=True)\n",
|
|
134
|
+
"viewer.reset_view()\n",
|
|
135
|
+
" "
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"cell_type": "code",
|
|
140
|
+
"execution_count": null,
|
|
141
|
+
"metadata": {},
|
|
142
|
+
"outputs": [],
|
|
143
|
+
"source": [
|
|
144
|
+
"# # neuroglancer\n",
|
|
145
|
+
"\n",
|
|
146
|
+
"# # doesn't work if time dimension is present\n",
|
|
147
|
+
"\n",
|
|
148
|
+
"# from multiview_stitcher import vis_utils, ngff_utils, msi_utils\n",
|
|
149
|
+
"# import importlib\n",
|
|
150
|
+
"# importlib.reload(vis_utils)\n",
|
|
151
|
+
"\n",
|
|
152
|
+
"# import tempfile\n",
|
|
153
|
+
"\n",
|
|
154
|
+
"# with tempfile.TemporaryDirectory() as tmp_dir:\n",
|
|
155
|
+
"\n",
|
|
156
|
+
"# tmp_dir = Path(tmp_dir)\n",
|
|
157
|
+
"\n",
|
|
158
|
+
"# zarr_paths = [tmp_dir / f\"sim_{imsim}.zarr\" for imsim, msim in enumerate(msims)]\n",
|
|
159
|
+
"\n",
|
|
160
|
+
"# sims = [msi_utils.get_sim_from_msim(msim) for msim in msims]\n",
|
|
161
|
+
"\n",
|
|
162
|
+
"# for imsim, msim in enumerate(msims):\n",
|
|
163
|
+
"# ngff_utils.write_sim_to_ome_zarr(\n",
|
|
164
|
+
"# msi_utils.get_sim_from_msim(msim),\n",
|
|
165
|
+
"# zarr_paths[imsim], overwrite=False)\n",
|
|
166
|
+
"\n",
|
|
167
|
+
"# # sims = [ngff_utils.write_sim_to_ome_zarr(\n",
|
|
168
|
+
"# # msi_utils.get_sim_from_msim(msim),\n",
|
|
169
|
+
"# # zarr_paths[imsim], overwrite=False) for imsim, msim in enumerate(msims)]\n",
|
|
170
|
+
"\n",
|
|
171
|
+
"# vis_utils.view_neuroglancer(\n",
|
|
172
|
+
"# sims,\n",
|
|
173
|
+
"# ome_zarr_paths=zarr_paths,\n",
|
|
174
|
+
"# # channel_coord='DAPI',\n",
|
|
175
|
+
"# transform_key=\"registered\",\n",
|
|
176
|
+
"# # single_layer=False,\n",
|
|
177
|
+
"# )"
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"cell_type": "markdown",
|
|
182
|
+
"metadata": {},
|
|
183
|
+
"source": [
|
|
184
|
+
"## Save parameters"
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"cell_type": "code",
|
|
189
|
+
"execution_count": 11,
|
|
190
|
+
"metadata": {},
|
|
191
|
+
"outputs": [],
|
|
192
|
+
"source": [
|
|
193
|
+
"test_bench.write_params(params, dataset[\"parameter_path\"])"
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"metadata": {
|
|
198
|
+
"kernelspec": {
|
|
199
|
+
"display_name": "ms_ns",
|
|
200
|
+
"language": "python",
|
|
201
|
+
"name": "python3"
|
|
202
|
+
},
|
|
203
|
+
"language_info": {
|
|
204
|
+
"codemirror_mode": {
|
|
205
|
+
"name": "ipython",
|
|
206
|
+
"version": 3
|
|
207
|
+
},
|
|
208
|
+
"file_extension": ".py",
|
|
209
|
+
"mimetype": "text/x-python",
|
|
210
|
+
"name": "python",
|
|
211
|
+
"nbconvert_exporter": "python",
|
|
212
|
+
"pygments_lexer": "ipython3",
|
|
213
|
+
"version": "3.11.11"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"nbformat": 4,
|
|
217
|
+
"nbformat_minor": 2
|
|
218
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from multiview_stitcher import msi_utils
|
|
3
|
+
from multiview_stitcher import spatial_image_utils as si_utils
|
|
4
|
+
|
|
5
|
+
# input data (can be any numpy compatible array: numpy, dask, cupy, etc.)
|
|
6
|
+
tile_arrays = [np.random.randint(0, 100, (2, 10, 100, 100)) for _ in range(3)]
|
|
7
|
+
|
|
8
|
+
# indicate the tile offsets and spacing
|
|
9
|
+
tile_translations = [
|
|
10
|
+
{"z": 2.5, "y": -10, "x": 30},
|
|
11
|
+
{"z": 2.5, "y": 30, "x": 10},
|
|
12
|
+
{"z": 2.5, "y": 30, "x": 50},
|
|
13
|
+
]
|
|
14
|
+
spacing = {"z": 2, "y": 0.5, "x": 0.5}
|
|
15
|
+
|
|
16
|
+
channels = ["DAPI", "GFP"]
|
|
17
|
+
|
|
18
|
+
# build input for stitching
|
|
19
|
+
msims = []
|
|
20
|
+
for tile_array, tile_translation in zip(tile_arrays, tile_translations):
|
|
21
|
+
sim = si_utils.get_sim_from_array(
|
|
22
|
+
tile_array,
|
|
23
|
+
dims=["c", "z", "y", "x"],
|
|
24
|
+
scale=spacing,
|
|
25
|
+
translation=tile_translation,
|
|
26
|
+
transform_key="stage_metadata",
|
|
27
|
+
c_coords=channels,
|
|
28
|
+
)
|
|
29
|
+
msims.append(msi_utils.get_msim_from_sim(sim, scale_factors=[]))
|
|
30
|
+
|
|
31
|
+
# plot the tile configuration
|
|
32
|
+
# from multiview_stitcher import vis_utils
|
|
33
|
+
# fig, ax = vis_utils.plot_positions(msims, transform_key='stage_metadata', use_positional_colors=False)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from dask.diagnostics import ProgressBar
|
|
2
|
+
from multiview_stitcher import registration
|
|
3
|
+
|
|
4
|
+
with ProgressBar():
|
|
5
|
+
params = registration.register(
|
|
6
|
+
msims,
|
|
7
|
+
reg_channel="DAPI", # channel to use for registration
|
|
8
|
+
transform_key="stage_metadata",
|
|
9
|
+
new_transform_key="translation_registered",
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# plot the tile configuration after registration
|
|
13
|
+
# vis_utils.plot_positions(msims, transform_key='translation_registered', use_positional_colors=False)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from multiview_stitcher import fusion
|
|
2
|
+
|
|
3
|
+
fused_sim = fusion.fuse(
|
|
4
|
+
[msi_utils.get_sim_from_msim(msim) for msim in msims],
|
|
5
|
+
transform_key="translation_registered",
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
# get fused array as a dask array
|
|
9
|
+
fused_sim.data
|
|
10
|
+
|
|
11
|
+
# get fused array as a numpy array
|
|
12
|
+
fused_sim.data.compute()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from multiview_stitcher import fusion, misc_utils
|
|
2
|
+
|
|
3
|
+
fused = fusion.fuse(
|
|
4
|
+
sims=[msi_utils.get_sim_from_msim(msim) for msim in msims],
|
|
5
|
+
transform_key="translation_registered",
|
|
6
|
+
# ... further optional args for fusion.fuse
|
|
7
|
+
output_zarr_url="fused_output.ome.zarr",
|
|
8
|
+
zarr_options={
|
|
9
|
+
"ome_zarr": True,
|
|
10
|
+
# "ngff_version": "0.4", # optional
|
|
11
|
+
},
|
|
12
|
+
# optionally, we can use ray for parallelization (`pip install "ray[default]"`)
|
|
13
|
+
# batch_options={
|
|
14
|
+
# "batch_func": misc_utils.process_batch_using_ray,
|
|
15
|
+
# "n_batch": 4, # number of chunk fusions to schedule / submit at a time
|
|
16
|
+
# "batch_func_kwargs": {
|
|
17
|
+
# 'num_cpus': 4 # number of processes for parallel processing to use with ray
|
|
18
|
+
# },
|
|
19
|
+
# },
|
|
20
|
+
)
|