imops 0.8.8__cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.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.
Files changed (58) hide show
  1. _build_utils.py +113 -0
  2. imops/__init__.py +10 -0
  3. imops/__version__.py +1 -0
  4. imops/_configs.py +29 -0
  5. imops/backend.py +95 -0
  6. imops/box.py +74 -0
  7. imops/cpp/cpp_modules.cpython-38-i386-linux-gnu.so +0 -0
  8. imops/cpp/interp2d/delaunator/delaunator-header-only.hpp +33 -0
  9. imops/cpp/interp2d/delaunator/delaunator.cpp +645 -0
  10. imops/cpp/interp2d/delaunator/delaunator.hpp +170 -0
  11. imops/cpp/interp2d/interpolator.h +52 -0
  12. imops/cpp/interp2d/triangulator.h +198 -0
  13. imops/cpp/interp2d/utils.h +63 -0
  14. imops/cpp/main.cpp +13 -0
  15. imops/crop.py +120 -0
  16. imops/interp1d.py +207 -0
  17. imops/interp2d.py +120 -0
  18. imops/measure.py +228 -0
  19. imops/morphology.py +525 -0
  20. imops/numeric.py +384 -0
  21. imops/pad.py +253 -0
  22. imops/py.typed +0 -0
  23. imops/radon.py +247 -0
  24. imops/src/__init__.py +0 -0
  25. imops/src/_backprojection.c +27339 -0
  26. imops/src/_backprojection.cpython-38-i386-linux-gnu.so +0 -0
  27. imops/src/_fast_backprojection.c +27339 -0
  28. imops/src/_fast_backprojection.cpython-38-i386-linux-gnu.so +0 -0
  29. imops/src/_fast_measure.c +33810 -0
  30. imops/src/_fast_measure.cpython-38-i386-linux-gnu.so +0 -0
  31. imops/src/_fast_morphology.c +26089 -0
  32. imops/src/_fast_morphology.cpython-38-i386-linux-gnu.so +0 -0
  33. imops/src/_fast_numeric.c +48651 -0
  34. imops/src/_fast_numeric.cpython-38-i386-linux-gnu.so +0 -0
  35. imops/src/_fast_radon.c +30714 -0
  36. imops/src/_fast_radon.cpython-38-i386-linux-gnu.so +0 -0
  37. imops/src/_fast_zoom.c +57203 -0
  38. imops/src/_fast_zoom.cpython-38-i386-linux-gnu.so +0 -0
  39. imops/src/_measure.c +33810 -0
  40. imops/src/_measure.cpython-38-i386-linux-gnu.so +0 -0
  41. imops/src/_morphology.c +26089 -0
  42. imops/src/_morphology.cpython-38-i386-linux-gnu.so +0 -0
  43. imops/src/_numba_zoom.py +503 -0
  44. imops/src/_numeric.c +48651 -0
  45. imops/src/_numeric.cpython-38-i386-linux-gnu.so +0 -0
  46. imops/src/_radon.c +30714 -0
  47. imops/src/_radon.cpython-38-i386-linux-gnu.so +0 -0
  48. imops/src/_zoom.c +57203 -0
  49. imops/src/_zoom.cpython-38-i386-linux-gnu.so +0 -0
  50. imops/testing.py +57 -0
  51. imops/utils.py +205 -0
  52. imops/zoom.py +297 -0
  53. imops-0.8.8.dist-info/LICENSE +21 -0
  54. imops-0.8.8.dist-info/METADATA +218 -0
  55. imops-0.8.8.dist-info/RECORD +58 -0
  56. imops-0.8.8.dist-info/WHEEL +6 -0
  57. imops-0.8.8.dist-info/top_level.txt +2 -0
  58. imops.libs/libgomp-65f46eca.so.1.0.0 +0 -0
