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