33import zarr
44import dask .array as da
55import dask .delayed as delayed
6- from dask_stitch .local_affine import local_affines_to_field
6+ from dask_stitch .local_affine import local_affines_to_field , geometric_transform
77
88
99def position_grid (shape ):
@@ -158,3 +158,35 @@ def prepare_apply_local_affines(
158158 transpose = transpose ,
159159 )
160160
161+ def prepare_apply_geometric_transform (fix , mov , transform , \
162+ mov_spacing , blocksize ,
163+ transpose = [False ,]* 3 ):
164+
165+ # wrap transform as dask array, define chunks
166+ transform_da = transform
167+ if not isinstance (transform , da .Array ):
168+ transform_da = da .from_array (transform )
169+ if transpose [2 ]:
170+ transform_da = transform_da .transpose (2 ,1 ,0 ,3 )
171+ transform_da = transform_da [..., ::- 1 ]
172+ transform_da = transform_da .rechunk (tuple (blocksize ) )
173+
174+ # wrap moving data appropriately
175+ if isinstance (mov , np .ndarray ):
176+ mov_s = delayed (mov )
177+ elif isinstance (mov , zarr .Array ):
178+ mov_s = mov
179+
180+ def geo_block (x , tform , source , block_info = None ):
181+ block_origin = np .array (block_info [0 ]['array-location' ])[:,0 ]
182+ def mapping (r ):
183+ r += block_origin + (1 ,)
184+ M = np .linalg .inv (tform )
185+ return tuple (np .matmul (M , r )[0 :3 ])
186+
187+ return geometric_transform (source , mapping ,
188+ target_shape = x .shape ,
189+ order = 1 , prefilter = False )
190+
191+ mov_tformed = da .empty (shape = fix .shape , chunks = blocksize , dtype = fix .dtype )
192+ return da .map_blocks (geo_block , mov_tformed , transform_da , source = mov_s )
0 commit comments