@@ -0,0 +1,503 @@
1
+ from typing import Union
2
+
3
+ import numpy as np
4
+ from numba import njit, prange
5
+
6
+
7
+ float_or_int = Union[float, int]
8
+
9
+
10
+ def _interp1d(
11
+ input: np.ndarray,
12
+ old_locations: np.ndarray,
13
+ new_locations: np.ndarray,
14
+ bounds_error: bool,
15
+ fill_value: float,
16
+ extrapolate: bool,
17
+ assume_sorted: bool,
18
+ ) -> np.ndarray:
19
+ rows, cols, dims = input.shape[0], input.shape[1], len(new_locations)
20
+ contiguous_input = np.ascontiguousarray(input)
21
+
22
+ dtype = input.dtype
23
+ interpolated = np.zeros((rows, cols, dims), dtype=dtype)
24
+ dd = np.zeros(dims)
25
+
26
+ old_dims = len(old_locations)
27
+ sort_permutation = np.arange(old_dims) if assume_sorted else np.argsort(old_locations)
28
+ max_idxs = np.searchsorted(old_locations[sort_permutation], new_locations)
29
+
30
+ extr = np.zeros(dims, dtype=np.int8)
31
+
32
+ for k in prange(dims):
33
+ if max_idxs[k] == 0:
34
+ if new_locations[k] < old_locations[sort_permutation[max_idxs[k]]]:
35
+ extr[k] = -1
36
+ else:
37
+ max_idxs[k] = 1
38
+
39
+ if max_idxs[k] >= old_dims:
40
+ extr[k] = 1
41
+
42
+ if extr[k] == 0:
43
+ dd[k] = (new_locations[k] - old_locations[sort_permutation[max_idxs[k] - 1]]) / (
44
+ old_locations[sort_permutation[max_idxs[k]]] - old_locations[sort_permutation[max_idxs[k] - 1]]
45
+ )
46
+
47
+ if bounds_error and np.any(extr):
48
+ raise ValueError('A value in x_new is out of the interpolation range.')
49
+
50
+ if np.any(extr) and extrapolate:
51
+ slope_left = np.zeros((rows, cols))
52
+ slope_right = np.zeros((rows, cols))
53
+ bias_left = np.zeros((rows, cols))
54
+ bias_right = np.zeros((rows, cols))
55
+
56
+ slope_left = get_slope(
57
+ old_locations[sort_permutation[0]],
58
+ contiguous_input[..., sort_permutation[0]],
59
+ old_locations[sort_permutation[1]],
60
+ contiguous_input[..., sort_permutation[1]],
61
+ )
62
+ slope_right = get_slope(
63
+ old_locations[sort_permutation[old_dims - 1]],
64
+ contiguous_input[..., sort_permutation[old_dims - 1]],
65
+ old_locations[sort_permutation[old_dims - 2]],
66
+ contiguous_input[..., sort_permutation[old_dims - 2]],
67
+ )
68
+
69
+ bias_left = contiguous_input[..., sort_permutation[0]] - slope_left * old_locations[sort_permutation[0]]
70
+ bias_right = (
71
+ contiguous_input[..., sort_permutation[old_dims - 1]]
72
+ - slope_right * old_locations[sort_permutation[old_dims - 1]]
73
+ )
74
+
75
+ for i in prange(rows):
76
+ for j in prange(cols):
77
+ for k in prange(dims):
78
+ if extr[k] == 0:
79
+ interpolated[i, j, k] = (
80
+ contiguous_input[i, j, sort_permutation[max_idxs[k] - 1]] * (1 - dd[k])
81
+ + contiguous_input[i, j, sort_permutation[max_idxs[k]]] * dd[k]
82
+ )
83
+ elif extrapolate:
84
+ if extr[k] == 1:
85
+ interpolated[i, j, k] = slope_right[i, j] * new_locations[k] + bias_right[i, j]
86
+ else:
87
+ interpolated[i, j, k] = slope_left[i, j] * new_locations[k] + bias_left[i, j]
88
+ else:
89
+ interpolated[i, j, k] = fill_value
90
+
91
+ return interpolated
92
+
93
+
94
+ @njit(nogil=True)
95
+ def get_slope(x1: np.ndarray, y1: np.ndarray, x2: np.ndarray, y2: np.ndarray) -> np.ndarray:
96
+ return (y2 - y1) / (x2 - x1)
97
+
98
+
99
+ @njit(nogil=True)
100
+ def get_pixel3d(
101
+ input: np.ndarray, rows: int, cols: int, dims: int, r: int, c: int, d: int, cval: float_or_int
102
+ ) -> float_or_int:
103
+ if 0 <= r < rows and 0 <= c < cols and 0 <= d < dims:
104
+ return input[r, c, d]
105
+
106
+ return cval
107
+
108
+
109
+ @njit(nogil=True)
110
+ def get_pixel4d(
111
+ input: np.ndarray,
112
+ dim1: int,
113
+ dim2: int,
114
+ dim3: int,
115
+ dim4: int,
116
+ c1: int,
117
+ c2: int,
118
+ c3: int,
119
+ c4: int,
120
+ cval: float_or_int,
121
+ ) -> float_or_int:
122
+ if 0 <= c1 < dim1 and 0 <= c2 < dim2 and 0 <= c3 < dim3 and 0 <= c4 < dim4:
123
+ return input[c1, c2, c3, c4]
124
+
125
+ return cval
126
+
127
+
128
+ @njit(nogil=True)
129
+ def adjusted_coef(old_n: int, new_n: int) -> float:
130
+ if new_n == 1:
131
+ return old_n
132
+ return (np.float64(old_n) - 1) / (np.float64(new_n) - 1)
133
+
134
+
135
+ @njit(nogil=True)
136
+ def distance3d(x1: float, y1: float, z1: float, x2: float, y2: float, z2: float) -> float:
137
+ return ((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2) ** 0.5
138
+
139
+
140
+ @njit(nogil=True)
141
+ def distance4d(x1: float, y1: float, z1: float, d1: float, x2: float, y2: float, z2: float, d2: float) -> float:
142
+ return ((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2 + (d1 - d2) ** 2) ** 0.5
143
+
144
+
145
+ @njit(nogil=True)
146
+ def interpolate3d_linear(
147
+ input: np.ndarray, rows: int, cols: int, dims: int, r: float, c: float, d: float, cval: float
148
+ ) -> float:
149
+ minr = int(r)
150
+ minc = int(c)
151
+ mind = int(d)
152
+ maxr = minr + 1
153
+ maxc = minc + 1
154
+ maxd = mind + 1
155
+
156
+ dr = r - minr
157
+ dc = c - minc
158
+ dd = d - mind
159
+
160
+ c000 = get_pixel3d(input, rows, cols, dims, minr, minc, mind, cval)
161
+ c001 = get_pixel3d(input, rows, cols, dims, minr, minc, maxd, cval)
162
+ c010 = get_pixel3d(input, rows, cols, dims, minr, maxc, mind, cval)
163
+ c011 = get_pixel3d(input, rows, cols, dims, minr, maxc, maxd, cval)
164
+ c100 = get_pixel3d(input, rows, cols, dims, maxr, minc, mind, cval)
165
+ c101 = get_pixel3d(input, rows, cols, dims, maxr, minc, maxd, cval)
166
+ c110 = get_pixel3d(input, rows, cols, dims, maxr, maxc, mind, cval)
167
+ c111 = get_pixel3d(input, rows, cols, dims, maxr, maxc, maxd, cval)
168
+
169
+ c00 = c000 * (1 - dr) + c100 * dr
170
+ c01 = c001 * (1 - dr) + c101 * dr
171
+ c10 = c010 * (1 - dr) + c110 * dr
172
+ c11 = c011 * (1 - dr) + c111 * dr
173
+
174
+ c0 = c00 * (1 - dc) + c10 * dc
175
+ c1 = c01 * (1 - dc) + c11 * dc
176
+
177
+ return c0 * (1 - dd) + c1 * dd
178
+
179
+
180
+ @njit(nogil=True)
181
+ def interpolate3d_nearest(
182
+ input: np.ndarray, rows: int, cols: int, dims: int, r: float, c: float, d: float, cval: float_or_int
183
+ ) -> float_or_int:
184
+ min_distance = 3.0
185
+ i_nearest, j_nearest, k_nearest = -1, -1, -1
186
+
187
+ minr = int(r)
188
+ minc = int(c)
189
+ mind = int(d)
190
+ maxr = minr + 1
191
+ maxc = minc + 1
192
+ maxd = mind + 1
193
+
194
+ for i in range(2):
195
+ curr = maxr if i else minr
196
+ if curr >= rows:
197
+ continue
198
+ for j in range(2):
199
+ curc = maxc if j else minc
200
+ if curc >= cols:
201
+ continue
202
+ for k in range(2):
203
+ curd = maxd if k else mind
204
+ if curd >= dims:
205
+ continue
206
+
207
+ distance = distance3d(r, c, d, curr, curc, curd)
208
+
209
+ if distance <= min_distance:
210
+ i_nearest = i
211
+ j_nearest = j
212
+ k_nearest = k
213
+ min_distance = distance
214
+
215
+ if i_nearest == -1 or j_nearest == -1 or k_nearest == -1:
216
+ return cval
217
+
218
+ return get_pixel3d(
219
+ input,
220
+ rows,
221
+ cols,
222
+ dims,
223
+ maxr if i_nearest else minr,
224
+ maxc if j_nearest else minc,
225
+ maxd if k_nearest else mind,
226
+ cval,
227
+ )
228
+
229
+
230
+ @njit(nogil=True)
231
+ def interpolate4d_linear(
232
+ input: np.ndarray,
233
+ dim1: int,
234
+ dim2: int,
235
+ dim3: int,
236
+ dim4: int,
237
+ c1: int,
238
+ c2: int,
239
+ c3: int,
240
+ c4: int,
241
+ cval: float,
242
+ ) -> float:
243
+ minc1 = int(c1)
244
+ minc2 = int(c2)
245
+ minc3 = int(c3)
246
+ minc4 = int(c4)
247
+ maxc1 = minc1 + 1
248
+ maxc2 = minc2 + 1
249
+ maxc3 = minc3 + 1
250
+ maxc4 = minc4 + 1
251
+
252
+ dc1 = c1 - minc1
253
+ dc2 = c2 - minc2
254
+ dc3 = c3 - minc3
255
+ dc4 = c4 - minc4
256
+
257
+ c0000 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, minc2, minc3, minc4, cval)
258
+ c0001 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, minc2, minc3, maxc4, cval)
259
+ c0010 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, minc2, maxc3, minc4, cval)
260
+ c0011 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, minc2, maxc3, maxc4, cval)
261
+ c0100 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, maxc2, minc3, minc4, cval)
262
+ c0101 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, maxc2, minc3, maxc4, cval)
263
+ c0110 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, maxc2, maxc3, minc4, cval)
264
+ c0111 = get_pixel4d(input, dim1, dim2, dim3, dim4, minc1, maxc2, maxc3, maxc4, cval)
265
+ c1000 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, minc2, minc3, minc4, cval)
266
+ c1001 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, minc2, minc3, maxc4, cval)
267
+ c1010 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, minc2, maxc3, minc4, cval)
268
+ c1011 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, minc2, maxc3, maxc4, cval)
269
+ c1100 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, maxc2, minc3, minc4, cval)
270
+ c1101 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, maxc2, minc3, maxc4, cval)
271
+ c1110 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, maxc2, maxc3, minc4, cval)
272
+ c1111 = get_pixel4d(input, dim1, dim2, dim3, dim4, maxc1, maxc2, maxc3, maxc4, cval)
273
+
274
+ c000 = c0000 * (1 - dc1) + c1000 * dc1
275
+ c001 = c0001 * (1 - dc1) + c1001 * dc1
276
+ c010 = c0010 * (1 - dc1) + c1010 * dc1
277
+ c011 = c0011 * (1 - dc1) + c1011 * dc1
278
+ c100 = c0100 * (1 - dc1) + c1100 * dc1
279
+ c101 = c0101 * (1 - dc1) + c1101 * dc1
280
+ c110 = c0110 * (1 - dc1) + c1110 * dc1
281
+ c111 = c0111 * (1 - dc1) + c1111 * dc1
282
+
283
+ c00 = c000 * (1 - dc2) + c100 * dc2
284
+ c01 = c001 * (1 - dc2) + c101 * dc2
285
+ c10 = c010 * (1 - dc2) + c110 * dc2
286
+ c11 = c011 * (1 - dc2) + c111 * dc2
287
+
288
+ c0_ = c00 * (1 - dc3) + c10 * dc3
289
+ c1_ = c01 * (1 - dc3) + c11 * dc3
290
+
291
+ return c0_ * (1 - dc4) + c1_ * dc4
292
+
293
+
294
+ @njit(nogil=True)
295
+ def interpolate4d_nearest(
296
+ input: np.ndarray,
297
+ dim1: int,
298
+ dim2: int,
299
+ dim3: int,
300
+ dim4: int,
301
+ c1: float,
302
+ c2: float,
303
+ c3: float,
304
+ c4: float,
305
+ cval: float_or_int,
306
+ ) -> float_or_int:
307
+ min_distance = 3.0
308
+ i1_nearest, i2_nearest, i3_nearest, i4_nearest = -1, -1, -1, -1
309
+ minc1 = int(c1)
310
+ minc2 = int(c2)
311
+ minc3 = int(c3)
312
+ minc4 = int(c4)
313
+ maxc1 = minc1 + 1
314
+ maxc2 = minc2 + 1
315
+ maxc3 = minc3 + 1
316
+ maxc4 = minc4 + 1
317
+
318
+ for i1 in range(2):
319
+ curc1 = maxc1 if i1 else minc1
320
+ if curc1 >= dim1:
321
+ continue
322
+ for i2 in range(2):
323
+ curc2 = maxc2 if i2 else minc2
324
+ if curc2 >= dim2:
325
+ continue
326
+ for i3 in range(2):
327
+ curc3 = maxc3 if i3 else minc3
328
+ if curc3 >= dim3:
329
+ continue
330
+ for i4 in range(2):
331
+ curc4 = maxc4 if i4 else minc4
332
+ if curc4 >= dim4:
333
+ continue
334
+
335
+ distance = distance4d(c1, c2, c3, c4, curc1, curc2, curc3, curc4)
336
+ if distance <= min_distance:
337
+ i1_nearest = i1
338
+ i2_nearest = i2
339
+ i3_nearest = i3
340
+ i4_nearest = i4
341
+ min_distance = distance
342
+
343
+ if i1_nearest == -1 or i2_nearest == -1 or i3_nearest == -1 or i4_nearest == -1:
344
+ return cval
345
+
346
+ return get_pixel4d(
347
+ input,
348
+ dim1,
349
+ dim2,
350
+ dim3,
351
+ dim4,
352
+ maxc1 if i1_nearest else minc1,
353
+ maxc2 if i2_nearest else minc2,
354
+ maxc3 if i3_nearest else minc3,
355
+ maxc4 if i4_nearest else minc4,
356
+ cval,
357
+ )
358
+
359
+
360
+ def _zoom3d_linear(input: np.ndarray, zoom: np.ndarray, cval: float) -> np.ndarray:
361
+ contiguous_input = np.ascontiguousarray(input)
362
+
363
+ old_rows, old_cols, old_dims = input.shape
364
+ row_coef, col_coef, dim_coef = zoom
365
+
366
+ new_shape = (round(old_rows * row_coef), round(old_cols * col_coef), round(old_dims * dim_coef))
367
+ new_rows, new_cols, new_dims = new_shape
368
+
369
+ zoomed = np.zeros(new_shape, dtype=input.dtype)
370
+
371
+ adjusted_row_coef = adjusted_coef(old_rows, new_rows)
372
+ adjusted_col_coef = adjusted_coef(old_cols, new_cols)
373
+ adjusted_dim_coef = adjusted_coef(old_dims, new_dims)
374
+
375
+ for i in prange(new_rows):
376
+ for j in prange(new_cols):
377
+ for k in prange(new_dims):
378
+ zoomed[i, j, k] = interpolate3d_linear(
379
+ contiguous_input,
380
+ old_rows,
381
+ old_cols,
382
+ old_dims,
383
+ i * adjusted_row_coef,
384
+ j * adjusted_col_coef,
385
+ k * adjusted_dim_coef,
386
+ cval,
387
+ )
388
+
389
+ return zoomed
390
+
391
+
392
+ def _zoom3d_nearest(input: np.ndarray, zoom: np.ndarray, cval: float_or_int) -> np.ndarray:
393
+ contiguous_input = np.ascontiguousarray(input)
394
+
395
+ old_rows, old_cols, old_dims = input.shape
396
+ row_coef, col_coef, dim_coef = zoom
397
+
398
+ new_shape = (round(old_rows * row_coef), round(old_cols * col_coef), round(old_dims * dim_coef))
399
+ new_rows, new_cols, new_dims = new_shape
400
+
401
+ zoomed = np.zeros(new_shape, dtype=input.dtype)
402
+
403
+ adjusted_row_coef = adjusted_coef(old_rows, new_rows)
404
+ adjusted_col_coef = adjusted_coef(old_cols, new_cols)
405
+ adjusted_dim_coef = adjusted_coef(old_dims, new_dims)
406
+
407
+ for i in prange(new_rows):
408
+ for j in prange(new_cols):
409
+ for k in prange(new_dims):
410
+ zoomed[i, j, k] = interpolate3d_nearest(
411
+ contiguous_input,
412
+ old_rows,
413
+ old_cols,
414
+ old_dims,
415
+ i * adjusted_row_coef,
416
+ j * adjusted_col_coef,
417
+ k * adjusted_dim_coef,
418
+ cval,
419
+ )
420
+
421
+ return zoomed
422
+
423
+
424
+ def _zoom4d_linear(input: np.ndarray, zoom: np.ndarray, cval: float) -> np.ndarray:
425
+ contiguous_input = np.ascontiguousarray(input)
426
+
427
+ old_dim1, old_dim2, old_dim3, old_dim4 = input.shape
428
+ dim1_coef, dim2_coef, dim3_coef, dim4_coef = zoom
429
+
430
+ new_shape = (
431
+ round(old_dim1 * dim1_coef),
432
+ round(old_dim2 * dim2_coef),
433
+ round(old_dim3 * dim3_coef),
434
+ round(old_dim4 * dim4_coef),
435
+ )
436
+ new_dim1, new_dim2, new_dim3, new_dim4 = new_shape
437
+
438
+ zoomed = np.zeros(new_shape, dtype=input.dtype)
439
+
440
+ adjusted_dim1_coef = adjusted_coef(old_dim1, new_dim1)
441
+ adjusted_dim2_coef = adjusted_coef(old_dim2, new_dim2)
442
+ adjusted_dim3_coef = adjusted_coef(old_dim3, new_dim3)
443
+ adjusted_dim4_coef = adjusted_coef(old_dim4, new_dim4)
444
+
445
+ for i1 in prange(new_dim1):
446
+ for i2 in prange(new_dim2):
447
+ for i3 in prange(new_dim3):
448
+ for i4 in prange(new_dim4):
449
+ zoomed[i1, i2, i3, i4] = interpolate4d_linear(
450
+ contiguous_input,
451
+ old_dim1,
452
+ old_dim2,
453
+ old_dim3,
454
+ old_dim4,
455
+ i1 * adjusted_dim1_coef,
456
+ i2 * adjusted_dim2_coef,
457
+ i3 * adjusted_dim3_coef,
458
+ i4 * adjusted_dim4_coef,
459
+ cval,
460
+ )
461
+
462
+ return zoomed
463
+
464
+
465
+ def _zoom4d_nearest(input: np.ndarray, zoom: np.ndarray, cval: float_or_int) -> np.ndarray:
466
+ contiguous_input = np.ascontiguousarray(input)
467
+
468
+ old_dim1, old_dim2, old_dim3, old_dim4 = input.shape
469
+ dim1_coef, dim2_coef, dim3_coef, dim4_coef = zoom
470
+
471
+ new_shape = (
472
+ round(old_dim1 * dim1_coef),
473
+ round(old_dim2 * dim2_coef),
474
+ round(old_dim3 * dim3_coef),
475
+ round(old_dim4 * dim4_coef),
476
+ )
477
+ new_dim1, new_dim2, new_dim3, new_dim4 = new_shape
478
+
479
+ zoomed = np.zeros(new_shape, dtype=input.dtype)
480
+
481
+ adjusted_dim1_coef = adjusted_coef(old_dim1, new_dim1)
482
+ adjusted_dim2_coef = adjusted_coef(old_dim2, new_dim2)
483
+ adjusted_dim3_coef = adjusted_coef(old_dim3, new_dim3)
484
+ adjusted_dim4_coef = adjusted_coef(old_dim4, new_dim4)
485
+
486
+ for i1 in prange(new_dim1):
487
+ for i2 in prange(new_dim2):
488
+ for i3 in prange(new_dim3):
489
+ for i4 in prange(new_dim4):
490
+ zoomed[i1, i2, i3, i4] = interpolate4d_nearest(
491
+ contiguous_input,
492
+ old_dim1,
493
+ old_dim2,
494
+ old_dim3,
495
+ old_dim4,
496
+ i1 * adjusted_dim1_coef,
497
+ i2 * adjusted_dim2_coef,
498
+ i3 * adjusted_dim3_coef,
499
+ i4 * adjusted_dim4_coef,
500
+ cval,
501
+ )
502
+
503
+ return zoomed