This commit is contained in:
2025-06-16 22:36:00 +02:00
parent a9b275c0b9
commit e11fb31386

View File

@@ -49,6 +49,16 @@ class TomoComponents:
file_path: str = "", file_path: str = "",
frames_per_trigger: int = 1, frames_per_trigger: int = 1,
): ):
"""
Restart the cameras with a new configuration.
This is typically used to reset the cameras during another scan, e.g. before acquiring dark or flat images.
Args:
name (str): Name of the configuration to restart with.
num_images (int): Number of images to acquire.
prefix (str): Prefix for the file names.
file_path (str): Path where the files will be saved.
frames_per_trigger (int): Number of frames to acquire per trigger.
"""
if not prefix: if not prefix:
return return
for cam in self.cameras: for cam in self.cameras:
@@ -64,24 +74,32 @@ class TomoComponents:
def scan_report_instructions(self): def scan_report_instructions(self):
""" """
Generate scan report instructions for the dark image acquisition. Generate scan report instructions for the acquisition.
This method provides the necessary instructions to listen to the camera progress during the scan. This method provides the necessary instructions to listen to the camera progress during the scan.
""" """
if not self.components.cameras: if not self.cameras:
yield from super().scan_report_instructions()
return return
# Use the first camera or "gfcam" if available for reporting # Use the first camera or "gfcam" if available for reporting
report_camera = ( report_camera = "gfcam" if "gfcam" in self.cameras else self.cameras[0]
"gfcam" if "gfcam" in self.components.cameras else self.components.cameras[0]
)
yield from self.stubs.scan_report_instruction({"device_progress": [report_camera]}) yield from self.stubs.scan_report_instruction({"device_progress": [report_camera]})
def complete(self): def complete(self):
"""
Complete the acquisition by sending an RPC to each camera.
This method is typically called after the acquisition is done to finalize the process and start
writing the virtual dataset.
"""
for cam in self.cameras: for cam in self.cameras:
yield from self.stubs.send_rpc_and_wait(device=cam, func_name="on_complete") yield from self.stubs.send_rpc_and_wait(device=cam, func_name="on_complete")
def restore_configs(self, name: str): def restore_configs(self, name: str):
"""
Restore the camera configurations after an acquisition.
Args:
name (str): Name of the configuration to restore.
"""
for cam in self.cameras: for cam in self.cameras:
yield from self.stubs.send_rpc_and_wait( yield from self.stubs.send_rpc_and_wait(
device=cam, func_name="restore_config", name=name device=cam, func_name="restore_config", name=name
@@ -121,7 +139,7 @@ class TomoComponents:
name=name, prefix=name, num_images=num_images, frames_per_trigger=num_images name=name, prefix=name, num_images=num_images, frames_per_trigger=num_images
) )
# yield from self.close_shutter() # yield from self.close_shutter()
yield from self.stubs.trigger(min_wait=exposure_time) yield from self.stubs.trigger(min_wait=exposure_time * num_images)
yield from self.complete() yield from self.complete()
yield from self.update_live_processing_references(ref_type="dark") yield from self.update_live_processing_references(ref_type="dark")
if restart: if restart:
@@ -149,7 +167,7 @@ class TomoComponents:
name=name, prefix=name, num_images=num_images, frames_per_trigger=num_images name=name, prefix=name, num_images=num_images, frames_per_trigger=num_images
) )
# yield from self.open_shutter() # yield from self.open_shutter()
yield from self.stubs.trigger(min_wait=exposure_time) yield from self.stubs.trigger(min_wait=exposure_time * num_images)
yield from self.complete() yield from self.complete()
yield from self.update_live_processing_references(ref_type="flat") yield from self.update_live_processing_references(ref_type="flat")
@@ -165,8 +183,9 @@ class TomoComponents:
class AcquireDark(ScanBase): class AcquireDark(ScanBase):
scan_name = "acquire_dark" scan_name = "acquire_dark"
gui_config = {"Acquisition Parameters": ["num_images", "exp_time"]}
def __init__(self, exp_time: float, frames_per_trigger: int = 1, **kwargs): def __init__(self, num_images: int, exp_time: float, **kwargs):
""" """
Acquire dark images. Acquire dark images.
@@ -177,6 +196,7 @@ class AcquireDark(ScanBase):
Returns: Returns:
ScanReport ScanReport
""" """
frames_per_trigger = num_images if num_images > 0 else 1
super().__init__(frames_per_trigger=frames_per_trigger, exp_time=exp_time, **kwargs) super().__init__(frames_per_trigger=frames_per_trigger, exp_time=exp_time, **kwargs)
self.components = TomoComponents(self) self.components = TomoComponents(self)
@@ -184,22 +204,28 @@ class AcquireDark(ScanBase):
yield from self.components.scan_report_instructions() yield from self.components.scan_report_instructions()
def scan_core(self): def scan_core(self):
yield from self.components.acquire_dark(self.frames_per_trigger, self.exp_time, restart=False) yield from self.components.acquire_dark(
self.frames_per_trigger, self.exp_time, restart=False
)
class AcquireFlat(ScanBase): class AcquireFlat(ScanBase):
scan_name = "acquire_flat" scan_name = "acquire_flat"
gui_config = {"Acquisition Parameters": ["num_images", "exp_time"]}
def __init__(self, exp_time: float, frames_per_trigger: int = 1, **kwargs): def __init__(self, num_images: int, exp_time: float, **kwargs):
""" """
Acquire flat images. Acquire flat images.
Args: Args:
num_images (int): Number of flat images to acquire. num_images (int): Number of flat images to acquire.
exp_time (float): Exposure time for each flat image in seconds. exp_time (float): Exposure time for each flat image in seconds.
frames_per_trigger (int): Number of frames to acquire per trigger.
Returns: Returns:
ScanReport ScanReport
""" """
frames_per_trigger = num_images if num_images > 0 else 1
super().__init__(frames_per_trigger=frames_per_trigger, exp_time=exp_time, **kwargs) super().__init__(frames_per_trigger=frames_per_trigger, exp_time=exp_time, **kwargs)
self.components = TomoComponents(self) self.components = TomoComponents(self)
@@ -207,12 +233,16 @@ class AcquireFlat(ScanBase):
yield from self.components.scan_report_instructions() yield from self.components.scan_report_instructions()
def scan_core(self): def scan_core(self):
yield from self.components.acquire_flat(self.frames_per_trigger, self.exp_time, restart=False) yield from self.components.acquire_flat(
self.frames_per_trigger, self.exp_time, restart=False
)
class AcquireReferences(ScanBase): class AcquireReferences(ScanBase):
scan_name = "acquire_refs" scan_name = "acquire_refs"
gui_config = {"Acquisition Parameters": ["num_darks", "num_flats", "exp_time"]}
def __init__(self, num_darks:int, num_flats:int, exp_time: float, frames_per_trigger: int = 1, **kwargs): def __init__(self, num_darks: int, num_flats: int, exp_time: float, **kwargs):
""" """
Acquire flats and darks. Acquire flats and darks.
@@ -220,11 +250,12 @@ class AcquireReferences(ScanBase):
num_darks (int): Number of dark images to acquire. num_darks (int): Number of dark images to acquire.
num_flats (int): Number of flat images to acquire. num_flats (int): Number of flat images to acquire.
exp_time (float): Exposure time for each flat image in seconds. exp_time (float): Exposure time for each flat image in seconds.
frames_per_trigger (int): Number of frames to acquire per trigger.
Returns: Returns:
ScanReport ScanReport
""" """
super().__init__(frames_per_trigger=frames_per_trigger, exp_time=exp_time, **kwargs) super().__init__(exp_time=exp_time, **kwargs)
self.num_darks = num_darks self.num_darks = num_darks
self.num_flats = num_flats self.num_flats = num_flats
self.components = TomoComponents(self) self.components = TomoComponents(self)
@@ -233,7 +264,8 @@ class AcquireReferences(ScanBase):
yield from self.components.scan_report_instructions() yield from self.components.scan_report_instructions()
def scan_core(self): def scan_core(self):
yield from self.components.acquire_references(self.num_darks, self.num_flats, self.frames_per_trigger, self.exp_time, restart=False) yield from self.components.acquire_references(self.num_darks, self.num_flats, self.exp_time)
class TomoScan(LineScan): class TomoScan(LineScan):
scan_name = "tomo_line_scan" scan_name = "tomo_line_scan"