Size: 6849
Comment:
|
Size: 6853
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 101: | Line 101: |
{{{$$p(x,y) = int T M(x,y,z) dz$$}}} | {{{$$p(x,y) = int_z T3D M(x,y,z) dz$$}}} |
Transformations in EMAN2
The Transform3D Class
EMAN2 uses the [http://blake.bcm.edu/eman2/doxygen_html/classEMAN_1_1Transform3D.html Transform3D] class for storing/managing Euler angles and translations. At any time a Transform3D ($$T3D) object defines a group of 3 affine transformations that are applied in a specific order, namely
$$T3D \equiv T_{post} R T_{pre}$$
Where $$T_{pre} is a pre translation, $$R$$ is a rotation and $$T_{post} is a post translation. The Transform3D object stores these transformations internally in a 4x4 matrix, as is commonly the case in computer graphics applications that use homogeneous coordinate systems (i.e. OpenGL). In these approaches the 4x4 transformation matrix $$T3D$$ is constructed in this way
$$T3D = [[R,\hat{t}],[\hat{0}^T,1]]$$
Where R is a $$3x3$$ rotation matrix and $$\hat{t}=(dx,dy,dz)^T$$ is a post translation. In this approach a 3D point $$\hat{p}=(x,y,z)^T$$ as represented in homogeneous coordinates as a 4D vector $$\hat{p_{hc}}=(x,y,z,1)^T$$ and is multiplied against the matrix $$M$$ to produce the result of applying the transformation
$$ T3D \hat{p}_{hc} = ( R\hat{p} + \hat{t}, 1 )^T $$
In this way the result of applying a Transform3D to a vector is literally a rotation follow by a translation. The Transform3D allows for both pre and post translation and stores the cumulative result internally
$$T3D = T_{post} R T_{pre} = [[I,\hat{t}_{post}],[\hat{0}^T,1]] [[R,\hat{0}],[\hat{0}^T,1]] [[I,\hat{t}_{pre}],[\hat{0}^T,1]] = [[R,R\hat{t}_{pre}+\hat{t}_{post}],[\hat{0}^T,1]]$$
Constructing a Transform3D Object In Python
In Python you can construct a Transform3D object in a number of ways
1 from EMAN2 import Transform3D
2 t = Transform3D() # t is the identity
3 t = Transfrom3D(EULER_EMAN,25,45,65) # EULER_EMAN rotation convention uses the az, alt, phi
4 t = Transform3D(EULER_SPIDER,24,44,64) # EULER_SPIDER rotation convention uses the phi, theta, psi convention
5 t = Transform3D(25,45,65) # EULER_EMAN convention used by default, arguments are taken as az, alt, phi
6 t = Transform3D(Vec3f(1,2,3),25,45,65,Vec3f(4,5,6)) # Specify a pre trans, followed by EULER_EMAN convention rotations az, alt, phi, followed by the post trans
7 t = Transform3D(25,45,65,Vec3f(4,5,6)) # EULER_EMAN convention rotations az, alt, phi, followed by the post trans
8 t = Transform3D(1,0,0,0,1,0,0,0,1) # Explicitly setting the nine members of the rotation matrix, row wise.
9 s = Transform3D(t) # copy constructor
Setting Transform3D Rotations and Translation Attributes in Python
You can set the pre and post translations, as well as the rotations, directly from Python
1 from EMAN2 import Transform3D
2 t = Transform3D()
3 # setting the rotations
4 t.set_rotation(25,45,65) # EULER_EMAN convention rotations az, alt, phi
5 t.set_rotation(EULER_SPIDER,24,44,64) # EULER_SPIDER rotation convention uses the phi, theta, psi convention
6 t.set_rotation(EULER_EMAN, {"az":25,"alt":45,"phi":65}) # Optional dictionary style approach
7 t.set_rotation(1,0,0,0,1,0,0,0,1) # Explicitly set the nine members of the rotation matrix, row wise.
8 # setting translations
9 t.set_pretrans(1,2,3)# pre translation dx, dy, dz
10 t.set_pretrans(Vec3f(1,2,3)) # also takes Vec3f argument
11 t.set_pretrans([1,2,3]) # also takes tuple argument
12 t.set_posttrans(4,5,6)# post translation dx, dy, dz
13 t.set_posttrans(Vec3f(4,5,6)) # also takes Vec3f argument
14 t.set_posttrans([4,5,6]) # also takes tuple argument
Getting Transform3D Rotations and Translation Attributes in Python
You can get these attributes using similar syntax to that employed for the setter methods
1 from EMAN2 import Transform3D
2 t = Transform3D(Vec3f(1,2,3),25,45,65,Vec3f(4,5,6)) # Specify a pre trans, followed by EULER_EMAN convention rotations az, alt, phi, followed by the post trans
3 # get rotations
4 dictionary = t.get_rotation(EULER_EMAN) # returns a dictionary with keys "az", "alt" and "phi"
5 dictionary = t.get_rotation(EULER_SPIDER) # returns a dictionary with keys "phi", "theta" and "psi"
6 # get translations
7 vector = t.get_pretrans() # Returns a Vec3f object containing the translation
8 vector = t.get_posttrans() # Returns a Vec3f object containing the translation
Multiplication
Transform3D Times a Transform3D
The main thing to consider when multiplying two Transform3D objects is what will be the ultimate result of asking for the pre_trans and post_trans vectors from Python. To answer this question we look at the details
$$T3D_{2} T3D_{1} = T_{2,post} R_{2} T_{2,pre} T_{1,post} R_{1} T_{1,pre} = T_{2,post} R_{2} T_{2,pre}[[R_{1},R_{1}\hat{t}_{1,pre}+\hat{t}_{1,post}],[\hat{0}^T,1]]$$
$$ = T_{2,post} R_{2} [[R_{1},R_{1}\hat{t}_{1,pre}+\hat{t}_{1,post}+\hat{t}_{2,pre}],[\hat{0}^T,1]]$$
The translation in right column ($$R_{1}\hat{t}_{1,pre}+\hat{t}_{1,post}+\hat{t}_{2,pre}$$) is now what will be returned when the Transform3D object is asked for its pre_translation vector from python. Similarly, the post translation vector of $$T3D_{2}$$ will now be returned by a call to get_postrans. To complete the details, internally the Transform3D object will look like
$$ T3D_{2} T3D_{1} = [[ R_{2}R_{1},R_{2}(R_{1}\hat{t}_{1,pre}+\hat{t}_{1,post}+\hat{t}_{2,pre})+\hat{t}_{2,post}],[\hat{0}^T,1]]$$
Transform3D Times a Vector
If v is a three dimensional vector encapsulated as a Vec3f then one can right multiply it by a Transform3D object and this achieves the following result
$$T3D v = [[R,\hat{t}],[\hat{0}^T,1]] v $$
$$T3D v = Rv+t $$
The vector v is treated implicitly as though it were an homogeneous coordinate, but the last row of the matrix-vector multiplication is not performed.
Transformations and projections
Say the data model is a 3D map denoted M(x,y,z) and a projection is to be generated in a particular direction. The model may also be pre and/or post translated as part of the projection process. The translation information along with the direction of the projection is to be stored in a Transform3D object T, and the projection is to be generated according to or equivalently to the following
$$p(x,y) = int_z T3D M(x,y,z) dz$$
That is, the projection is generated by first transforming the 3D map M by the Transform3D object, and proceeded by taking line integrals along z.
Transformations and recontructors
In order to insert a projection as generated in the conventional way (above) into a 3D volume in the correct orientation, one must invert the Transform3D object that was used to generate the projection prior to slice insertion.