Skip to content

Commit

Permalink
Make sure PMAC completed_steps_lookup matches length of padded arrays
Browse files Browse the repository at this point in the history
This fixes a bug on I08 with exposure times > 8s
  • Loading branch information
coretl committed Mar 2, 2017
1 parent 7bf0e1a commit d547504
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
31 changes: 23 additions & 8 deletions malcolm/parts/pmac/pmactrajectorypart.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ def configure(self, task, completed_steps, steps_to_do, part_info, params):
task.put(self.child["cs"], cs_port)
futures = self.move_to_start(task, completed_steps)
self.steps_up_to = completed_steps + steps_to_do
self.completed_steps_lookup = []
profile = self.build_generator_profile(completed_steps, do_run_up=True)
task.wait_all(futures)
self.write_profile_points(task, **profile)
Expand Down Expand Up @@ -449,7 +448,7 @@ def move_to_start(self, task, start_index):
return futures

def write_profile_points(self, task, time_array, velocity_mode, trajectory,
user_programs):
user_programs, completed_steps_lookup=None):
"""Build profile using part_tasks
Args:
Expand All @@ -458,7 +457,13 @@ def write_profile_points(self, task, time_array, velocity_mode, trajectory,
trajectory (dict): {axis_name: [positions in EGUs]}
task (Task): Task for running
user_programs (list): List of user programs like TRIG_LIVE_FRAME
completed_steps_lookup (list): If given, when we get to this index,
how many completed steps have we done?
"""
# If not given, make a completed_steps_lookup
if completed_steps_lookup is None:
completed_steps_lookup = [0] * len(time_array)

