eman2:eman2transforminpython
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
eman2:eman2transforminpython [2025/07/04 16:00] – steveludtke | eman2:eman2transforminpython [2025/07/06 02:44] (current) – steveludtke | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Transforms in Python ====== | + | This page has [[transforminpython|moved]] |
- | + | ||
- | ===== The center of the image ===== | + | |
- | ---- | + | |
- | The center of the image for purposes of rotations is different for odd and even sized images. For even images, the center is at $(nx/ | + | |
- | + | ||
- | {{attachment: | + | |
- | + | ||
- | ===== What is a Transform? ===== | + | |
- | ---- | + | |
- | We use the [[http:// | + | |
- | + | ||
- | $$\mathrm{Tr} = M T S R$$ | + | |
- | + | ||
- | Where $M$ is a mirroring operation about the x-axis, $T$ is a translation, | + | |
- | + | ||
- | ===== Supported Rotation Conventions ===== | + | |
- | ---- | + | |
- | ||Convention ||Angle Names ||Matrices || | + | |
- | ||EMAN ||az, alt, phi (Z, | + | |
- | ||Imagic ||gamma, beta, alpha ||$\begin{bmatrix}\cos gamma& | + | |
- | ||Spider ||psi, theta, phi ||$\begin{bmatrix}\cos psi& | + | |
- | ||MRC ||phi, theta, omega ||$\begin{bmatrix}\cos phi& | + | |
- | ||XYZ ||z, y, x ||$\begin{bmatrix}\cos z&\sin z& 0\\-\sin z& \cos z& | + | |
- | ||spin ||Omega, n1, n2, n3 ||Quaternion rotation by Omega degrees about the vector $[n1, | + | |
- | ||sgirot ||q, n1, n2, n3 ||Quaternion rotation by q degrees about the vector $[n1, | + | |
- | ||quaternion ||e0, e1, e2, e3 ||Literal quaternion rotation using $q = e0 + e1\mathbf{i} + e2\mathbf{j} + e2\mathbf{k}$ | + | |
- | ||2d||alpha||Rotation in 2-D only, for 3-D objects this is a rotation about Z|| | + | |
- | + | ||
- | + | ||
- | ===== The Transform object in Python ===== | + | |
- | ---- | + | |
- | ==== Constructing a Transform ==== | + | |
- | There a four ways to construct a Transform object in Python | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() # default constructor, | + | |
- | t = Transform({" | + | |
- | p = Transform({" | + | |
- | q = Transform([1, | + | |
- | s = Transform(t) # copy construction - s is precisely the same as t | + | |
- | </ | + | |
- | + | ||
- | **NOTE:** | + | |
- | All the CONVENTIONS listed on the table above can be supplied as arguments or " | + | |
- | For example: | + | |
- | + | ||
- | <code python> | + | |
- | t = Tranform({" | + | |
- | t = Tranform({" | + | |
- | t = Tranform({" | + | |
- | Etc. | + | |
- | </ | + | |
- | + | ||
- | For more information on default parameters and what happens when some parameters are not set see [[# | + | |
- | + | ||
- | ==== Setting/ | + | |
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_rotation({" | + | |
- | spider_rot = t.get_rotation(" | + | |
- | eman_rot = t.get_rotation(" | + | |
- | s = Transform(eman_rot) # works fine | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | **NOTE:** | + | |
- | The **get_rotation() method can take a string as an argument, but it does NOT require one**; it is defaulted to ' | + | |
- | You can supply ANY rotation CONVENTION as a string to get the rotation in the corresponding convention, irrespective of the " | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({' | + | |
- | </ | + | |
- | + | ||
- | You can still get the rotation in other conventions: | + | |
- | + | ||
- | <code python> | + | |
- | t.get_rotation(' | + | |
- | t.get_rotation(' | + | |
- | </ | + | |
- | + | ||
- | ==== Setting/ | + | |
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_scale(2.0) | + | |
- | scale = t.get_scale() | + | |
- | s = Transform({" | + | |
- | </ | + | |
- | ==== Setting/ | + | |
- | <code python> | + | |
- | t = Transform() | + | |
- | # Can be set using integers | + | |
- | t.set_mirror(1) # means True | + | |
- | t.set_mirror(0) # means False | + | |
- | t.set_mirror(False) | + | |
- | t.set_mirror(True) | + | |
- | mirror = t.get_mirror() | + | |
- | s = Transform({" | + | |
- | </ | + | |
- | ==== Setting/ | + | |
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_trans(1, | + | |
- | t.set_trans(Vec3f(1, | + | |
- | t.set_trans([1, | + | |
- | v = t.get_trans() | + | |
- | s = Transform({" | + | |
- | </ | + | |
- | ==== Setting/ | + | |
- | You can tell a Transform deduce any of its parameters from a dictionary. Similarly you can get the parameters of a Transform as a dictionary | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | d = t.get_params(" | + | |
- | s = Transform(d) # s is the same as t | + | |
- | d = t.get_params(" | + | |
- | s = Transform(d) # s is the same as t | + | |
- | d = t.get_params(" | + | |
- | s = Transform(d) # s is the same as t | + | |
- | </ | + | |
- | For more information the behaviour of set_params see [[# | + | |
- | + | ||
- | ==== A Transform multiplied by a Vec3f ==== | + | |
- | The transformation of a 3D vector $$ v = (v_x, | + | |
- | + | ||
- | $$ Tr \mathbf{v} | + | |
- | + | ||
- | This can be done in Python using the following | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | v = Vec3f(3, | + | |
- | v_transformed = t*v | + | |
- | v_transformed = t.transform(v) # can also do it this way if you prefer | + | |
- | </ | + | |
- | ==== Transforming a 3D image ==== | + | |
- | Transforming a 3D image is achieved using a single function call | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | t.set_trans( ... ) | + | |
- | e = test_image_3d() | + | |
- | e.transform(t) | + | |
- | </ | + | |
- | You can alternatively use the EMData processing framework, for example: | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | t.set_trans( ... ) | + | |
- | f = e.process(" | + | |
- | e.process_inplace(" | + | |
- | </ | + | |
- | In fact < | + | |
- | + | ||
- | ===== 2D degenerate use of the Transform object in Python ===== | + | |
- | ---- | + | |
- | The Transform object can be used as though it were a 2D transformation matrix. In this case the interface for setting/ | + | |
- | + | ||
- | ==== Setting/ | + | |
- | Use the " | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_rotation({" | + | |
- | a = t.get_rotation(" | + | |
- | s = Transform(a) # works fine | + | |
- | </ | + | |
- | ==== Setting/ | + | |
- | The interface is more or less identical to the 3D case | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_trans(1, | + | |
- | t.set_trans(Vec2f(1, | + | |
- | v = t.get_trans_2d() | + | |
- | s = Transform(" | + | |
- | </ | + | |
- | ==== Setting/ | + | |
- | For getting the parameters in 2D form use the following | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | d = t.get_params(" | + | |
- | s = Transform(d) # s is the same as t | + | |
- | </ | + | |
- | ==== A Transform multiplied by a Vec2f ==== | + | |
- | The transformation of a 2D vector $$ v_{2D} = (v_x,v_y)^T $$ by a Transform is equivalent to setting the z component of 3D vector to 0. If $$ v = (v_x, | + | |
- | + | ||
- | $$ Tr \mathbf{v_{2D}} | + | |
- | + | ||
- | and the z component is ignored. Note that the internal implementation is efficient. 2D vector transformation can be done in Python using the following | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | v = Vec2f(3, | + | |
- | v_transformed = t*v | + | |
- | v_transformed = t.transform(v) # can also do it this way if you prefer | + | |
- | </ | + | |
- | ==== Transforming a 2D image ==== | + | |
- | Transforming a 2D image is achieved using a single function call | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | e = test_image() | + | |
- | e.transform(t) | + | |
- | </ | + | |
- | You can alternatively use the EMData processing framework, for example: | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform() | + | |
- | t.set_params({" | + | |
- | f = e.process(" | + | |
- | e.proceess_inplace(" | + | |
- | </ | + | |
- | As stated previously, < | + | |
- | + | ||
- | Note that if you try to transform a 2D image using a Transform that contains 3D rotations or translations you will get an error: | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | a = test_image() # 2D | + | |
- | a.transform(t) # ERROR is thrown | + | |
- | t = Transform({" | + | |
- | a.transform(t) # ERROR is thrown | + | |
- | </ | + | |
- | << | + | |
- | + | ||
- | ===== A more in depth look at the dictionary constructor ===== | + | |
- | ---- | + | |
- | The dictionary constructor, | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | t = Transform({" | + | |
- | </ | + | |
- | If any of the angles or not specified they are implicitly set to 0 | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | t = Transform({" | + | |
- | </ | + | |
- | If no euler type is specified then the rotation matrix is the identity | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | </ | + | |
- | Similarly if any of the translation parameters are not specified they are implicitly set to 0 | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | t = Transform({" | + | |
- | </ | + | |
- | If scale is not specified it is by default 1.0, similarly if mirror is not specified it is be default False | + | |
- | + | ||
- | <code python> | + | |
- | t = Transform({" | + | |
- | </ | + | |
- | << | + | |
- | + | ||
- | ===== A more in depth look at set_params ===== | + | |
- | ---- | + | |
- | Constructing a Transform with some dictionary is the same as calling set_params on a Transform that is the identity. | + | |
- | + | ||
- | <code python> | + | |
- | d = {" | + | |
- | t = Transform(d) # t is initialized as the identity and then set_params(d) is called internally | + | |
- | s = Transform() # s is the identity | + | |
- | s.set_params(d) # s is identical to t | + | |
- | </ | + | |
- | The main difference between calling set_params explicitly on a Transform as opposed to constructing a Tranform with a dictionary lies in the fact that the construction method first sets the Transform object to the identity before calling set_params. So if calling the set_params function on a Transform that has already been initialized and had many things done than you should be aware of the following... | + | |
- | + | ||
- | ==== If unspecified, | + | |
- | <code python> | + | |
- | t = Transform({" | + | |
- | d = {" | + | |
- | t.set_params(d) # t still has the same rotation, scale and mirror but it has an updated translation | + | |
- | </ | + | |
- | ==== For rotation and translation, | + | |
- | <code python> | + | |
- | t = Transform({" | + | |
- | d = {" | + | |
- | t.set_params(d) # ty and tz are now 0 | + | |
- | # | + | |
- | t = Transform({" | + | |
- | d = {" | + | |
- | t.set_params(d) # alt and az are 0 | + | |
- | t.set_params({" | + | |
- | </ | + |
eman2/eman2transforminpython.1751644837.txt.gz · Last modified: by steveludtke