Skip to content

Stage

Classes

Stage(tem)

Stage control.

Source code in src/instamatic/TEMController/stage.py
15
16
17
18
19
20
def __init__(self, tem):
    super().__init__()
    self._tem = tem
    self._setter = self._tem.setStagePosition
    self._getter = self._tem.getStagePosition
    self._wait = True  # properties only

Attributes

a: int property writable

Rotation angle.

b: int property writable

Secondary rotation angle.

name: str property

Get name of the class.

x: int property writable

X position.

xy: Tuple[int, int] property writable

XY position as a tuple.

y: int property writable

Y position.

z: int property writable

Stage height Z.

Functions

alpha_wobbler(delta=5.0, event=None)

Tilt the stage by plus/minus the value of delta (degrees) If event is not set, press Ctrl-C to interrupt.

Source code in src/instamatic/TEMController/stage.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
def alpha_wobbler(self, delta: float = 5.0, event=None) -> None:
    """Tilt the stage by plus/minus the value of delta (degrees) If event
    is not set, press Ctrl-C to interrupt."""

    a_center = self.a
    print(f"Wobbling 'alpha': {a_center:.2f}±{delta:.2f}")

    if event:
        while not event.is_set():
            self.a = a_center + delta
            self.a = a_center - delta
    else:
        print("(press 'Ctrl-C' to interrupt)")
        try:
            while True:
                self.a = a_center + delta
                self.a = a_center - delta
        except KeyboardInterrupt:
            pass

    print(f"Restoring 'alpha': {a_center:.2f}")
    self.a = a_center
    print(f'Print z={self.z:.2f}')
eliminate_backlash_a(target_angle=0.0, step=1.0, n_steps=3, settle_delay=0.2)

Eliminate backlash by relaxing the position. The routine will move in opposite direction of the targeted angle by n_steps*step, and walk up to the current tilt angle in n_steps. Based on Suloway et al., J. Struct. Biol. (2009), doi: 10.1016/j.jsb.2009.03.019.

target_angle: float, target angle for the rotation in degrees step: float, stepsize in degrees n_steps: int > 0, number of steps to walk up to current angle settle_delay: float, delay between movements in seconds to allow the stage to settle

Source code in src/instamatic/TEMController/stage.py
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
def eliminate_backlash_a(self, target_angle: float = 0.0, step: float = 1.0, n_steps: int = 3, settle_delay: float = 0.200) -> None:
    """Eliminate backlash by relaxing the position. The routine will move
    in opposite direction of the targeted angle by `n_steps`*`step`, and
    walk up to the current tilt angle in `n_steps`. Based on Suloway et
    al., J. Struct. Biol. (2009), doi: 10.1016/j.jsb.2009.03.019.

    target_angle: float,
        target angle for the rotation in degrees
    step: float,
        stepsize in degrees
    n_steps: int > 0,
        number of steps to walk up to current angle
    settle_delay: float,
        delay between movements in seconds to allow the stage to settle
    """
    current = self.a

    if target_angle > current:
        s = +1
    elif target_angle < current:
        s = -1
    else:
        return

    n_steps += 1

    for i in reversed(range(n_steps)):
        self.a = current - s * i * step
        time.sleep(settle_delay)
eliminate_backlash_xy(step=10000, settle_delay=0.2)

Eliminate backlash by in XY by moving the stage away from the current position, and approaching it from the common direction. Uses set_xy_with_backlash_correction internally.

step: float, stepsize in nm settle_delay: float, delay between movements in seconds to allow the stage to settle

Source code in src/instamatic/TEMController/stage.py
302
303
304
305
306
307
308
309
310
311
312
313
def eliminate_backlash_xy(self, step: float = 10000, settle_delay: float = 0.200) -> None:
    """Eliminate backlash by in XY by moving the stage away from the
    current position, and approaching it from the common direction. Uses
    `set_xy_with_backlash_correction` internally.

    step: float,
        stepsize in nm
    settle_delay: float,
        delay between movements in seconds to allow the stage to settle
    """
    stage = self.get()
    self.set_xy_with_backlash_correction(x=stage.x, y=stage.y, step=step, settle_delay=settle_delay)
get()

Get stage positions; x, y, z, and status of the rotation axes; a, b.

Source code in src/instamatic/TEMController/stage.py
79
80
81
82
def get(self) -> Tuple[int, int, int, int, int]:
    """Get stage positions; x, y, z, and status of the rotation axes; a,
    b."""
    return StagePositionTuple(*self._getter())
is_moving()

Return 'True' if the stage is moving.

Source code in src/instamatic/TEMController/stage.py
179
180
181
def is_moving(self) -> bool:
    """Return 'True' if the stage is moving."""
    return self._tem.isStageMoving()