# Work out which axes should be used and set their resolutions and
# offsets
use = []
Expand All @@ -483,13 +488,18 @@ def write_profile_points(self, task, time_array, velocity_mode, trajectory,
new_time_array = time_array[:i]
new_velocity_mode = velocity_mode[:i]
new_user_programs = user_programs[:i]
new_completed_steps_lookup = completed_steps_lookup[:i]
for _ in range(nsplit):
new_time_array.append(t / nsplit)
new_velocity_mode.append(PREV_TO_NEXT)
new_user_programs.append(NO_PROGRAM)
new_completed_steps_lookup.append(
new_completed_steps_lookup[-1])
time_array = new_time_array + time_array[i+1:]
user_programs = new_user_programs[:-1] + user_programs[i:]
velocity_mode = new_velocity_mode[:-1] + velocity_mode[i:]
completed_steps_lookup = new_completed_steps_lookup[:-1] + \
completed_steps_lookup[i:]

for k, traj in trajectory.items():
new_traj = traj[:i]
Expand Down Expand Up @@ -527,6 +537,9 @@ def write_profile_points(self, task, time_array, velocity_mode, trajectory,
attr_dict["positions%s" % cs_axis] = trajectory[axis_name]
task.put_many(self.child, attr_dict)

# Set completed_steps
self.completed_steps_lookup = completed_steps_lookup

def reset_triggers(self, task):
"""Just call a Move to the run up position ready to start the scan"""
task.put(self.child["numPoints"], 10)
Expand Down Expand Up @@ -584,6 +597,7 @@ def build_generator_profile(self, start_index, do_run_up=False):
time_array = []
velocity_mode = []
user_programs = []
completed_steps_lookup = []

# Cap last point to steps_up_to
self.end_index = start_index + POINTS_PER_BUILD
Expand All @@ -607,7 +621,7 @@ def build_generator_profile(self, start_index, do_run_up=False):
time_array.append(run_up_time)
velocity_mode.append(CURRENT_TO_NEXT)
user_programs.append(TRIG_LIVE_FRAME)
self.completed_steps_lookup.append(0)
completed_steps_lookup.append(start_index)

for i in range(start_index, self.end_index):
point = self.generator.get_point(i)
Expand All @@ -616,15 +630,15 @@ def build_generator_profile(self, start_index, do_run_up=False):
time_array.append(point.duration / 2.0)
velocity_mode.append(PREV_TO_NEXT)
user_programs.append(TRIG_CAPTURE)
self.completed_steps_lookup.append(i)
completed_steps_lookup.append(i)
for axis_name, positions in trajectory.items():
positions.append(point.positions[axis_name])

# Add upper bound
time_array.append(point.duration / 2.0)
velocity_mode.append(PREV_TO_NEXT)
user_programs.append(TRIG_LIVE_FRAME)
self.completed_steps_lookup.append(i + 1)
completed_steps_lookup.append(i + 1)
for axis_name, positions in trajectory.items():
positions.append(point.upper[axis_name])

Expand Down Expand Up @@ -665,7 +679,7 @@ def build_generator_profile(self, start_index, do_run_up=False):
for axis_name in trajectory:
trajectory[axis_name] += \
profile["trajectory"][axis_name]
self.completed_steps_lookup += [i + 1] * len(
completed_steps_lookup += [i + 1] * len(
profile["time_array"])

# Add the last tail off point
Expand All @@ -689,10 +703,11 @@ def build_generator_profile(self, start_index, do_run_up=False):
time_array.append(tail_off_time)
velocity_mode.append(ZERO_VELOCITY)
user_programs.append(TRIG_ZERO)
self.completed_steps_lookup.append(self.end_index)
completed_steps_lookup.append(self.end_index)

profile = dict(time_array=time_array, velocity_mode=velocity_mode,
trajectory=trajectory, user_programs=user_programs)
trajectory=trajectory, user_programs=user_programs,
completed_steps_lookup=completed_steps_lookup)
return profile

def points_joined(self, last_point, point):
Expand Down
43 changes: 39 additions & 4 deletions tests/test_parts/test_pmac/test_pmactrajectorypart.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,15 @@ def make_part_info(self, x_pos=0.5, y_pos=0.0):
)
return part_info

def do_configure(self, axes_to_scan, completed_steps=0, x_pos=0.5, y_pos=0.0):
def do_configure(self, axes_to_scan, completed_steps=0, x_pos=0.5,
y_pos=0.0, duration=1.0):
part_info = self.make_part_info(x_pos, y_pos)
task = Mock()
steps_to_do = 3 * len(axes_to_scan)
params = Mock()
xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate_direction=True)
ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
mutator = FixedDurationMutator(1.0)
mutator = FixedDurationMutator(duration)
params.generator = CompoundGenerator([ys, xs], [], [mutator])
params.axesToMove = axes_to_scan
self.o.configure(task, completed_steps, steps_to_do, part_info, params)
Expand All @@ -323,6 +324,8 @@ def test_configure(self):
self.assertEqual(task.post_async.call_count, 1)
self.assertEqual(task.put.call_count, 2)
self.assertEqual(task.put.call_args_list[0],
call(self.child["numPoints"], 4000000))
self.assertEqual(task.put.call_args_list[1],
call(self.child["cs"], "CS1"))
self.check_resolutions_and_use(task.put_many.call_args_list[0][0][1])
self.assertEqual(task.put_many.call_args_list[1][0][1], dict(
Expand Down Expand Up @@ -360,8 +363,6 @@ def test_configure(self):
positionsB=[
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05,
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]))
self.assertEqual(task.put.call_args_list[1],
call(self.child["numPoints"], 18))

@patch("malcolm.parts.pmac.pmactrajectorypart.INTERPOLATE_INTERVAL", 0.2)
def test_2_axis_move_to_start(self):
Expand Down Expand Up @@ -438,6 +439,40 @@ def test_multi_run(self):
-0.125, -0.1375],
))

@patch("malcolm.parts.pmac.pmactrajectorypart.INTERPOLATE_INTERVAL", 0.2)
def test_long_steps_lookup(self):
task = self.do_configure(
axes_to_scan=["x"], completed_steps=3, x_pos=0.62506, duration=14.0)
self.assertEqual(task.put_many.call_args_list[1][0][1], dict(
timeArray=[7143, 3500000,
3500000, 3500000,
3500000, 3500000,
3500000, 3500000,
3500000, 3500000,
3500000, 3500000,
3500000, 7143],
velocityMode=[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
userPrograms=[3, 0, 4, 0, 3, 0, 4, 0, 3, 0, 4, 0, 2, 8],
pointsToBuild=14,
positionsA=[0.625,
0.5625,
0.5,
0.4375,
0.375,
0.3125,
0.25,
0.1875,
0.125,
0.0625,
0.0,
-0.0625,
-0.125,
-0.1250637755102041],
))
self.assertEqual(self.o.completed_steps_lookup,
[3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6])


@patch("malcolm.parts.pmac.pmactrajectorypart.INTERPOLATE_INTERVAL", 2.0)
def test_long_move(self):
task = self.do_configure(axes_to_scan=["x"], x_pos=-10.1375)
Expand Down

0 comments on commit d547504

Please sign in to comment.