Size: 148
Comment:
|
Size: 13505
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
== Transforms in the context of Projections, Reconstructions, and in General == === Transforming an EMData Object === When an EMData object |
[[TableOfContents]] = Transformations in EMAN2 = == Helpful Links == For a more information on the contents of 3D rotation matrices please consult the Sparx [http://macro-em.org/sparxwiki/Euler_angles Euler Angles] page. == 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 transformations of a rigid body 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,\mathbf{t}],[\mathbf{0}^T,1]]$$}}} Where R is a {{{$$3x3$$}}} rotation matrix and {{{$$\mathbf{t}=(dx,dy,dz)^T$$}}} is a post translation. In this approach a 3D point {{{$$\mathbf{p}=(x,y,z)^T$$}}} as represented in homogeneous coordinates as a 4D vector {{{$$\mathbf{p}_{hc}=(x,y,z,1)^T$$}}} and is multiplied by the matrix {{{$$M$$}}} to produce the result of applying the transformation {{{$$ T3D \mathbf{p}_{hc} = ( (R\mathbf{p} + \mathbf{t})^T, 1 )^T $$}}} In this way the result of applying a Transform3D to a vector is literally a rotation followed 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,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R,\mathbf{0}],[\mathbf{0}^T,1]] [[I,\mathbf{t}_{pre}],[\mathbf{0}^T,1]] = [[R,R\mathbf{t}_{pre}+\mathbf{t}_{post}],[\mathbf{0}^T,1]]$$}}} === Constructing a Transform3D object in Python === In Python you can construct a Transform3D object in a number of ways {{{#!python from EMAN2 import Transform3D t = Transform3D() # t is the identity t = Transfrom3D(EULER_EMAN,25,45,65) # EULER_EMAN rotation convention uses the az, alt, phi t = Transform3D(EULER_SPIDER,24,44,64) # EULER_SPIDER rotation convention uses the phi, theta, psi convention t = Transform3D(25,45,65) # EULER_EMAN convention used by default, arguments are taken as az, alt, phi 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 t = Transform3D(25,45,65,Vec3f(4,5,6)) # EULER_EMAN convention rotations az, alt, phi, followed by the post trans t = Transform3D(1,0,0,0,1,0,0,0,1) # Explicitly setting the nine members of the rotation matrix, row wise. 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 {{{#!python from EMAN2 import Transform3D t = Transform3D() # setting the rotations t.set_rotation(25,45,65) # EULER_EMAN convention rotations az, alt, phi t.set_rotation(EULER_SPIDER,24,44,64) # EULER_SPIDER rotation convention uses the phi, theta, psi convention t.set_rotation(EULER_EMAN, {"az":25,"alt":45,"phi":65}) # Optional dictionary style approach t.set_rotation(1,0,0,0,1,0,0,0,1) # Explicitly set the nine members of the rotation matrix, row wise. # setting translations t.set_pretrans(1,2,3)# pre translation dx, dy, dz t.set_pretrans(Vec3f(1,2,3)) # also takes Vec3f argument t.set_pretrans([1,2,3]) # also takes tuple argument t.set_posttrans(4,5,6)# post translation dx, dy, dz t.set_posttrans(Vec3f(4,5,6)) # also takes Vec3f argument 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 {{{#!python from EMAN2 import Transform3D 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 # get rotations dictionary = t.get_rotation(EULER_EMAN) # returns a dictionary with keys "az", "alt" and "phi" dictionary = t.get_rotation(EULER_SPIDER) # returns a dictionary with keys "phi", "theta" and "psi" # get translations vector = t.get_pretrans() # Returns a Vec3f object containing the translation 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 of the resulting Transform3D object ({{{$$T3D_{rst}$$}}}). To answer this question we look at the details {{{$$T3D_{rst} = 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}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}],[\mathbf{0}^T,1]]$$}}} {{{$$ = T_{2,post} R_{2} [[R_{1},R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre}],[\mathbf{0}^T,1]]$$}}} The translation in right column ({{{$$R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre}$$}}}) is now what will be returned when {{{$$T3D_{rst}$$}}} is asked for its pre_translation vector from python (or C++). Similarly, the post translation vector of {{{$$T3D_{2}$$}}} will now be returned by calling get_postrans on {{{$$T3D_{rst}$$}}}. To complete the details, internally the Transform3D object will look like {{{$$ T3D_{rst} = [[ R_{2}R_{1},R_{2}(R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre})+\mathbf{t}_{2,post}],[\mathbf{0}^T,1]]$$}}} In Python the Transfrom3D x Transform3D operation can be achieved using the '*' operator {{{#!python T1 = 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 T2 = Transform3D(25,45,65,Vec3f(4,5,6)) # EULER_EMAN convention rotations az, alt, phi, followed by the post trans Trst = T2*T1 }}} === Transform3D times a 3D vector (Vec3f) === 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 \mathbf{v} = [[R,R\mathbf{t}_{pre}+\mathbf{t}_{post}],[\mathbf{0}^T,1]] \mathbf{v} $$}}} {{{$$T3D \mathbf{v} = Rv+R\mathbf{t}_{pre}+\mathbf{t}_{post} $$}}} The vector v is treated implicitly as though it were an homogeneous point, but the last row of the matrix-vector multiplication is not performed. In Python the Transfrom3D x Vec3f operation can be achieved using the '*' operator or by calling the Transform3D::transform(Vec3f) function {{{#!python 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 v = Vec3f(1,2,3) # for example, pixel coordinates 1,2,3 v_dash = T*v v_dash = T.transform(v) # Achieves the same result as calling T*v }}} === Explicitly rotating a 3D vector (Vec3f) === If a Transform3D is represented as {{{$$T3D = [[R,\mathbf{t}],[\mathbf{0}^T,1]]$$}}} One can calculate {{{$$\mathbf{v}_R = R \mathbf{v}$$}}} in Python by doing {{{#!python 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 v = Vec3f(1,2,3) # for example, pixel coordinates 1,2,3 v_R = T.rotate(v) }}} = 2D image alignment conventions = == The xform.align2d header attribute == The "xform.align2d" EMData attribute stores a Transform3D object denoted here as {{{$$T3D_{ali2D}$$}}}, which represents the alignment of the 2D Image {{{$$M(x,y)$$}}}, as given by the following {{{$$ M(x,y)_{ali} = T3D_{ali2D} M(x,y) $$}}} Where {{{$$ M(x,y)_{ali}$$}}} denotes the aligned image. The Transform3D object has been designed to allow for application of 2D transformations. The internal transformation matrix of Transform3D object that stores only 2D alignment parameters {{{$$T3D_{ali2D}$$}}} appears just as any other Transform3D object {{{$$T3D_{ali2D} = T_{post} R T_{pre} = [[I,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R,\mathbf{0}],[\mathbf{0}^T,1]] [[I,\mathbf{t}_{pre}],[\mathbf{0}^T,1]] $$}}} However the rotation and translations can be made 'psuedo-2D', more specifically {{{$$ R = [[cos phi,sin phi, 0],[-sin phi,cos phi,0],[0,0,1]], \mathbf{t}_{pre} = (dx_{pre},dy_{pre},0)^T, \mathbf{t}_{post} = (dx_{post},dy_{post},0)^T $$}}} == Creating Transform3D objects that describe 2D transformations == To construct "pseudo-2D" Transform3D objects in Python you can use any of the following approaches {{{#!python from EMAN2 import Transform3D # set the rotation t = Transform3D(0,0,25) # 25 is phi t = Transform3D(EULER_SPIDER 0,0,24) # 24 is psi which is equivalent to setting phi # set pre and post trans t.set_pretrans(2,3) # pre translation dx and dy t.set_pretrans(Vec2f(2,3)) # use Vec2f instead t.set_posttrans(-1,-10) # post translation dx and dy t.set_posttrans(Vec2f(-1,-10)) # use Vec2f instead }}} == Transform3D times a 2D vector (Vec2f) == A Vec2f, an EMAN2 object that stores two values {{{$$v_x$$}}} and {{{$$v_y$$}}}, may be right multiplied against a Transform3D object to efficiently calculate transformed 2D coordinates. {{{$$ T3D_{ali2D} \dot \mathbf(Vec2f) \equiv [[cos phi,sin phi, cos phi * dx_{pre} + sin phi * dy_{pre} + dx_{post}],[-sin phi,cos phi,-sin phi * dx_{pre} + cos phi * dy_{pre} + dy_{post}],[0,0,1]] ((v_x),(v_y),(1)) $$}}} The 2D coordinates are multiplied by the internal transformation matrix in the Transform3D to mimic 2D transformation. The Transform3D object is not checked to ensure it describes a single (phi) rotation or whether the current translations are purely 2D. This responsibility is left to the programmer. Here is an example of doing Transform3D times Vec2f in Python {{{#!python from EMAN2 import Transform3D # make a Transform3D that can be used as a 2D transformation t = Transform3D(0,0,25) # 25 is phi t.set_pretrans(Vec2f(2,3)) # use Vec2f instead t.set_posttrans(Vec2f(-1,-10)) # use Vec2f instead v = Vec2f(2,3) # for example, pixel coordinate 2,3 v_trans = t*v # calculates the 2D transformation }}} = 3D image alignment conventions = == The xform.align3d header attribute == The "xform.align3d" EMData attribute stores a Transform3D object denoted as {{{$$T3D_{ali3D}$$}}}, which represents the transformation of the 3D map {{{$$M(x,y,z)$$}}}, as given by the following {{{$$ M(x,y,z)_{ali} = T3D_{ali3D} M(x,y,z) $$}}} Where {{{$$ M(x,y,z)_{ali}$$}}} denotes the transformed 3D map. The programmer is free to construct {{{$$T3D_{ali3D}$$}}} using the guidelines of the Transform3D class. = 3D backprojection alignment conventions = 3D projection alignment is used here to denote the set of transformations that must be applied to a projection in order to backproject into a 3D volume, presumably as part of a 3D reconstruction routine. == 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, possibly including pre or post translation (the latter is a default). The translation information along with the direction of the projection is to be stored in a Transform3D object {{{$$T3D$$}}}, 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 operation can be thought of as first transforming the 3D map M by the Transform3D object, and by subsequently taking line integrals along z. The programmer is free to construct {{{$$T3D_{ali3D}$$}}} using the guidelines of the Transform3D class. In Python one may generate a projection using a strategy similar to {{{#!python from EMAN2 import * t = Transform3D(23,24,25) # EMAN convent az, alt, phi t.set_pretrans(1,2,3) model = test_image_3d() # load a test model, defaults to 128x128x128. Shows the 'axes' image. model is an EMData object model = EMData("groel.mrc") # read the 3D image 'groel.mrc' from the current directory. p = model.project("standard",t) # projects using the standard method and the Transform3D object t. see e2help.py projectors }}} == Transformations and backprojections: the xform.reconstruct header attribute == The "xform.reconstruct" EMData attribute returns a specialized Transform3D {{{$$T3D_{rec}$$}}} that stores a 2D translation that is to be applied to the projection {{{$$p(x,y)$$}}} before it is backprojected into the 3D volume {{{$$V(x,y,z)$$}}} in the orientation dictated by the Transform3D's rotation matrix (Euler angles). More specifically {{{$$T3D_{rec}$$}}} consists of a rotation and a single post translation, i.e. {{{$$T3D_{rec} = T_{post,rec} R_{rec} = [[I,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R_{rec},\mathbf{0}],[\mathbf{0}^T,1]] = [[R_{rec},\mathbf{t}_{post}],[\mathbf{0}^T,1]]$$}}} Where {{{$$ T_{post,rec} $$}}} is defined as {{{$$ T_{post,rec} = (dx,dy,0)^T $$}}} [...] {{{$$ T_{post,rec} p(x,y) \approx int_z R_{rec} M(x,y,z) dz$$}}} |
Transformations in EMAN2
Helpful Links
For a more information on the contents of 3D rotation matrices please consult the Sparx [http://macro-em.org/sparxwiki/Euler_angles Euler Angles] page.
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 transformations of a rigid body 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,\mathbf{t}],[\mathbf{0}^T,1]]$$
Where R is a $$3x3$$ rotation matrix and $$\mathbf{t}=(dx,dy,dz)^T$$ is a post translation. In this approach a 3D point $$\mathbf{p}=(x,y,z)^T$$ as represented in homogeneous coordinates as a 4D vector $$\mathbf{p}_{hc}=(x,y,z,1)^T$$ and is multiplied by the matrix $$M$$ to produce the result of applying the transformation
$$ T3D \mathbf{p}_{hc} = ( (R\mathbf{p} + \mathbf{t})^T, 1 )^T $$
In this way the result of applying a Transform3D to a vector is literally a rotation followed 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,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R,\mathbf{0}],[\mathbf{0}^T,1]] [[I,\mathbf{t}_{pre}],[\mathbf{0}^T,1]] = [[R,R\mathbf{t}_{pre}+\mathbf{t}_{post}],[\mathbf{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 of the resulting Transform3D object ($$T3D_{rst}$$). To answer this question we look at the details
$$T3D_{rst} = 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}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}],[\mathbf{0}^T,1]]$$
$$ = T_{2,post} R_{2} [[R_{1},R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre}],[\mathbf{0}^T,1]]$$
The translation in right column ($$R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre}$$) is now what will be returned when $$T3D_{rst}$$ is asked for its pre_translation vector from python (or C++). Similarly, the post translation vector of $$T3D_{2}$$ will now be returned by calling get_postrans on $$T3D_{rst}$$. To complete the details, internally the Transform3D object will look like
$$ T3D_{rst} = [[ R_{2}R_{1},R_{2}(R_{1}\mathbf{t}_{1,pre}+\mathbf{t}_{1,post}+\mathbf{t}_{2,pre})+\mathbf{t}_{2,post}],[\mathbf{0}^T,1]]$$
In Python the Transfrom3D x Transform3D operation can be achieved using the '*' operator
Transform3D times a 3D vector (Vec3f)
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 \mathbf{v} = [[R,R\mathbf{t}_{pre}+\mathbf{t}_{post}],[\mathbf{0}^T,1]] \mathbf{v} $$
$$T3D \mathbf{v} = Rv+R\mathbf{t}_{pre}+\mathbf{t}_{post} $$
The vector v is treated implicitly as though it were an homogeneous point, but the last row of the matrix-vector multiplication is not performed.
In Python the Transfrom3D x Vec3f operation can be achieved using the '*' operator or by calling the Transform3D::transform(Vec3f) function
1 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
2 v = Vec3f(1,2,3) # for example, pixel coordinates 1,2,3
3 v_dash = T*v
4 v_dash = T.transform(v) # Achieves the same result as calling T*v
Explicitly rotating a 3D vector (Vec3f)
If a Transform3D is represented as
$$T3D = [[R,\mathbf{t}],[\mathbf{0}^T,1]]$$
One can calculate
$$\mathbf{v}_R = R \mathbf{v}$$
in Python by doing
2D image alignment conventions
The xform.align2d header attribute
The "xform.align2d" EMData attribute stores a Transform3D object denoted here as $$T3D_{ali2D}$$, which represents the alignment of the 2D Image $$M(x,y)$$, as given by the following
$$ M(x,y)_{ali} = T3D_{ali2D} M(x,y) $$
Where $$ M(x,y)_{ali}$$ denotes the aligned image. The Transform3D object has been designed to allow for application of 2D transformations. The internal transformation matrix of Transform3D object that stores only 2D alignment parameters $$T3D_{ali2D}$$ appears just as any other Transform3D object
$$T3D_{ali2D} = T_{post} R T_{pre} = [[I,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R,\mathbf{0}],[\mathbf{0}^T,1]] [[I,\mathbf{t}_{pre}],[\mathbf{0}^T,1]] $$
However the rotation and translations can be made 'psuedo-2D', more specifically
$$ R = [[cos phi,sin phi, 0],[-sin phi,cos phi,0],[0,0,1]], \mathbf{t}_{pre} = (dx_{pre},dy_{pre},0)^T, \mathbf{t}_{post} = (dx_{post},dy_{post},0)^T $$
Creating Transform3D objects that describe 2D transformations
To construct "pseudo-2D" Transform3D objects in Python you can use any of the following approaches
1 from EMAN2 import Transform3D
2 # set the rotation
3 t = Transform3D(0,0,25) # 25 is phi
4 t = Transform3D(EULER_SPIDER 0,0,24) # 24 is psi which is equivalent to setting phi
5 # set pre and post trans
6 t.set_pretrans(2,3) # pre translation dx and dy
7 t.set_pretrans(Vec2f(2,3)) # use Vec2f instead
8 t.set_posttrans(-1,-10) # post translation dx and dy
9 t.set_posttrans(Vec2f(-1,-10)) # use Vec2f instead
Transform3D times a 2D vector (Vec2f)
A Vec2f, an EMAN2 object that stores two values $$v_x$$ and $$v_y$$, may be right multiplied against a Transform3D object to efficiently calculate transformed 2D coordinates.
$$ T3D_{ali2D} \dot \mathbf(Vec2f) \equiv [[cos phi,sin phi, cos phi * dx_{pre} + sin phi * dy_{pre} + dx_{post}],[-sin phi,cos phi,-sin phi * dx_{pre} + cos phi * dy_{pre} + dy_{post}],[0,0,1]] ((v_x),(v_y),(1)) $$
The 2D coordinates are multiplied by the internal transformation matrix in the Transform3D to mimic 2D transformation. The Transform3D object is not checked to ensure it describes a single (phi) rotation or whether the current translations are purely 2D. This responsibility is left to the programmer.
Here is an example of doing Transform3D times Vec2f in Python
1 from EMAN2 import Transform3D
2 # make a Transform3D that can be used as a 2D transformation
3 t = Transform3D(0,0,25) # 25 is phi
4 t.set_pretrans(Vec2f(2,3)) # use Vec2f instead
5 t.set_posttrans(Vec2f(-1,-10)) # use Vec2f instead
6 v = Vec2f(2,3) # for example, pixel coordinate 2,3
7 v_trans = t*v # calculates the 2D transformation
3D image alignment conventions
The xform.align3d header attribute
The "xform.align3d" EMData attribute stores a Transform3D object denoted as $$T3D_{ali3D}$$, which represents the transformation of the 3D map $$M(x,y,z)$$, as given by the following
$$ M(x,y,z)_{ali} = T3D_{ali3D} M(x,y,z) $$
Where $$ M(x,y,z)_{ali}$$ denotes the transformed 3D map. The programmer is free to construct $$T3D_{ali3D}$$ using the guidelines of the Transform3D class.
3D backprojection alignment conventions
3D projection alignment is used here to denote the set of transformations that must be applied to a projection in order to backproject into a 3D volume, presumably as part of a 3D reconstruction routine.
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, possibly including pre or post translation (the latter is a default). The translation information along with the direction of the projection is to be stored in a Transform3D object $$T3D$$, 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 operation can be thought of as first transforming the 3D map M by the Transform3D object, and by subsequently taking line integrals along z. The programmer is free to construct $$T3D_{ali3D}$$ using the guidelines of the Transform3D class.
In Python one may generate a projection using a strategy similar to
1 from EMAN2 import *
2 t = Transform3D(23,24,25) # EMAN convent az, alt, phi
3 t.set_pretrans(1,2,3)
4 model = test_image_3d() # load a test model, defaults to 128x128x128. Shows the 'axes' image. model is an EMData object
5 model = EMData("groel.mrc") # read the 3D image 'groel.mrc' from the current directory.
6 p = model.project("standard",t) # projects using the standard method and the Transform3D object t. see e2help.py projectors
Transformations and backprojections: the xform.reconstruct header attribute
The "xform.reconstruct" EMData attribute returns a specialized Transform3D $$T3D_{rec}$$ that stores a 2D translation that is to be applied to the projection $$p(x,y)$$ before it is backprojected into the 3D volume $$V(x,y,z)$$ in the orientation dictated by the Transform3D's rotation matrix (Euler angles). More specifically $$T3D_{rec}$$ consists of a rotation and a single post translation, i.e.
$$T3D_{rec} = T_{post,rec} R_{rec} = [[I,\mathbf{t}_{post}],[\mathbf{0}^T,1]] [[R_{rec},\mathbf{0}],[\mathbf{0}^T,1]] = [[R_{rec},\mathbf{t}_{post}],[\mathbf{0}^T,1]]$$
Where $$ T_{post,rec} $$ is defined as
$$ T_{post,rec} = (dx,dy,0)^T $$
[...]
$$ T_{post,rec} p(x,y) \approx int_z R_{rec} M(x,y,z) dz$$