move_along_optical_axis(delta_z)

See Stage.move_in_projection

Source code in src/instamatic/TEMController/stage.py
137
138
139
140
141
142
143
def move_along_optical_axis(self, delta_z: int):
    """See `Stage.move_in_projection`"""
    x, y, z, a, b = self.get()
    a = np.radians(a)
    y = y + delta_z * np.sin(a)
    z = z + delta_z * np.cos(a)
    self.set(y=y, z=z)
move_in_projection(delta_x, delta_y)

Y and z are always perpendicular to the sample stage. To achieve the movement in the projection, x and yshould be broken down into the components z' and y'.

y = y' * cos(a) z = y' * sin(a)

z'| / z | / |/_____ y' \ a \ \ y

Source code in src/instamatic/TEMController/stage.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
def move_in_projection(self, delta_x: int, delta_y: int) -> None:
    r"""Y and z are always perpendicular to the sample stage. To achieve the
    movement in the projection, x and yshould be broken down into the
    components z' and y'.

    y = y' * cos(a)
    z = y' * sin(a)

    z'|  / z
      | /
      |/_____ y'
       \ a
        \
         \ y
    """
    x, y, z, a, b = self.get()
    a = np.radians(a)
    x = x + delta_x
    y = y + delta_y * np.cos(a)
    z = z - delta_y * np.sin(a)
    self.set(x=x, y=y, z=z)
move_xy_with_backlash_correction(shift_x=None, shift_y=None, step=5000, settle_delay=0.2, wait=True)

Move xy by given shifts in stage coordinates with backlash correction. This is done by moving backwards from the targeted position by step, before moving to the targeted position. This function is meant to be used when precise relative movements are needed, for example when a shift is calculated from an image. Based on Liu et al., Sci. Rep. (2016) DOI: 10.1038/srep29231.

shift_x, shift_y: float, relative movement in x and y (nm) step: float, stepsize in nm settle_delay: float, delay between movements in seconds to allow the stage to settle wait: bool, block until stage movement is complete (JEOL only)

Source code in src/instamatic/TEMController/stage.py
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
def move_xy_with_backlash_correction(self, shift_x: int = None, shift_y: int = None, step: float = 5000, settle_delay: float = 0.200, wait=True) -> None:
    """Move xy by given shifts in stage coordinates with backlash
    correction. This is done by moving backwards from the targeted position
    by `step`, before moving to the targeted position. This function is
    meant to be used when precise relative movements are needed, for
    example when a shift is calculated from an image. Based on Liu et al.,
    Sci. Rep. (2016) DOI: 10.1038/srep29231.

    shift_x, shift_y: float,
        relative movement in x and y (nm)
    step: float,
        stepsize in nm
    settle_delay: float,
        delay between movements in seconds to allow the stage to settle
    wait: bool,
        block until stage movement is complete (JEOL only)
    """
    stage = self.get()

    if shift_x:
        target_x = stage.x + shift_x
        if target_x > stage.x:
            pre_x = stage.x - step
        elif target_x < stage.x:
            pre_x = stage.x + step
    else:
        pre_x = None
        target_x = None

    if shift_y:
        target_y = stage.y + shift_y
        if target_y > stage.y:
            pre_y = stage.y - step
        elif target_y < stage.y:
            pre_y = stage.y + step
    else:
        pre_y = None
        target_y = None

    self.set(x=pre_x, y=pre_y)
    if settle_delay:
        time.sleep(settle_delay)

    self.set(x=target_x, y=target_y, wait=wait)
    if settle_delay:
        time.sleep(settle_delay)
neutral()

Reset the position of the stage to the 0-position.

Source code in src/instamatic/TEMController/stage.py
175
176
177
def neutral(self) -> None:
    """Reset the position of the stage to the 0-position."""
    self.set(x=0, y=0, z=0, a=0, b=0)
no_wait()

Context manager that prevents blocking stage position calls on properties.

Usage: with ctrl.stage.no_wait(): ctrl.stage.x += 1000 ctrl.stage.y += 1000

Source code in src/instamatic/TEMController/stage.py
187
188
189
190
191
192
193
194
195
196
197
198
199
@contextmanager
def no_wait(self):
    """Context manager that prevents blocking stage position calls on
    properties.

    Usage:
        with ctrl.stage.no_wait():
            ctrl.stage.x += 1000
            ctrl.stage.y += 1000
    """
    self._wait = False
    yield
    self._wait = True
relax_xy(step=100)

Relax the stage by moving it in the opposite direction from the last movement.

