def test_alternate_fails_unless_squashed(self): tmp_dir = mkdtemp() + os.path.sep cols, rows, alternate = 3000, 2000, True self.steps_to_do = cols * rows xs = LineGenerator("x", "mm", 0.0, 0.5, cols, alternate=alternate) ys = LineGenerator("y", "mm", 0.0, 0.1, rows) self.generator = CompoundGenerator([ys, xs], [], [], 0.1) self.generator.prepare() with self.assertRaises(BadValueError): self.o.on_configure( self.context, self.completed_steps, self.steps_to_do, generator=self.generator, fileDir=tmp_dir, formatName="odin3", ) self.generator = CompoundGenerator( [ys, xs], [SquashingExcluder(axes=["x", "y"])], [], 0.1) self.generator.prepare() self.o.on_configure( self.context, self.completed_steps, self.steps_to_do, generator=self.generator, fileDir=tmp_dir, formatName="odin2", )
def test_validate_with_positive_generator_duration_and_min_acquire_period( self): xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) # duration = 0.1 is fine generator = CompoundGenerator([ys, xs], [], [], 0.1) self.o.on_validate(self.context, generator) # duration = 0.005 < min_acquire_period generator = CompoundGenerator([ys, xs], [], [], 0.005) self.assertRaises(AssertionError, self.o.on_validate, self.context, generator)
def test_validate(self): params = MagicMock() xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) params.generator = CompoundGenerator([ys, xs], [], [], 0.0002) params.generator.prepare() self.o.validate(ANY, ANY, params)
def test_load_more_positions(self): child = MagicMock() current_index = 1 # Haven't done point 4 or 5 yet self.o.end_index = 4 self.o.steps_up_to = 6 xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) self.o.generator = CompoundGenerator([ys, xs], [], []) self.o.generator.prepare() self.o.load_more_positions(current_index, child) expected_xml = """<?xml version="1.0" ?> <pos_layout> <dimensions> <dimension name="d0" /> <dimension name="d1" /> <dimension name="FilePluginClose" /> </dimensions> <positions> <position FilePluginClose="0" d0="1" d1="1" /> <position FilePluginClose="1" d0="1" d1="0" /> </positions> </pos_layout>""".replace("\n", "") assert child.mock_calls == [call.xml.put_value(expected_xml)] assert self.o.end_index == 6
def test_configure_stepped(self): xs = LineGenerator("x", "mm", 0.0, 0.3, 4) ys = LineGenerator("y", "mm", 0.0, 0.2, 3) generator = CompoundGenerator([ys, xs], [], [], 1.0, continuous=False) generator.prepare() self.set_motor_attributes() self.set_attributes(self.child, rowTrigger="Motion Controller") self.set_attributes(self.child_seq1, bita="TTLIN1.VAL") self.set_attributes(self.child_seq2, bita="TTLIN1.VAL") axes_to_move = ["x", "y"] seq_rows = self.get_sequencer_rows(generator, axes_to_move) # Triggers B0 = Trigger.BITA_0 B1 = Trigger.BITA_1 IT = Trigger.IMMEDIATE # Half a frame hf = 62500000 expected = SequencerRows() for i in range(11): expected.add_seq_entry(1, B1, 0, hf, 1, 0) expected.add_seq_entry(1, B0, 0, MIN_PULSE, 0, 1) expected.add_seq_entry(1, B1, 0, hf, 1, 0) expected.add_seq_entry(1, IT, 0, MIN_PULSE, 0, 1) expected.add_seq_entry(0, IT, 0, MIN_PULSE, 0, 0) assert seq_rows.as_tuples() == expected.as_tuples()
def test_configure_continuous(self): xs = LineGenerator("x", "mm", 0.0, 0.3, 4, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) generator = CompoundGenerator([ys, xs], [], [], 1.0) self.set_motor_attributes() axes_to_move = ["x", "y"] seq_rows = self.get_sequencer_rows(generator, axes_to_move) # Triggers GT = Trigger.POSA_GT IT = Trigger.IMMEDIATE LT = Trigger.POSA_LT # Half a frame hf = 62500000 # Half how long to be blind for hb = 22500000 expected = SequencerRows() expected.add_seq_entry(count=1, trigger=LT, position=50, half_duration=hf, live=1, dead=0) expected.add_seq_entry(3, IT, 0, hf, 1, 0) expected.add_seq_entry(1, IT, 0, hb, 0, 1) expected.add_seq_entry(1, GT, -350, hf, 1, 0) expected.add_seq_entry(3, IT, 0, hf, 1, 0) expected.add_seq_entry(1, IT, 0, MIN_PULSE, 0, 1) expected.add_seq_entry(0, IT, 0, MIN_PULSE, 0, 0) assert seq_rows.as_tuples() == expected.as_tuples()
def test_configure_and_run_prepare_components(self, buffer_class): buffer_instance = buffer_class.return_value buffer_instance.run.return_value = [] xs = LineGenerator("x", "mm", 0.0, 0.3, 4, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) generator = CompoundGenerator([ys, xs], [], [], 1.0) generator.prepare() completed_steps = 0 steps_to_do = generator.size self.set_motor_attributes() axes_to_move = ["x", "y"] self.o.on_configure(self.context, completed_steps, steps_to_do, {}, generator, axes_to_move) assert self.o.generator is generator assert self.o.loaded_up_to == completed_steps assert self.o.scan_up_to == completed_steps + steps_to_do # Other unit tests check that the sequencer rows used here are correct buffer_instance.configure.assert_called_once() self.gate_part.enable_set.assert_not_called() buffer_instance.run.assert_not_called() # The SRGate should only be enabled by on_pre_run() here. self.o.on_pre_run(self.context) self.o.on_run(self.context) self.gate_part.enable_set.assert_called_once() buffer_instance.run.assert_called_once()
def test_load_more_positions(self): task = MagicMock() current_index = 1 # Haven't done point 4 or 5 yet self.o.end_index = 4 self.o.steps_up_to = 6 xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) self.o.generator = CompoundGenerator([ys, xs], [], []) self.o.generator.prepare() self.o.load_more_positions(current_index, task) expected_xml = """<?xml version="1.0" ?> <pos_layout> <dimensions> <dimension name="d0" /> <dimension name="d1" /> <dimension name="FilePluginClose" /> </dimensions> <positions> <position FilePluginClose="0" d0="1" d1="1" /> <position FilePluginClose="1" d0="1" d1="0" /> </positions> </pos_layout>""".replace("\n", "") task.put.assert_called_once_with(self.child["xml"], expected_xml) self.assertEqual(self.o.end_index, 6)
def test_complex_masks(self): tg = LineGenerator("t", "mm", 1, 5, 5) zg = LineGenerator("z", "mm", 0, 4, 5, alternate=True) yg = LineGenerator("y", "mm", 1, 5, 5, alternate=True) xg = LineGenerator("x", "mm", 2, 6, 5, alternate=True) r1 = CircularROI([4., 4.], 1.5) e1 = ROIExcluder([r1], ["y", "x"]) e2 = ROIExcluder([r1], ["z", "y"]) g = CompoundGenerator([tg, zg, yg, xg], [e1, e2], []) g.prepare() t_mask = [True] * 5 iy = 0 ix = 0 xyz_mask = [] xyz = [] for z in range_(0, 5): for y in (range_(1, 6) if iy % 2 == 0 else range_(5, 0, -1)): for x in (range_(2, 7) if ix % 2 == 0 else range_(6, 1, -1)): xyz_mask.append( (x-4)**2 + (y-4)**2 <= 1.5**2 \ and (y-4)**2 + (z-4)**2 <= 1.5**2) xyz.append((x, y, z)) ix += 1 iy += 1 self.assertEqual(t_mask, g.dimensions[0].mask.tolist()) self.assertEqual(xyz_mask, g.dimensions[1].mask.tolist())
def test_staticpointgen_in_alternating(self): x = LineGenerator("x", "mm", 0, 1, 3, True) y = LineGenerator("y", "cm", 2, 3, 4, False) m = StaticPointGenerator(5) r = CircularROI((0.5, 2.5), 0.4) e = ROIExcluder([r], ["x", "y"]) g = CompoundGenerator([y, m, x], [e], []) g.prepare() expected_positions = [] x_positions = [0.0, 0.5, 1.0] direction = 1 for yp in [2.0, 2 + 1. / 3, 2 + 2. / 3, 3.0]: for mp in range_(5): for xp in x_positions[::direction]: if (xp - 0.5)**2 + (yp - 2.5)**2 <= 0.4**2: expected_positions.append({"y": yp, "x": xp}) direction *= -1 positions = [point.positions for point in g.iterator()] self.assertEqual(expected_positions, positions) self.assertEqual(len(expected_positions), g.size) self.assertEqual((len(expected_positions), ), g.shape) self.assertEqual(["y", "x"], g.axes) self.assertEqual({"y": "cm", "x": "mm"}, g.units) self.assertEqual(1, len(g.dimensions))
def test_configure(self): xs = LineGenerator("x", "mm", 0.0, 0.5, 3000, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2000) generator = CompoundGenerator([ys, xs], [], [], 0.1) generator.prepare() completed_steps = 0 steps_to_do = 2000 * 3000 # We wait to be armed, so set this here self.set_attributes(self.child, acquiring=True, fanStateReady=1) self.o.on_configure( self.context, completed_steps, steps_to_do, {}, generator=generator, fileDir="/tmp", ) assert self.child.handled_requests.mock_calls == [ call.put("arrayCallbacks", True), call.put("arrayCounter", 0), call.put("imageMode", "Multiple"), call.put("numImages", 6000000), call.put("numImagesPerSeries", 1), call.post("start"), ]
def grid_fly(flyer, y, ystart, ystop, ynum, x, xstart, xstop, xnum): generator = CompoundGenerator( generators=[ LineGenerator(y.name, "mm", ystart, ystop, ynum), LineGenerator(x.name, "mm", xstart, xstop, xnum), ], duration=0.1, ) mapping.configure(dict(generator=generator)) md = dict( hints=dict( gridding="rectilinear", dimensions=[([y.name], "primary"), ([x.name], "primary")], ), shape=(ynum, xnum), extents=([ystart, ystop], [xstart, xstop]), ) uid = yield from bps.open_run(md) yield from bps.kickoff(flyer, wait=True) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.complete(flyer, group="flyer") for _ in range(int(ynum * xnum * 0.1)): yield from bps.sleep(1) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.wait(group="flyer") yield from bps.collect(flyer, stream=True) yield from bps.close_run() return uid
def test_alternating_line_with_staticpointgen(self): x = LineGenerator("x", "mm", 0, 1, 3, True) m = StaticPointGenerator(5) g = CompoundGenerator([m, x], [], []) g.prepare() expected_positions = [ {'x':0.0}, {'x':0.5}, {'x':1.0}, {'x':1.0}, {'x':0.5}, {'x':0.0}, {'x':0.0}, {'x':0.5}, {'x':1.0}, {'x':1.0}, {'x':0.5}, {'x':0.0}, {'x':0.0}, {'x':0.5}, {'x':1.0}] positions = [point.positions for point in g.iterator()] self.assertEqual(expected_positions, positions) self.assertEqual(15, g.size) self.assertEqual((5, 3), g.shape) self.assertEqual(["x"], g.axes) self.assertEqual({"x":"mm"}, g.units) expected_dimensions = [{"axes":[], "size":5, "alternate":False, "upper":[], "lower":[]}, {"axes":["x"], "size":3, "alternate":True, "upper":[1.0], "lower":[0.0]}] dimensions = [{"axes":d.axes, "size":d.size, "alternate":d.alternate, "upper":d.upper, "lower":d.lower} for d in g.dimensions] self.assertEqual(expected_dimensions, dimensions)
def test_excluder_spread_axes(self): sp = SpiralGenerator(["s1", "s2"], ["mm", "mm"], centre=[0, 0], radius=1, scale=0.5, alternate=True) y = LineGenerator("y", "mm", 0, 1, 3, True) z = LineGenerator("z", "mm", -2, 3, 6, True) e = ROIExcluder([CircularROI([0., 0.], 1.0)], ["s1", "z"]) g = CompoundGenerator([z, y, sp], [e], []) g.prepare() s1_pos, s2_pos = sp.positions["s1"], sp.positions["s2"] s1_pos = np.tile(np.append(s1_pos, s1_pos[::-1]), 9) s2_pos = np.tile(np.append(s2_pos, s2_pos[::-1]), 9) y_pos = np.tile(np.repeat(np.array([0, 0.5, 1.0, 1.0, 0.5, 0]), sp.size), 3) z_pos = np.repeat(np.array([-2, -1, 0, 1, 2, 3]), sp.size * 3) mask_func = lambda ps1, pz: ps1**2 + pz**2 <= 1 mask = mask_func(s1_pos, z_pos) expected_s1 = s1_pos[mask] expected_s2 = s2_pos[mask] expected_y = y_pos[mask] expected_z = z_pos[mask] expected_positions = [{'s1':ps1, 's2':ps2, 'y':py, 'z':pz} for (ps1, ps2, py, pz) in zip(expected_s1, expected_s2, expected_y, expected_z)] positions = [point.positions for point in list(g.iterator())] self.assertEqual(positions, expected_positions)
def test_raise_before_prepare(self): x = LineGenerator("x", "mm", 1.0, 1.2, 3, True) g = CompoundGenerator([x], [], []) with self.assertRaises(ValueError): g.get_point(0) with self.assertRaises(ValueError): for p in g.iterator(): pass
def test_bounds_consistency_in_compound(self): liss = LissajousGenerator(["x", "y"], ["mm", "mm"], [0., 0.], [2., 2.], 4, 100, True) line = LineGenerator("z", "mm", 0, 1, 3) m = RandomOffsetMutator(1, ["x", "y"], [0.1, 0.1]) g = CompoundGenerator([line, liss], [], []) gm = CompoundGenerator([line, liss], [], [m]) g.prepare() gm.prepare() points = list(gm.iterator()) lx = [l.upper["x"] for l in points[:-1]] rx = [r.lower["x"] for r in points[1:]] self.assertListAlmostEqual(lx, rx) ly = [l.upper["y"] for l in points[:-1]] ry = [r.lower["y"] for r in points[1:]] self.assertListAlmostEqual(ly, ry)
def test_configure(self): task = MagicMock() params = MagicMock() xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) params.generator = CompoundGenerator([ys, xs], [], []) params.generator.prepare() completed_steps = 2 steps_to_do = 4 part_info = ANY self.o.configure(task, completed_steps, steps_to_do, part_info, params) self.assertEqual( task.post_async.call_args_list, [call(self.child["delete"]), call(self.child["start"])]) task.put_many_async.assert_called_once_with( self.child, dict(enableCallbacks=True, idStart=3)) expected_xml = """<?xml version="1.0" ?> <pos_layout> <dimensions> <dimension name="d0" /> <dimension name="d1" /> <dimension name="FilePluginClose" /> </dimensions> <positions> <position FilePluginClose="0" d0="0" d1="2" /> <position FilePluginClose="0" d0="1" d1="2" /> <position FilePluginClose="0" d0="1" d1="1" /> <position FilePluginClose="1" d0="1" d1="0" /> </positions> </pos_layout>""".replace("\n", "") task.put.assert_called_once_with(self.child["xml"], expected_xml)
def test_separate_indexes(self): x1 = LineGenerator("x1", "mm", -1.0, 1.0, 5, False) y1 = LineGenerator("y1", "mm", -1.0, 1.0, 5, False) z1 = LineGenerator("z1", "mm", -1.0, 1.0, 5, False) x2 = LineGenerator("x2", "mm", -1.0, 1.0, 5, False) y2 = LineGenerator("y2", "mm", -1.0, 1.0, 5, False) x3 = LineGenerator("x3", "mm", 0, 1.0, 5, False) y3 = LineGenerator("y3", "mm", 0, 1.0, 5, False) r = CircularROI([0, 0], 1) e1 = ROIExcluder([r], ["x1", "y1"]) e2 = ROIExcluder([r], ["y1", "z1"]) e3 = ROIExcluder([r], ["x1", "y1"]) e4 = ROIExcluder([r], ["x2", "y2"]) e5 = ROIExcluder([r], ["x3", "y3"]) g = CompoundGenerator([x3, y3, y2, x2, z1, y1, x1], [e1, e2, e3, e4, e5], []) g.prepare() p = [(x / 2., y / 2., z / 2.) for z in range_(-2, 3) for y in range_(-2, 3) for x in range_(-2, 3)] m1 = [x * x + y * y <= 1 for (x, y, z) in p] m2 = [y * y + z * z <= 1 for (x, y, z) in p] expected_mask = [(b1 and b2) for (b1, b2) in zip(m1, m2)] self.assertEqual(expected_mask, g.dimensions[2].mask.tolist()) p = [(x / 2., y / 2.) for y in range_(-2, 3) for x in range_(-2, 3)] expected_mask = [x * x + y * y <= 1 for (x, y) in p] self.assertEqual(expected_mask, g.dimensions[1].mask.tolist()) p = [(x / 4., y / 4.) for y in range_(0, 5) for x in range_(0, 5)] expected_mask = [x * x + y * y <= 1 for (x, y) in p] self.assertEqual(expected_mask, g.dimensions[0].mask.tolist())
def test_configure(self): xs = LineGenerator("x", "mm", 0.0, 0.5, 3000, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2000) generator = CompoundGenerator([ys, xs], [], [], 0.1) generator.prepare() completed_steps = 0 steps_to_do = 2000 * 3000 # We wait to be armed, so set this here self.set_attributes(self.child, acquiring=True) # This is what the detector does when exposure and acquirePeriod are # both set to 0.1 self.set_attributes(self.child, exposure=0.1, acquirePeriod=0.105) self.o.configure(self.context, completed_steps, steps_to_do, {}, generator=generator) assert self.child.handled_requests.mock_calls == [ call.put('exposure', 0.1), call.put('acquirePeriod', 0.1), call.put('arrayCallbacks', True), call.put('arrayCounter', 0), # duration - readout - fudge_factor - crystal offset call.put('exposure', pytest.approx(0.1 - 0.005 - 0.0014 - 5e-6)), call.put('imageMode', 'Multiple'), call.put('numImages', 6000000), call.put('acquirePeriod', 0.1 - 5e-6), call.post('start') ]
def test_to_dict(self): self.g = CompoundGenerator([self.l2, self.l1], [self.e1], [self.m1], -1, True) self.l1.to_dict.return_value = self.l1_dict self.l2.to_dict.return_value = self.l2_dict self.e1.to_dict.return_value = self.e1_dict self.m1.to_dict.return_value = self.m1_dict gen_list = [self.l2_dict, self.l1_dict] mutators_list = [self.m1_dict] excluders_list = [self.e1_dict] expected_dict = dict() expected_dict[ 'typeid'] = "scanpointgenerator:generator/CompoundGenerator:1.0" expected_dict['generators'] = gen_list expected_dict['excluders'] = excluders_list expected_dict['mutators'] = mutators_list expected_dict['duration'] = -1 expected_dict['continuous'] = True d = self.g.to_dict() self.assertEqual(expected_dict, d)
def test_configure_and_run_prepare_no_axes(self, buffer_class): buffer_instance = buffer_class.return_value buffer_instance.run.return_value = [] generator = CompoundGenerator([StaticPointGenerator(size=1)], [], [], 1.0) generator.prepare() completed_steps = 0 steps_to_do = generator.size self.o.on_configure(self.context, completed_steps, steps_to_do, {}, generator, "") assert self.o.generator is generator assert self.o.loaded_up_to == completed_steps assert self.o.scan_up_to == completed_steps + steps_to_do buffer_instance.configure.assert_called_once() self.gate_part.enable_set.assert_not_called() buffer_instance.run.assert_not_called() # The SRGate should only be enabled by on_run() here. self.o.on_pre_run(self.context) self.o.on_run(self.context) self.gate_part.enable_set.assert_called_once() buffer_instance.run.assert_called_once()
def test_from_dict(self, gen_mock, ex_mock, mutator_mock): self.g = CompoundGenerator([self.l2, self.l1], [self.e1], [self.m1]) gen_mock.from_dict.side_effect = [self.l2, self.l1] mutator_mock.from_dict.return_value = self.m1 ex_mock.from_dict.return_value = self.e1 _dict = dict() _dict['generators'] = [self.l1_dict, self.l2_dict] _dict['excluders'] = [self.e1_dict] _dict['mutators'] = [self.m1_dict] _dict['duration'] = 12 _dict['continuous'] = False units_dict = dict() units_dict['x'] = 'mm' units_dict['y'] = 'mm' gen = CompoundGenerator.from_dict(_dict) self.assertEqual(gen.generators[0], self.l2) self.assertEqual(gen.generators[1], self.l1) self.assertEqual(gen.mutators[0], self.m1) self.assertEqual(gen.excluders[0], self.e1) self.assertEqual(gen.duration, 12) self.assertEqual(gen.continuous, False)
def test_configure_motion_controller_trigger(self): xs = LineGenerator("x", "mm", 0.0, 0.3, 4, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) generator = CompoundGenerator([ys, xs], [], [], 1.0) self.set_motor_attributes() self.set_attributes(self.child, rowTrigger="Motion Controller") self.set_attributes(self.child_seq1, bita="TTLIN1.VAL") self.set_attributes(self.child_seq2, bita="TTLIN1.VAL") axes_to_move = ["x", "y"] seq_rows = self.get_sequencer_rows(generator, axes_to_move) # Triggers B0 = Trigger.BITA_0 B1 = Trigger.BITA_1 IT = Trigger.IMMEDIATE # Half a frame hf = 62500000 expected = SequencerRows() expected.add_seq_entry(count=1, trigger=B1, position=0, half_duration=hf, live=1, dead=0) expected.add_seq_entry(3, IT, 0, hf, 1, 0) expected.add_seq_entry(1, B0, 0, MIN_PULSE, 0, 1) expected.add_seq_entry(1, B1, 0, hf, 1, 0) expected.add_seq_entry(3, IT, 0, hf, 1, 0) expected.add_seq_entry(1, IT, 0, MIN_PULSE, 0, 1) expected.add_seq_entry(0, IT, 0, MIN_PULSE, 0, 0) assert seq_rows.as_tuples() == expected.as_tuples()
def test_alternating_three_axis(self): z = LineGenerator("z", "mm", 1, 2, 2) y = LineGenerator("y", "mm", 1, 2, 2, True) x = LineGenerator("x", "mm", 3, 1, 3, True) g = CompoundGenerator([z, y, x], [], []) g.prepare() expected = [] expected_idx = [] expected_lower = [] expected_upper = [] y_f = True x_f = True for z in range_(1, 3): y_r = range_(1, 3) if y_f else range_(2, 0, -1) y_f = not y_f for y in y_r: x_r = range_(3, 0, -1) if x_f else range_(1, 4) for x in x_r: expected.append({ "x": float(x), "y": float(y), "z": float(z) }) expected_idx.append([z - 1, y - 1, 3 - x]) expected_lower.append(x + (0.5 if x_f else -0.5)) expected_upper.append(x + (-0.5 if x_f else 0.5)) x_f = not x_f points = list(g.iterator()) self.assertEqual(expected, [p.positions for p in points]) self.assertEqual(expected_idx, [p.indexes for p in points]) self.assertEqual(expected_lower, [p.lower["x"] for p in points]) self.assertEqual(expected_upper, [p.upper["x"] for p in points])
def test_configure_long_pcomp_row_trigger(self): # Skip on GitHub Actions and GitLab CI if "CI" in os.environ: pytest.skip("performance test only") self.set_motor_attributes( 0, 0, "mm", x_velocity=300, y_velocity=300, x_acceleration=30, y_acceleration=30, ) x_steps, y_steps = 4000, 1000 xs = LineGenerator("x", "mm", 0.0, 10, x_steps, alternate=True) ys = LineGenerator("y", "mm", 0.0, 8, y_steps) generator = CompoundGenerator([ys, xs], [], [], 0.005) generator.prepare() completed_steps = 0 steps_to_do = x_steps * y_steps self.set_motor_attributes() axes_to_move = ["x", "y"] start = datetime.now() self.o.on_configure(self.context, completed_steps, steps_to_do, {}, generator, axes_to_move) elapsed = datetime.now() - start assert elapsed.total_seconds() < 3.0
def test_inner_alternating(self): z = LineGenerator("z", "mm", 1, 5, 5) y = LineGenerator("y", "mm", 1, 5, 5, alternate=True) x = LineGenerator("x", "mm", 1, 5, 5, alternate=True) r1 = CircularROI([3, 3], 1.5) e1 = ROIExcluder([r1], ["x", "y"]) g = CompoundGenerator([z, y, x], [e1], []) g.prepare() expected = [] xy_expected = [] x_f = True for y in range_(1, 6): for x in (range_(1, 6) if x_f else range(5, 0, -1)): if (x - 3)**2 + (y - 3)**2 <= 1.5**2: xy_expected.append((x, y)) x_f = not x_f xy_f = True for z in range_(1, 6): for (x, y) in (xy_expected if xy_f else xy_expected[::-1]): expected.append({"x": float(x), "y": float(y), "z": float(z)}) xy_f = not xy_f expected_idx = [] xy_f = True for z in range_(0, 5): xy_idx = range_(len(xy_expected)) if xy_f \ else range_(len(xy_expected)-1, -1, -1) expected_idx += [[z, xy] for xy in xy_idx] xy_f = not xy_f points = list(g.iterator()) self.assertEqual(expected, [p.positions for p in points]) self.assertEqual(expected_idx, [p.indexes for p in points])
def test_configure(self): xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) generator = CompoundGenerator([ys, xs], [], []) generator.prepare() completed_steps = 2 steps_to_do = 4 self.o.done_when_reaches = 30 self.o.on_configure(self.context, completed_steps, steps_to_do, generator) expected_xml = """<?xml version="1.0" ?> <pos_layout> <dimensions> <dimension name="d0" /> <dimension name="d1" /> </dimensions> <positions> <position d0="0" d1="2" /> <position d0="1" d1="2" /> <position d0="1" d1="1" /> <position d0="1" d1="0" /> </positions> </pos_layout>""".replace("\n", "") # Wait for the start_future so the post gets through to our child # even on non-cothread systems self.o.start_future.result(timeout=1) assert self.child.handled_requests.mock_calls == [ call.post("delete"), call.put("enableCallbacks", True), call.put("idStart", 31), call.put("xml", expected_xml), call.post("start"), ] assert self.o.done_when_reaches == 34
def test_alternating_regions_2(self): z = LineGenerator("z", "mm", 1, 5, 5) y = LineGenerator("y", "mm", 1, 5, 5, True) x = LineGenerator("x", "mm", 1, 5, 5, True) r1 = CircularROI([3, 3], 1.5) e1 = ROIExcluder([r1], ["x", "y"]) e2 = ROIExcluder([r1], ["z", "y"]) g = CompoundGenerator([z, y, x], [e1, e2], []) #20 points g.prepare() actual = [p.positions for p in list(g.iterator())] expected = [] yf = True xf = True for z in range_(1, 6): yr = range_(1, 6) if yf else range_(5, 0, -1) yf = not yf for y in yr: xr = range_(1, 6) if xf else range_(5, 0, -1) xf = not xf for x in xr: expected.append({ "x": float(x), "y": float(y), "z": float(z) }) expected = [ p for p in expected if (p["x"] - 3)**2 + (p["y"] - 3)**2 <= 1.5**2 and (p["z"] - 3)**2 + (p["y"] - 3)**2 <= 1.5**2 ] self.assertEqual(expected, actual)
def test_report_configuration(self): p = DSGather("DS") self.o.add_part(p) b = self.process.block_view("P") pos_table = DatasetPositionsTable( name=["INENC1.VAL", "INENC2.VAL", "INENC3.VAL", "INENC4.VAL"], value=[0] * 4, offset=[0] * 4, scale=[0] * 4, units=[""] * 4, capture=["Diff", "No", "Min Max Mean", "Diff"], datasetName=["", "x1", "x2", "x3"], datasetType=["monitor", "monitor", "position", "monitor"], ) b.positions.put_value(pos_table) b.configure(generator=CompoundGenerator([StaticPointGenerator(1)], [], [])) dataset_infos = p.part_info["busses"] assert len(dataset_infos) == 4 assert dataset_infos[0].name == "x2.min" assert dataset_infos[0].type == DatasetType.POSITION_MIN assert dataset_infos[0].attr == "INENC3.VAL.Min" assert dataset_infos[1].name == "x2.max" assert dataset_infos[1].type == DatasetType.POSITION_MAX assert dataset_infos[1].attr == "INENC3.VAL.Max" assert dataset_infos[2].name == "x2.value" assert dataset_infos[2].type == DatasetType.POSITION_VALUE assert dataset_infos[2].attr == "INENC3.VAL.Mean" assert dataset_infos[3].name == "x3.data" assert dataset_infos[3].type == DatasetType.MONITOR assert dataset_infos[3].attr == "INENC4.VAL.Diff"
def test_line_spiral(self): expected = [ { 'y': -0.3211855677650875, 'x': 0.23663214944574582, 'z': 0.0 }, { 'y': -0.25037538922751695, 'x': -0.6440318266552169, 'z': 0.0 }, { 'y': 0.6946549630820702, 'x': -0.5596688286164636, 'z': 0.0 }, { 'y': 0.6946549630820702, 'x': -0.5596688286164636, 'z': 2.0 }, { 'y': -0.25037538922751695, 'x': -0.6440318266552169, 'z': 2.0 }, { 'y': -0.3211855677650875, 'x': 0.23663214944574582, 'z': 2.0 }, { 'y': -0.3211855677650875, 'x': 0.23663214944574582, 'z': 4.0 }, { 'y': -0.25037538922751695, 'x': -0.6440318266552169, 'z': 4.0 }, { 'y': 0.6946549630820702, 'x': -0.5596688286164636, 'z': 4.0 }, ] z = LineGenerator("z", "mm", 0.0, 4.0, 3) spiral = SpiralGenerator(['x', 'y'], "mm", [0.0, 0.0], 0.8, alternate=True) g = CompoundGenerator([z, spiral], [], []) g.prepare() self.assertEqual(g.axes, ["z", "x", "y"]) points = list(g.iterator()) self.assertEqual(len(expected), len(points)) for i, p in enumerate(points): self.assertEqual(expected[i], p.positions)