1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ # Multiscale transformation checks.
5
+
6
+ This is a test to make sure that the transforms are propagated correctly to reduced scales in a multiscale representation.
7
+
8
+ The coordinates represent the center of a pixel.
9
+ The transform will transform a coordinate to "real space".
10
+
11
+ r = s*p + t
12
+
13
+ p, pixel location. t is the translate portion of the transform. s is the scale.
14
+
15
+ Each scale will have it's own set of pixels, transform, and scale. pi, ti, si respectivly.
16
+ s0 is the original scale factor, it is often used to describe the size of a voxel.
17
+
18
+ The downsampling factor is the ratio of original pixels to scaled pixels.
19
+
20
+ f = ( D0/D1, H0/H1, W0/W1 )
21
+
22
+ The volume will cover the same real volume, so the ratio of the scale factors will be
23
+ the downsampling used.
24
+
25
+ s1 = f * s0
26
+
27
+ To find the translation volume begins in the same pixel location for any resolution:
28
+
29
+ pi = (-0.5, -0.5, -0.5)
30
+
31
+ Then we can solve.
32
+
33
+ -0.5s0 + t0 = -0.5*s1 + t1
34
+
35
+ t1 = t0 + 0.5*(s1 - s0)
36
+ t1 = t0 + 0.5*(f - 1)s0
37
+
38
+ """
39
+
40
+ import ngff_zarr , numpy
41
+
42
+ import pytest
43
+
44
+
45
+ def checkTransformation ( metaTransformations , expected ):
46
+ #must contain scale as first transform v04.
47
+ scale = metaTransformations [0 ]
48
+ assert scale .type == "scale"
49
+ for a , b in zip (scale .scale , expected [0 ]):
50
+ assert a == b
51
+ #optional scale
52
+ if len (expected ) == 1 :
53
+ return
54
+
55
+ translation = metaTransformations [1 ]
56
+
57
+ assert translation .type == "translation"
58
+
59
+ for a , b in zip (translation .translation , expected [1 ]):
60
+ assert a == b ;
61
+
62
+ def test_multiscale_translate ():
63
+ #input
64
+ dims = ["t" , "c" , "z" , "y" , "x" ]
65
+ scale = { "t" :60 , "c" :1 , "z" :2 , "y" :0.35 , "x" :0.35 }
66
+ translation = { "t" :0 , "c" :0 , "z" :10 , "y" :20 , "x" :30 }
67
+ scale_factors = {'x' :2 , 'y' :2 , 'z' :1 }
68
+ image_shape = (3 , 2 , 32 , 64 , 64 )
69
+
70
+ #generation
71
+ arr = numpy .zeros ( image_shape , dtype = "uint8" )
72
+ image = ngff_zarr .ngff_image .NgffImage ( arr , dims , scale = scale , translation = translation )
73
+ multiscales = ngff_zarr .to_multiscales (image , scale_factors = [scale_factors ])
74
+
75
+ #checking the values of the ngff image.
76
+ os = multiscales .images [0 ].scale
77
+ ot = multiscales .images [0 ].translation
78
+
79
+ ns = multiscales .images [1 ].scale
80
+ nt = multiscales .images [1 ].translation
81
+
82
+ for key in scale_factors :
83
+ t1 = ot [key ] + 0.5 * (scale_factors [key ] - 1 )* os [key ]
84
+ s1 = os [key ]* scale_factors [key ]
85
+ assert nt [key ] == t1
86
+ assert ns [key ] == s1
87
+
88
+ #check values found in the metadata
89
+ datasets = multiscales .metadata .datasets
90
+ set0 = datasets [0 ]
91
+ set1 = datasets [1 ]
92
+
93
+ original = [ [ scale [k ] for k in dims ], [translation [k ] for k in dims ] ]
94
+
95
+ #Newly generated scale values.
96
+ scale1 = {}
97
+ translation1 = {}
98
+
99
+ for k in dims :
100
+ if k in scale_factors :
101
+ scale1 [k ] = scale [k ]* scale_factors [k ]
102
+ translation1 [k ] = translation [k ] + 0.5 * ( scale_factors [k ] - 1 )* scale [k ]
103
+ else :
104
+ scale1 [k ] = 1
105
+ translation1 [k ] = 0
106
+
107
+ scaled = [ [ scale1 [k ] for k in dims ], [translation1 [k ] for k in dims ] ]
108
+
109
+ checkTransformation (set0 .coordinateTransformations , original )
110
+ checkTransformation (set1 .coordinateTransformations , scaled )
0 commit comments