Source code in src/instamatic/TEMController/stage.py
230
231
232
233
def relax_xy(self, step: int = 100) -> None:
    """Relax the stage by moving it in the opposite direction from the last
    movement."""
    pass
rotating_speed(speed)

Context manager that sets the rotation speed for the duration of the with statement (JEOL only).

Usage: with ctrl.stage.rotating_speed(1): ctrl.stage.a = 40.0

Source code in src/instamatic/TEMController/stage.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@contextmanager
def rotating_speed(self, speed: int):
    """Context manager that sets the rotation speed for the duration of the
    `with` statement (JEOL only).

    Usage:
        with ctrl.stage.rotating_speed(1):
            ctrl.stage.a = 40.0
    """
    try:
        current_speed = self._tem.getRotationSpeed()
    except BaseException:
        yield  # on error
    else:
        if current_speed != speed:
            self.set_rotation_speed(speed)
            yield  # default flow
            self.set_rotation_speed(current_speed)
        else:
            yield  # if requested speed is the same as current
set(x=None, y=None, z=None, a=None, b=None, wait=True)

Wait: bool, block until stage movement is complete (JEOL only)

Source code in src/instamatic/TEMController/stage.py
31
32
33
def set(self, x: int = None, y: int = None, z: int = None, a: int = None, b: int = None, wait: bool = True) -> None:
    """Wait: bool, block until stage movement is complete (JEOL only)"""
    self._setter(x, y, z, a, b, wait=wait)
set_a_with_speed(a, speed, wait=False)

Rotate to angle a with speed (JEOL only).

wait: bool, block until stage movement is complete.

Source code in src/instamatic/TEMController/stage.py
47
48
49
50
51
52
53
54
55
56
def set_a_with_speed(self, a: float, speed: int, wait: bool = False):
    """Rotate to angle `a` with speed (JEOL only).

    wait: bool, block until stage movement is complete.
    """
    with self.rotating_speed(speed):
        self.set(a=a, wait=False)
    # Do not wait on `set` to return to normal rotation speed quickly
    if wait:
        self.wait()
set_rotation_speed(speed=1)

Sets the stage (rotation) movement speed on the TEM.

Source code in src/instamatic/TEMController/stage.py
43
44
45
def set_rotation_speed(self, speed=1) -> None:
    """Sets the stage (rotation) movement speed on the TEM."""
    self._tem.setRotationSpeed(value=speed)
set_with_speed(x=None, y=None, z=None, a=None, b=None, wait=True, speed=1.0)

Note that this function only works on FEI machines.

wait: ignored, but necessary for compatibility with JEOL API speed: float, set stage rotation with specified speed (FEI only)

Source code in src/instamatic/TEMController/stage.py
35
36
37
38
39
40
41
def set_with_speed(self, x: int = None, y: int = None, z: int = None, a: int = None, b: int = None, wait: bool = True, speed: float = 1.0) -> None:
    """Note that this function only works on FEI machines.

    wait: ignored, but necessary for compatibility with JEOL API
    speed: float, set stage rotation with specified speed (FEI only)
    """
    self._setter(x, y, z, a, b, wait=wait, speed=speed)
set_xy_with_backlash_correction(x=None, y=None, step=10000, settle_delay=0.2)

Move to new x/y position with backlash correction. This is done by approaching the target x/y position always from the same direction.

SerialEM uses the same approach (x first, y second, step=10000).

step: float, stepsize in nm settle_delay: float, delay between movements in seconds to allow the stage to settle

Source code in src/instamatic/TEMController/stage.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
def set_xy_with_backlash_correction(self, x: int = None, y: int = None, step: float = 10000, settle_delay: float = 0.200) -> None:
    """Move to new x/y position with backlash correction. This is done by
    approaching the target x/y position always from the same direction.

    SerialEM uses the same approach (x first, y second, step=10000).

    step: float,
        stepsize in nm
    settle_delay: float,
        delay between movements in seconds to allow the stage to settle
    """
    wait = True
    self.set(x=x - step, y=y - step)
    if settle_delay:
        time.sleep(settle_delay)

    self.set(x=x, y=y, wait=wait)
    if settle_delay:
        time.sleep(settle_delay)
stop()

This will halt the stage preemptively if wait=False is passed to Stage.set.

Source code in src/instamatic/TEMController/stage.py
201
202
203
204
def stop(self) -> None:
    """This will halt the stage preemptively if `wait=False` is passed to
    Stage.set."""
    self._tem.stopStage()
wait()

Blocking call that waits for stage movement to finish.

Source code in src/instamatic/TEMController/stage.py
183
184
185
def wait(self) -> None:
    """Blocking call that waits for stage movement to finish."""
    self._tem.waitForStage()