Differences between revisions 48 and 74 (spanning 26 versions)
Revision 48 as of 2008-08-19 03:28:09
Size: 7554
Comment:
Revision 74 as of 2008-08-19 17:32:45
Size: 8324
Comment:
Deletions are marked like this. Additions are marked like this.
Line 7: Line 7:
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 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
Line 19: Line 19:
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 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
Line 38: Line 38:
=== Setting and Getting Transform3D Rotations and Translation Attributes === ===  Setting Transform3D Rotations and Translation Attributes in Python ===
Line 58: Line 58:
== Multiplication == === Getting Transform3D Rotations and Translation Attributes in Python ===
Line 60: Line 60:
=== 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 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} = 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]]$$}}}

You can get these attributes using similar syntax
You can get these attributes using similar syntax to that employed for the setter methods
Line 85: Line 73:
== Rotations == == Multiplication ==
Line 87: Line 75:
A rotation of a pixel coordinate at [x,y,z] about the y axis looks like === Transform3D Times a Transform3D ===
Line 89: Line 77:
4x4 Rotation matrix x homog pix coord 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
Line 91: Line 79:
In general a rotation matrix will look like this {{{$$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}\hat{t}_{1,pre}+\hat{t}_{1,post}],[\hat{0}^T,1]]$$}}}
Line 93: Line 81:
4x4 general rotation matrix {{{$$ = 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]]$$}}}
Line 95: Line 83:
Note that only the upper left 3x3 block is used to store the rotation information 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 {{{$$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
Line 97: Line 85:
{{{$$ T3D_{rst} = [[ 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]]$$}}}
Line 98: Line 87:
== Translations ==

Translation of a pixel coordinate at [x,y,z] by [dx,dy,dz] looks like

4x4 depiction of translation matrix x homog pix coord

This shows how the homogeneous coordinate representation is used to achieve translation


== Rotations and Translations ==

Rotation


Need MathML

== Transforming an EMData object ==

An EMData object may be transformed using the following syntax
In Python the Transfrom3D x Transform3D operation can be achieved using the '*' operator
Line 119: Line 90:
e = EMData("mydata.hdf")
t = Transform3D(EULER_EMAN,10,23,0) # three angles in the EMAN convention are az=10,alt=23,phi=0.
# The convention may also be EULER_SPIDER, EULER_IMAGIC, EULER_MRC, EULER_SPIN, EULER_XYZ
t.set_pretrans(1,1,1)
t.set_postrans(2,2,2)
e.rotate_translate(t)
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
Line 127: Line 95:
This next section will look better once we get mathml working === Transform3D Times a Vector (Vec3f) ===
Line 129: Line 97:
A pixel given at coordinate vector v = [x,y,z]^T will be transformed using the following" 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
Line 131: Line 99:
{{{$$vhat = T_{post} R T_{pre} v$$}}} {{{$$T3D \hat{v} = [[R,R\hat{t}_{pre}+\hat{t}_{post}],[\hat{0}^T,1]] \hat{v} $$}}}
Line 133: Line 101:
Where the rotation matrix R and associated conventions are defined in Baldwin and Penczek 2007. {{{$$T3D \hat{v} = Rv+R\hat{t}_{pre}+\hat{t}_{post} $$}}}
Line 135: Line 103:
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.
Line 136: Line 105:
== Transformations and projections == 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 Vector (Vec3f) ===

If a Transform3D is represented as

{{{$$T3D = [[R,\hat{t}],[\hat{0}^T,1]]$$}}}

One can calculate

{{{$$\hat{v}_R = R \hat{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)
}}}

= Transformations and projections =
Line 140: Line 136:
{{{$$p(x,y) = int T M(x,y,z) dz$$}}} {{{$$p(x,y) = int_z T3D M(x,y,z) dz$$}}}
Line 142: Line 138:
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. 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.
Line 144: Line 140:
== Transformations and recontructors == = Transformations and backprojections =
Line 146: Line 142:
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. If a projection was generated as described above using a Transform3D object, the operation of backprojection
(in the same direction) requires inverse of the original Transform3D object.

TableOfContents

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 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,\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 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}\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 $$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}\hat{t}_{1,pre}+\hat{t}_{1,post}+\hat{t}_{2,pre})+\hat{t}_{2,post}],[\hat{0}^T,1]]$$

In Python the Transfrom3D x Transform3D operation can be achieved using the '*' operator

   1 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
   2 T2 = Transform3D(25,45,65,Vec3f(4,5,6)) # EULER_EMAN convention rotations az, alt, phi, followed by the post trans
   3 Trst = T2*T1

Transform3D Times a 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 \hat{v} =  [[R,R\hat{t}_{pre}+\hat{t}_{post}],[\hat{0}^T,1]] \hat{v}  $$

$$T3D \hat{v} = Rv+R\hat{t}_{pre}+\hat{t}_{post}  $$

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.

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 Vector (Vec3f)

If a Transform3D is represented as

$$T3D = [[R,\hat{t}],[\hat{0}^T,1]]$$

One can calculate

$$\hat{v}_R = R \hat{v}$$

in Python by doing

   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_R = T.rotate(v)

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 operation can be thought of as first transforming the 3D map M by the Transform3D object, and by subsequently taking line integrals along z.

Transformations and backprojections

If a projection was generated as described above using a Transform3D object, the operation of backprojection (in the same direction) requires inverse of the original Transform3D object.

EMAN2/TransformConventions (last edited 2009-02-04 21:14:56 by DavidWoolford)