Coverage for src/pytribeam/insertable_devices.py: 0%
248 statements
« prev ^ index » next coverage.py v7.6.1, created at 2026-06-16 18:30 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2026-06-16 18:30 +0000
1#!/usr/bin/python3
2"""
3Insertable Devices Module
4==========================
6This module contains functions for managing and controlling insertable devices in the microscope, including detectors, EBSD, and EDS systems.
8Functions
9---------
10detector_insertable(microscope: tbt.Microscope, detector: tbt.DetectorType) -> bool
11 Determine whether or not the built-in microscope detector is insertable and return its state.
13detector_state(microscope: tbt.Microscope, detector: tbt.DetectorType) -> tbt.RetractableDeviceState
14 Determine the state of the detector, only valid if the detector is insertable.
16detectors_will_collide(microscope: tbt.Microscope, detector_to_insert: tbt.DetectorType) -> bool
17 Determine if a collision may occur when inserting the specified detector.
19device_access(microscope: tbt.Microscope) -> tbt.ViewQuad
20 Switch to the upper-left quadrant and assign the electron beam as the active device.
22insert_EBSD(microscope: tbt.Microscope) -> bool
23 Insert the EBSD camera into the microscope.
25insert_EDS(microscope: tbt.Microscope) -> bool
26 Insert the EDS camera into the microscope.
28insert_detector(microscope: tbt.Microscope, detector: tbt.DetectorType, time_delay_s: float = 0.5) -> bool
29 Insert the selected detector into the microscope.
31retract_all_devices(microscope: tbt.Microscope, enable_EBSD: bool, enable_EDS: bool) -> bool
32 Retract all insertable devices, including microscope detectors and EBSD/EDS detectors if integrated.
34connect_EBSD() -> tbt.RetractableDeviceState
35 Connect to the EBSD system and retrieve the camera status.
37retract_EBSD(microscope: tbt.Microscope) -> bool
38 Retract the EBSD camera from the microscope.
40connect_EDS() -> tbt.RetractableDeviceState
41 Connect to the EDS system and retrieve the camera status.
43retract_EDS(microscope: tbt.Microscope) -> bool
44 Retract the EDS detector from the microscope.
46retract_device(microscope: tbt.Microscope, detector: tbt.DetectorType) -> bool
47 Retract the specified detector from the microscope.
49CCD_pause(microscope: tbt.Microscope, quad: tbt.ViewQuad = tbt.ViewQuad.LOWER_RIGHT) -> bool
50 Pause the CCD camera, typically used after device or stage movement.
52CCD_view(microscope: tbt.Microscope, quad: tbt.ViewQuad = tbt.ViewQuad.LOWER_RIGHT) -> bool
53 Visualize detector or stage movement for the user using the CCD camera.
55specimen_current(microscope: tbt.Microscope, hfw_mm=Constants.specimen_current_hfw_mm, delay_s=Constants.specimen_current_delay_s) -> float
56 Measure the specimen current using the electron beam and return the value in nA.
57"""
59# Default python modules
60# from functools import singledispatch
61import time
62import warnings
64# 3rd party module
66# Local scripts
67import pytribeam.constants as cs
68from pytribeam.constants import Constants
69import pytribeam.image as img
71try:
72 from pytribeam.laser import tfs_laser as external
73except:
74 pass
75import pytribeam.types as tbt
78def detector_insertable(
79 microscope: tbt.Microscope,
80 detector: tbt.DetectorType,
81) -> bool:
82 """
83 Determine whether or not the built-in microscope detector is insertable and return its state.
85 This function checks if the specified detector is being read by Autoscript and if it is insertable.
87 Parameters
88 ----------
89 microscope : tbt.Microscope
90 The microscope object for which to check the detector.
91 detector : tbt.DetectorType
92 The type of the detector to check.
94 Returns
95 -------
96 bool
97 True if the detector is insertable, False otherwise.
99 Warnings
100 --------
101 UserWarning
102 If the detector type is invalid for the currently selected device or if the detector is not found on the system.
103 """
104 # check if the detector is being read by Autoscript
105 try:
106 # make requested detector the active detector
107 microscope.detector.type.value = detector.value
108 except:
109 warnings.warn(
110 f"""Warning. Invalid detector type of "{detector.value}" for currently selected device
111 of "{tbt.Device(microscope.imaging.get_active_device()).value}" or detector not found on this system.
112 Detector will be assumed to not be insertable."""
113 )
114 return False
116 # check if it is insertable
117 try:
118 state = microscope.detector.state
119 if state == tbt.RetractableDeviceState.STATIONARY.value:
120 return False
121 return True
122 except Exception:
123 return False
126def detector_state(
127 microscope: tbt.Microscope,
128 detector: tbt.DetectorType,
129) -> tbt.RetractableDeviceState:
130 """
131 Determine the state of the detector, only valid if the detector is insertable.
133 This function checks if the specified detector is insertable and returns its state.
135 Parameters
136 ----------
137 microscope : tbt.Microscope
138 The microscope object for which to check the detector state.
139 detector : tbt.DetectorType
140 The type of the detector to check.
142 Returns
143 -------
144 tbt.RetractableDeviceState
145 The state of the detector if it is insertable, None otherwise.
146 """
147 # check if the detector is being read by Autoscriptdevice_access(microscope)
148 # try:
149 # return tbt.RetractableDeviceState(microscope.detector.state)
150 # except Exception:
151 # return tbt.RetractableDeviceState.STATIONARY
152 if not detector_insertable(
153 microscope=microscope,
154 detector=detector,
155 ):
156 return tbt.RetractableDeviceState.STATIONARY
157 return tbt.RetractableDeviceState(microscope.detector.state)
160def detectors_will_collide(
161 microscope: tbt.Microscope,
162 detector_to_insert: tbt.DetectorType,
163) -> bool:
164 """
165 Determine if a collision may occur when inserting the specified detector.
167 This function checks if inserting the specified detector will cause a collision with any other detectors.
169 Parameters
170 ----------
171 microscope : tbt.Microscope
172 The microscope object for which to check for potential collisions.
173 detector_to_insert : tbt.DetectorType
174 The type of the detector to insert.
176 Returns
177 -------
178 bool
179 True if a collision may occur, False otherwise.
180 """
181 device_retracted = tbt.RetractableDeviceState.RETRACTED.value
182 for detector_combo in Constants.detector_collisions:
183 if detector_to_insert in detector_combo:
184 for detector in detector_combo:
185 if detector == detector_to_insert:
186 continue
187 if detector == tbt.DetectorType.EDS:
188 if external.EDS_CameraStatus() != device_retracted:
189 return True
190 elif detector == tbt.DetectorType.EBSD:
191 if external.EBSD_CameraStatus() != device_retracted:
192 return True
193 else:
194 state = detector_state(microscope=microscope, detector=detector)
195 if state.value != device_retracted:
196 return True
197 return False
200def device_access(microscope: tbt.Microscope) -> tbt.ViewQuad:
201 """
202 Switch to the upper-left quadrant and assign the electron beam as the active device.
204 This function switches the view to the upper-left quadrant and assigns the electron beam as the active device, which is the only device with access to insertable devices like the CBS/ABS detector. Other devices, like the ion beam, CCD, or Nav-Cam, do not have CBS/ABS access.
206 Parameters
207 ----------
208 microscope : tbt.Microscope
209 The microscope object for which to switch the view and assign the active device.
211 Returns
212 -------
213 tbt.ViewQuad
214 The upper-left quadrant view.
215 """
216 img.set_view(
217 microscope=microscope,
218 quad=tbt.ViewQuad.UPPER_LEFT,
219 )
220 img.set_beam_device(
221 microscope=microscope,
222 device=tbt.Device.ELECTRON_BEAM,
223 )
224 return True
227def insert_EBSD(
228 microscope: tbt.Microscope,
229) -> bool:
230 """
231 Insert the EBSD camera into the microscope.
233 This function connects to the EBSD system, checks for potential collisions with other detectors, and inserts the EBSD camera if it is not already inserted. It raises an error if the EBSD camera cannot be inserted.
235 Parameters
236 ----------
237 microscope : tbt.Microscope
238 The microscope object for which to insert the EBSD camera.
240 Returns
241 -------
242 bool
243 True if the EBSD camera is successfully inserted.
245 Raises
246 ------
247 SystemError
248 If a collision may occur with another detector, if the EBSD camera is in an error state, if the EBSD mapping is not idle, or if the EBSD camera cannot be inserted.
249 """
250 connect_EBSD()
251 if detectors_will_collide(
252 microscope=microscope,
253 detector_to_insert=tbt.DetectorType.EBSD,
254 ):
255 raise SystemError(
256 f"""Error. Cannot insert EBSD which may collide with another detector.
257 Disallowed detector combinations are: {Constants.detector_collisions}"""
258 )
259 ebsd_cam_status = tbt.RetractableDeviceState(external.EBSD_CameraStatus())
260 map_status = tbt.MapStatus(external.EBSD_MappingStatus())
261 if ebsd_cam_status == tbt.RetractableDeviceState.ERROR:
262 raise SystemError("Error, EDS Camera in error state, workflow stopped.")
263 if map_status != tbt.MapStatus.IDLE:
264 raise SystemError(
265 f'Error, EBSD mapping not in "{tbt.MapStatus.IDLE.value}" state.'
266 )
267 if ebsd_cam_status != tbt.RetractableDeviceState.INSERTED:
268 print("\tInserting EBSD Camera...")
269 # TODO change to constants
270 minutes_to_wait = 3
271 timeout = minutes_to_wait * 60 # seconds
272 waittime = 4 # seconds
273 CCD_view(microscope=microscope)
274 # Oxford Inst requires 2 inserts
275 while True:
276 external.EBSD_InsertCamera() # inserted state
277 if (
278 external.EBSD_CameraStatus()
279 == tbt.RetractableDeviceState.INSERTED.value
280 ):
281 break
282 time.sleep(waittime)
283 timeout = timeout - waittime
284 if timeout < 1:
285 warnings.warn("Warning: EBSD insert timeout. Trying to continue...")
286 break
287 CCD_pause(microscope=microscope)
289 new_ebsd_cam_status = tbt.RetractableDeviceState(external.EBSD_CameraStatus())
290 if new_ebsd_cam_status == tbt.RetractableDeviceState.INSERTED:
291 print("\tEBSD Camera inserted")
292 return True
293 raise SystemError(
294 f'EBSDS Camera is not inserted, currently in "{new_ebsd_cam_status}" state'
295 )
298def insert_EDS(
299 microscope: tbt.Microscope,
300) -> bool:
301 """
302 Insert the EDS camera into the microscope.
304 This function connects to the EDS system, checks for potential collisions with other detectors, and inserts the EDS camera if it is not already inserted. It raises an error if the EDS camera cannot be inserted.
306 Parameters
307 ----------
308 microscope : tbt.Microscope
309 The microscope object for which to insert the EDS camera.
311 Returns
312 -------
313 bool
314 True if the EDS camera is successfully inserted.
316 Raises
317 ------
318 SystemError
319 If a collision may occur with another detector, if the EDS camera is in an error state, if the EDS mapping is not idle, or if the EDS camera cannot be inserted.
320 """
321 connect_EDS()
322 if detectors_will_collide(
323 microscope=microscope,
324 detector_to_insert=tbt.DetectorType.EDS,
325 ):
326 raise SystemError(
327 f"""Error. Cannot insert EDS while CBS not in "Retracted" state.
328 CBS detector currently in "{detector_state(microscope=microscope, detector=tbt.DetectorType.CBS).value}" state."""
329 )
330 eds_cam_status = tbt.RetractableDeviceState(external.EDS_CameraStatus())
331 map_status = tbt.MapStatus(external.EDS_MappingStatus())
332 if eds_cam_status == tbt.RetractableDeviceState.ERROR:
333 raise SystemError("Error, EDS Camera in error state, workflow stopped.")
334 if map_status != tbt.MapStatus.IDLE:
335 raise SystemError(
336 f'Error, EDS mapping not in "{tbt.MapStatus.IDLE.value}" state.'
337 )
338 if eds_cam_status != tbt.RetractableDeviceState.INSERTED:
339 print("\tInserting EDS Camera...")
340 CCD_view(microscope=microscope)
341 external.EDS_InsertCamera()
342 CCD_pause(microscope=microscope)
344 new_eds_cam_status = tbt.RetractableDeviceState(external.EDS_CameraStatus())
345 if new_eds_cam_status == tbt.RetractableDeviceState.INSERTED:
346 print("\tEDS Camera inserted")
347 return True
348 raise SystemError(
349 f'EDS Camera is not inserted, currently in "{new_eds_cam_status}" state'
350 )
353def insert_detector(
354 microscope: tbt.Microscope,
355 detector: tbt.DetectorType,
356 time_delay_s: float = 0.5,
357) -> bool:
358 """
359 Insert the selected detector into the microscope.
361 This function ensures the specified detector is the active one, confirms it is insertable, and inserts it if it is not already inserted. It raises an error if the detector cannot be inserted.
363 Parameters
364 ----------
365 microscope : tbt.Microscope
366 The microscope object for which to insert the detector.
367 detector : tbt.DetectorType
368 The type of the detector to insert.
369 time_delay_s : float, optional
370 The time delay in seconds after inserting the detector (default is 0.5 seconds).
372 Returns
373 -------
374 bool
375 True if the detector is successfully inserted.
377 Raises
378 ------
379 ValueError
380 If the detector is not insertable.
381 SystemError
382 If a collision may occur with another detector or if the detector cannot be inserted.
383 """
384 # ensure detector is the active one
385 microscope.detector.type.value = detector.value
386 # confirm detector is insertable
387 try:
388 state = microscope.detector.state
389 except:
390 raise ValueError(f"{detector.value} detector is not insertable.")
391 if state == tbt.RetractableDeviceState.RETRACTED.value:
392 if detectors_will_collide(
393 microscope=microscope,
394 detector_to_insert=detector,
395 ):
396 raise SystemError(
397 f"""Error. Cannot insert {detector.value} which may collide with another detector.
398 Disallowed detector combinations are: {Constants.detector_collisions}"""
399 )
401 print(f"\tInserting {detector.value} detector...")
402 CCD_view(microscope=microscope)
403 microscope.detector.insert()
404 time.sleep(time_delay_s)
405 CCD_pause(microscope=microscope)
406 if microscope.detector.state == tbt.RetractableDeviceState.INSERTED.value:
407 print(f"\t\t{detector.value} detector inserted.")
408 return True
409 elif state == tbt.RetractableDeviceState.INSERTED.value:
410 print(f"\t{detector.value} detector is already inserted.")
411 return True
412 raise SystemError(
413 f'Cannot insert {detector.value} detector, current detector state is "{state}".'
414 )
417def retract_all_devices(
418 microscope: tbt.Microscope,
419 enable_EBSD: bool,
420 enable_EDS: bool,
421) -> bool:
422 # TODO come up with better system for enable_EBSD_EDS
423 """
424 Retract all insertable devices, including microscope detectors and EBSD/EDS detectors if integrated.
426 This function retracts all insertable devices, first retracting microscope detectors and then retracting EBSD/EDS detectors if they are integrated and enabled.
428 Parameters
429 ----------
430 microscope : tbt.Microscope
431 The microscope object for accessing the Autoscript API.
432 enable_EBSD : bool
433 Whether to enable retraction of the EBSD detector.
434 enable_EDS : bool
435 Whether to enable retraction of the EDS detector.
437 Returns
438 -------
439 bool
440 True if all devices are successfully retracted.
442 Raises
443 ------
444 None
445 """
446 print("\tRetracting devices, do not interact with xTUI during this process...")
447 initial_view = tbt.ViewQuad(microscope.imaging.get_active_view())
448 device_access(microscope)
450 for detector in microscope.detector.type.available_values:
451 detector = tbt.DetectorType(detector) # overwrite
452 state = detector_state(
453 microscope=microscope,
454 detector=detector,
455 )
456 if (
457 state is not tbt.RetractableDeviceState.STATIONARY
458 and state is not tbt.RetractableDeviceState.RETRACTED
459 ):
460 # if (state is not None) and (state != tbt.RetractableDeviceState.RETRACTED):
461 retract_device(
462 microscope=microscope,
463 detector=detector,
464 )
466 # EBSD/EDS detectors:
467 try:
468 external
469 except NameError:
470 pass
471 print("\t\tLaser API not imported, EBSD and EDS detectors are unavailable")
472 else:
473 if enable_EBSD:
474 retract_EBSD(microscope=microscope)
475 if enable_EDS:
476 retract_EDS(microscope=microscope)
477 # else:
478 # warnings.warn(
479 # "\t\tWarning: EBSD and EDS device control API is available but not being used."
480 # )
482 # reset initial settings:
483 img.set_view(
484 microscope=microscope,
485 quad=initial_view,
486 )
487 print("\t\tAll available and enabled devices retracted.")
488 return True
491def connect_EBSD() -> tbt.RetractableDeviceState:
492 """
493 Connect to the EBSD system and retrieve the camera status.
495 This function attempts to connect to the EBSD system and retrieve the camera status. It raises a ConnectionError if the connection fails.
497 Returns
498 -------
499 tbt.RetractableDeviceState
500 The status of the EBSD camera.
502 Raises
503 ------
504 ConnectionError
505 If the EBSD control is not connected.
506 """
507 try:
508 status = external.EBSD_CameraStatus()
509 except:
510 raise ConnectionError(
511 """EBSD control not connected, "Laser Control" from ThermoFisher must be open.
512 Try closing Laser Control, restarting EBSD/EDS software, then opening Laser Control again."""
513 )
514 return tbt.RetractableDeviceState(status)
517def retract_EBSD(microscope: tbt.Microscope) -> bool:
518 """
519 Retract the EBSD camera from the microscope.
521 This function connects to the EBSD system, checks the camera status, and retracts the EBSD camera if it is not already retracted. It raises an error if the EBSD camera cannot be retracted.
523 Parameters
524 ----------
525 microscope : tbt.Microscope
526 The microscope object for which to retract the EBSD camera.
528 Returns
529 -------
530 bool
531 True if the EBSD camera is successfully retracted.
533 Raises
534 ------
535 SystemError
536 If the EBSD camera is in an error state, if the EBSD mapping is not completed, or if the EBSD camera retraction fails.
537 """
538 connect_EBSD()
539 ebsd_status = tbt.RetractableDeviceState(external.EBSD_CameraStatus())
540 if ebsd_status == tbt.RetractableDeviceState.ERROR:
541 raise SystemError(
542 "EBSD Camera in error state, workflow stopped. Check EBSD/EDS software or restart laser control"
543 )
544 if ebsd_status != tbt.RetractableDeviceState.RETRACTED:
545 print(
546 '\t\t\tEBSD Camera Retraction requested, please wait for "mapping complete" verification...'
547 )
548 map_status = tbt.MapStatus(external.EBSD_MappingStatus())
549 # first check if mapping is finished properly
550 minutes_to_wait = 5 # TODO set constant
551 timeout = minutes_to_wait * 60 # seconds #TODO
552 cameraokconfirmations = 3 # synchronization issue with EDAX, try to get map completed 3x before continuing
553 waittime = 10 # seconds
554 if map_status == tbt.MapStatus.ACTIVE:
555 print("\t\t\tEBSD mapping currently active, waiting for mapping to finish")
556 while True:
557 current_map_status = tbt.MapStatus(external.EBSD_MappingStatus())
558 if current_map_status != tbt.MapStatus.ACTIVE:
559 cameraokconfirmations = cameraokconfirmations - 1
560 waittime = 3 # shorten wait time, polling 3x to see if mapping was really completed.
561 time.sleep(waittime)
562 timeout = timeout - waittime
563 if cameraokconfirmations < 1:
564 delay = minutes_to_wait * 60 - timeout
565 print(f"\t\t\t\tEBSD mapping finished. Delay of {delay} seconds")
566 break
567 if timeout < 1:
568 warnings.warn(
569 "\t\t\tWarning, EBSD mapping timeout. Trying to continue..."
570 )
571 break
572 CCD_view(microscope=microscope)
573 print("\t\t\tEBSD Camera retracting...")
574 external.EBSD_RetractCamera()
575 time.sleep(1)
576 CCD_pause(microscope=microscope)
577 current_ebsd_status = tbt.RetractableDeviceState(external.EBSD_CameraStatus())
578 if current_ebsd_status != tbt.RetractableDeviceState.RETRACTED:
579 raise SystemError("Error, EBSD Camera retraction failed, workflow stopped.")
580 print("\t\tEBSD Camera retracted")
581 return True
584def connect_EDS() -> tbt.RetractableDeviceState:
585 """
586 Connect to the EDS system and retrieve the camera status.
588 This function attempts to connect to the EDS system and retrieve the camera status. It raises a ConnectionError if the connection fails.
590 Returns
591 -------
592 tbt.RetractableDeviceState
593 The status of the EDS camera.
595 Raises
596 ------
597 ConnectionError
598 If the EDS control is not connected.
599 """
600 try:
601 status = external.EDS_CameraStatus()
602 except:
603 raise ConnectionError(
604 """EDS control not connected, "Laser Control" from ThermoFisher must be open.
605 Try closing Laser Control, restarting EBSD/EDS software, then opening Laser Control again."""
606 )
607 return tbt.RetractableDeviceState(status)
610def retract_EDS(microscope: tbt.Microscope) -> bool:
611 """
612 Retract the EDS detector from the microscope.
614 This function connects to the EDS system, checks the camera status, and retracts the EDS camera if it is not already retracted. It raises an error if the EDS camera cannot be retracted.
616 Parameters
617 ----------
618 microscope : tbt.Microscope
619 The microscope object for which to retract the EDS camera.
621 Returns
622 -------
623 bool
624 True if the EDS camera is successfully retracted.
626 Raises
627 ------
628 SystemError
629 If the EDS camera is in an error state or if the EDS camera retraction fails.
630 """
631 # print(f"\t\tRetracting EDS detector")
632 connect_EDS()
633 eds_status = tbt.RetractableDeviceState(external.EDS_CameraStatus())
634 if eds_status == tbt.RetractableDeviceState.ERROR:
635 raise SystemError(
636 "EDS Camera in error state, workflow stopped. Check EBSD/EDS software or restart laser control"
637 )
638 if eds_status != tbt.RetractableDeviceState.RETRACTED:
639 print("\t\t\tEDS Camera retracting...")
640 CCD_view(microscope=microscope)
641 external.EDS_RetractCamera()
642 time.sleep(1)
643 if (
644 tbt.RetractableDeviceState(external.EDS_CameraStatus())
645 != tbt.RetractableDeviceState.RETRACTED
646 ):
647 raise SystemError("Error, EDS Camera retraction failed, workflow stopped.")
648 CCD_pause(microscope=microscope)
649 print("\t\tEDS Camera retracted")
650 return True
653def retract_device(microscope: tbt.Microscope, detector: tbt.DetectorType) -> bool:
654 """
655 Retract the specified detector from the microscope.
657 This function ensures the specified detector is the active one, retracts it, and checks its state. It raises an error if the detector cannot be retracted.
659 Parameters
660 ----------
661 microscope : tbt.Microscope
662 The microscope object for which to retract the detector.
663 detector : tbt.DetectorType
664 The type of the detector to retract.
666 Returns
667 -------
668 bool
669 True if the detector is successfully retracted.
671 Raises
672 ------
673 SystemError
674 If the detector cannot be retracted.
675 """
676 CCD_view(microscope=microscope)
677 print(f"\t\tRetracting {detector.value} detector")
678 microscope.detector.type.value = detector.value
679 microscope.detector.retract()
680 state = tbt.RetractableDeviceState(microscope.detector.state)
681 if state != tbt.RetractableDeviceState.RETRACTED:
682 raise SystemError(
683 f"{detector.value} detector not retracted, current detector state is {detector_state.value}"
684 )
685 print(f"\t\t{detector.value} detector retracted")
686 CCD_pause(microscope=microscope)
688 return True
691def CCD_pause(
692 microscope: tbt.Microscope,
693 quad: tbt.ViewQuad = tbt.ViewQuad.LOWER_RIGHT,
694) -> bool:
695 """
696 Pause the CCD camera, typically used after device or stage movement.
698 This function pauses the CCD camera by switching to the specified quadrant, setting the beam device to the CCD camera, and stopping the acquisition. It restores the initial view afterward.
700 Parameters
701 ----------
702 microscope : tbt.Microscope
703 The microscope object for which to pause the CCD camera.
704 quad : tbt.ViewQuad, optional
705 The quadrant to switch to before pausing the CCD camera (default is tbt.ViewQuad.LOWER_RIGHT).
707 Returns
708 -------
709 bool
710 True if the CCD camera is successfully paused.
712 Warnings
713 --------
714 UserWarning
715 If the CCD camera is not installed on the microscope.
716 """
717 initial_view = tbt.ViewQuad(microscope.imaging.get_active_view())
718 img.set_view(microscope=microscope, quad=quad)
719 try:
720 img.set_beam_device(microscope=microscope, device=tbt.Device.CCD_CAMERA)
721 except:
722 warnings.warn("CCD camera is not installed on this microscope.")
723 else:
724 microscope.imaging.stop_acquisition()
725 finally:
726 microscope.imaging.set_active_view(initial_view.value)
727 return True
730def CCD_view(
731 microscope: tbt.Microscope,
732 quad: tbt.ViewQuad = tbt.ViewQuad.LOWER_RIGHT,
733) -> bool:
734 """
735 Visualize detector or stage movement for the user using the CCD camera.
737 This function visualizes detector or stage movement by switching to the specified quadrant, setting the beam device to the CCD camera, and starting the acquisition. It restores the initial view afterward.
739 Parameters
740 ----------
741 microscope : tbt.Microscope
742 The microscope object for which to visualize the movement.
743 quad : tbt.ViewQuad, optional
744 The quadrant to switch to before visualizing the movement (default is tbt.ViewQuad.LOWER_RIGHT).
746 Returns
747 -------
748 bool
749 True if the CCD camera is successfully used for visualization.
751 Warnings
752 --------
753 UserWarning
754 If the CCD camera is not installed on the microscope.
755 """
756 initial_view = tbt.ViewQuad(microscope.imaging.get_active_view())
757 img.set_view(microscope=microscope, quad=quad)
758 try:
759 img.set_beam_device(microscope=microscope, device=tbt.Device.CCD_CAMERA)
760 except:
761 warnings.warn("CCD camera is not installed on this microscope.")
762 else:
763 microscope.imaging.start_acquisition()
764 finally:
765 microscope.imaging.set_active_view(initial_view.value)
766 return True
769def specimen_current(
770 microscope: tbt.Microscope,
771 hfw_mm=Constants.specimen_current_hfw_mm,
772 delay_s=Constants.specimen_current_delay_s,
773) -> float:
774 """
775 Measure the specimen current using the electron beam and return the value in nA.
777 This function sets the beam device to the electron beam, adjusts the horizontal field width (HFW) and detector, starts the acquisition, and measures the specimen current. It then resets the detector and HFW to their initial values.
779 Parameters
780 ----------
781 microscope : tbt.Microscope
782 The microscope object for which to measure the specimen current.
783 hfw_mm : float, optional
784 The horizontal field width in millimeters (default is Constants.specimen_current_hfw_mm).
785 delay_s : float, optional
786 The delay in seconds before measuring the specimen current (default is Constants.specimen_current_delay_s).
788 Returns
789 -------
790 float
791 The measured specimen current in nA.
792 """
793 img.set_beam_device(
794 microscope=microscope,
795 device=tbt.Device.ELECTRON_BEAM,
796 )
797 initial_hfw_m = microscope.beams.electron_beam.horizontal_field_width.value
798 initial_detector = tbt.DetectorType(microscope.detector.type.value)
800 img.detector_type(microscope=microscope, detector=tbt.DetectorType.ETD)
801 img.beam_hfw(
802 beam=tbt.ElectronBeam(settings=tbt.BeamSettings()),
803 microscope=microscope,
804 hfw_mm=hfw_mm,
805 )
806 microscope.imaging.start_acquisition()
807 time.sleep(delay_s)
808 current_na = microscope.state.specimen_current.value * cs.Conversions.A_TO_NA
809 microscope.imaging.stop_acquisition()
811 # reset detector and hfw
812 microscope.beams.electron_beam.horizontal_field_width.value = initial_hfw_m
813 img.detector_type(microscope=microscope, detector=initial_detector)
814 img.beam_hfw(
815 beam=tbt.ElectronBeam(settings=tbt.BeamSettings()),
816 microscope=microscope,
817 hfw_mm=initial_hfw_m * cs.Conversions.M_TO_MM,
818 )
820 return current_na