Source code for malcolm.modules.pmac.parts.beamselectorpart

from annotypes import add_call_types
from scanpointgenerator import CompoundGenerator, LineGenerator, StaticPointGenerator

from malcolm.modules import builtin, scanning

from ..util import MIN_INTERVAL, MIN_TIME
from .pmacchildpart import PmacChildPart, VelocityModes

# 80 char line lengths...
AIV = builtin.parts.AInitialVisibility

# Pull re-used annotypes into our namespace in case we are subclassed
APartName = builtin.parts.APartName
AMri = builtin.parts.AMri
AAxisName = builtin.parts.AValue
AAngle = builtin.parts.AValue
ATime = builtin.parts.AValue


[docs]class BeamSelectorPart(PmacChildPart): def __init__( self, name: APartName, mri: AMri, selectorAxis: AAxisName, tomoAngle: AAngle, diffAngle: AAngle, moveTime: ATime, initial_visibility: AIV = False, ) -> None: super().__init__(name, mri, initial_visibility) self.selectorAxis = selectorAxis try: self.tomoAngle = float(tomoAngle) self.diffAngle = float(diffAngle) self.move_time = float(moveTime) except ValueError: self.tomoAngle = 0.0 self.diffAngle = 0.0 self.move_time = 0.500 # seconds
[docs] @add_call_types def on_configure( self, context: scanning.hooks.AContext, completed_steps: scanning.hooks.ACompletedSteps, steps_to_do: scanning.hooks.AStepsToDo, part_info: scanning.hooks.APartInfo, generator: scanning.hooks.AGenerator, axesToMove: scanning.hooks.AAxesToMove, ) -> None: # Double the number of cycles to get rotations static_axis = generator.generators[0] assert isinstance( static_axis, StaticPointGenerator ), "Static Point Generator not configured correctly" static_axis = StaticPointGenerator(size=static_axis.size * 2) steps_to_do *= 2 # Create a linear scan axis (proper rotation) selector_axis = LineGenerator( self.selectorAxis, "deg", self.tomoAngle, self.diffAngle, 1, alternate=True ) axesToMove = [self.selectorAxis] def get_minturnaround(): # See if there is a minimum turnaround infos = scanning.infos.MinTurnaroundInfo.filter_values(part_info) if infos: assert ( len(infos) == 1 ), "Expected 0 or 1 MinTurnaroundInfos, got %d" % len(infos) min_turnaround = max(MIN_TIME, infos[0].gap) min_interval = infos[0].interval else: min_turnaround = MIN_TIME min_interval = MIN_INTERVAL return min_turnaround, min_interval # Calculate the exposure time min_turnaround = get_minturnaround()[0] cycle_duration = generator.duration exposure_time = cycle_duration / 2 - self.move_time if exposure_time < min_turnaround: exposure_time = min_turnaround new_generator = CompoundGenerator( [static_axis, selector_axis], [], [], duration=self.move_time, continuous=True, delay_after=exposure_time, ) new_generator.prepare() # Reduce the exposure of the camera/detector generator.duration = exposure_time super().on_configure( context, completed_steps, steps_to_do, part_info, new_generator, axesToMove )
def add_tail_off(self): # The current point current_point = self.generator.get_point(self.steps_up_to - 1) # the next point is same as the previous next_point = self.generator.get_point(self.steps_up_to - 2) # insert the turnaround points self.insert_gap(current_point, next_point, self.steps_up_to + 1) # Do the last move # user_program = self.get_user_program(PointType.TURNAROUND) # self.add_profile_point(tail_off_time, ZERO_VELOCITY, # user_program, # self.steps_up_to, axis_points) # Mangle the last point to end the scan self.profile["velocityMode"][-1] = VelocityModes.ZERO_VELOCITY # user_program = self.get_user_program(PointType.TURNAROUND) # self.profile["userProgram"][-1] = user_program self.end_index = self.steps_up_to