class JLineGenerator2D(JavaIteratorWrapper): """ Create a 2D LineGenerator and wrap the points into java Point objects """ def __init__(self, names, units, start, stop, num_points, alternate_direction=False): super(JLineGenerator2D, self).__init__() start = start.tolist() # Convert from array to list stop = stop.tolist() self.names = names self.generator = LineGenerator(names, units, start, stop, num_points, alternate_direction) logging.debug(self.generator.to_dict()) def _iterator(self): for point in self.generator.iterator(): index = point.indexes[0] x_name = self.names[0] y_name = self.names[1] x_position = point.positions[x_name] y_position = point.positions[y_name] java_point = Point(x_name, index, x_position, y_name, index, y_position, False) # Set is2D=False yield java_point
def test_triple_alternating_linked_gen(self): tg = LineGenerator("t", "mm", 1, 5, 5) zg = LineGenerator("z", "mm", -1, 3, 5, True) yg = LineGenerator("y", "mm", 0, 4, 5, True) xg = LineGenerator("x", "mm", 0, 4, 5, True) r1 = RectangularROI([-1, -1], 5.5, 3.5) r2 = RectangularROI([1, 0], 2.5, 2.5) e1 = ROIExcluder([r1], ["z", "y"]) e2 = ROIExcluder([r2], ["x", "y"]) g = CompoundGenerator([tg, zg, yg, xg], [e1, e2], []) g.prepare() zf = True yf = True xf = True expected = [] for t in range_(1, 6): zr = range_(-1, 4) if zf else range_(3, -2, -1) zf = not zf for z in zr: yr = range_(0, 5) if yf else range_(4, -1, -1) yf = not yf for y in yr: xr = range_(0, 5) if xf else range_(4, -1, -1) xf = not xf for x in xr: if z >= -1 and z < 4.5 and y >= 0 and y < 2.5 \ and x >= 1 and x < 3.5: expected.append({"x":float(x), "y":float(y), "z":float(z), "t":float(t)}) actual = [p.positions for p in g.iterator()] self.assertEqual(len(expected), len(actual)) for e, a in zip(expected, actual): self.assertEqual(e, a)
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_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_validate(self): line1 = LineGenerator('y', 'mm', 0, 2, 3) line2 = LineGenerator('x', 'mm', 0, 2, 2) compound = CompoundGenerator([line1, line2], [], []) actual = self.b.validate(generator=compound, axesToMove=['x']) self.assertEqual(actual["generator"], compound) self.assertEqual(actual["axesToMove"], ('x', ))
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_array_positions_from_line_non_matching_bounds(self): genone = LineGenerator("x", "mm", 1.0, 9.0, 5) gentwo = LineGenerator("x", "mm", 20, 24, 5) g = ConcatGenerator([genone, gentwo]) g.prepare_positions() with self.assertRaises(AssertionError): g.prepare_bounds()
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_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_with_breakpoints(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], [], [], 0.1) generator.prepare() completed_steps = 0 steps_to_do = 3 info = ExposureDeadtimeInfo(0.01, 1000, 0.0) part_info = dict(anyname=[info]) self.set_attributes(self.child, triggerMode="Internal") self.o.on_configure( self.context, completed_steps, steps_to_do, part_info, generator, fileDir="/tmp", breakpoints=[3, 3], exposure=info.calculate_exposure(generator.duration), ) assert self.child.handled_requests.mock_calls == [ call.put("arrayCallbacks", True), call.put("arrayCounter", 0), call.put("exposure", 0.1 - 0.01 - 0.0001), call.put("imageMode", "Multiple"), call.put("numImages", 3), call.put("acquirePeriod", 0.1 - 0.0001), ] assert not self.o.is_hardware_triggered
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.1) params.generator.prepare() self.o.validate(ANY, ANY, params)
def test_minimum_profile(self): # tests that a turnaround that is >= minturnaround # is reduced to a start and end point only # this supports keeping the turnaround really short where # the motors are fast e.g. j15 axes_to_scan = ["x", "y"] duration = 0.005 self.set_motor_attributes( 0.0, 0.0, "mm", x_acceleration=100.0, x_velocity=2.0, y_acceleration=100.0, y_velocity=2.0, ) steps_to_do = 1 * len(axes_to_scan) xs = LineGenerator("x", "mm", 0, 0.0001, 2) ys = LineGenerator("y", "mm", 0, 0, 2) generator = CompoundGenerator([ys, xs], [], [], duration, continuous=False) generator.prepare() m = [MinTurnaroundInfo(0.002, 0.002)] self.o.on_configure(self.context, 0, steps_to_do, {"part": m}, generator, axes_to_scan) action, func, args = self.child.handled_requests.mock_calls[-1] assert args["a"] == pytest.approx( [0, 0, 0, 0.0001, 0.0001, 0.0001, 0.0001]) assert args["b"] == pytest.approx([0, 0, 0, 0, 0, 0, 0]) assert args["timeArray"] == pytest.approx( [2000, 2500, 2500, 2000, 2500, 2500, 2000]) # now make the acceleration slower so that the turnaround takes # longer than the minimum interval self.set_motor_attributes( 0.0, 0.0, "mm", x_acceleration=10.0, x_velocity=2.0, y_acceleration=100.0, y_velocity=2.0, ) self.o.on_configure(self.context, 0, steps_to_do, {"part": m}, generator, axes_to_scan) # this generates one mid point between the 1st upper and 2nd lower # bounds. Note that the point is not exactly central due to time # quantization action, func, args = self.child.handled_requests.mock_calls[-1] assert args["a"] == pytest.approx( [0, 0, 0, 5.0e-05, 0.0001, 0.0001, 0.0001, 0.0001]) assert args["b"] == pytest.approx([0, 0, 0, 0, 0, 0, 0, 0]) assert args["timeArray"] == pytest.approx( [2000, 2500, 2500, 6000, 6000, 2500, 2500, 2000])
def test_post_run_armed_with_hardware_trigger_and_breakpoints(self): xs = LineGenerator("x", "mm", 0.0, 0.5, 100, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 5) generator = CompoundGenerator([ys, xs], [], [], 0.1) generator.prepare() info = ExposureDeadtimeInfo(0.01, 1000, 0.0) part_info = dict(anyname=[info]) breakpoints = [100, 400] # This would have been done by initial configure self.o.is_hardware_triggered = True self.o.done_when_reaches = 100 self.o.on_post_run_armed(self.context, 100, 400, part_info, generator, breakpoints) assert self.child.handled_requests.mock_calls == [ call.put("arrayCallbacks", True), call.put("arrayCounter", 100), call.put("imageMode", "Multiple"), call.put("numImages", 400), call.put("acquirePeriod", 0.1 - 0.0001), call.post("start"), call.when_value_matches("acquiring", True, None), ] assert self.o.done_when_reaches == 500
def long_configure(self, row_gate=False): # test 4,000,000 points configure - used to check performance if row_gate: infos = [ MotionTriggerInfo(MotionTrigger.ROW_GATE), ] else: infos = None self.set_motor_attributes( 0, 0, "mm", x_velocity=300, y_velocity=300, x_acceleration=30, y_acceleration=30, ) axes_to_scan = ["x", "y"] x_steps, y_steps = 4000, 1000 steps_to_do = x_steps * y_steps 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.0001) generator.prepare() start = datetime.now() self.o.on_configure(self.context, 0, steps_to_do, {"part": infos}, generator, axes_to_scan) elapsed = datetime.now() - start # todo goal was sub 1 second but we achieved sub 3 secs assert elapsed.total_seconds() < 3.5
def test_configure_software_trigger_succeeds(self): xs = LineGenerator("x", "mm", 0.0, 0.5, 3, alternate=True) ys = LineGenerator("y", "mm", 0.0, 0.1, 2) duration = 0.1 generator = CompoundGenerator([ys, xs], [], [], duration) generator.prepare() completed_steps = 0 steps_to_do = 6 # We wait to be armed, so set this here self.set_attributes(self.child, acquiring=True, triggerOffCondition="Always On") self.o.on_configure(self.context, completed_steps, steps_to_do, {}, generator, fileDir="/tmp") # We expect only these calls (no arming in software trigger mode) assert self.child.handled_requests.mock_calls == [ call.put("arrayCallbacks", True), call.put("arrayCounter", 0), call.put("imageMode", "Multiple"), call.put("numImages", 6), call.put("postCount", 1000), ]
def test_configure_with_hardware_start_trigger_succeeds(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], [], [], 0.1) generator.prepare() completed_steps = 0 steps_to_do = 6 # We are not gated self.o.gated_trigger = False # We want to be armed and in a hardware trigger mode self.set_attributes(self.child, acquiring=True, triggerMode="Rising Edge") self.o.on_configure(self.context, completed_steps, steps_to_do, {}, 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", 6), call.put("postCount", 999), call.post("start"), call.when_value_matches("acquiring", True, None), ]
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 grid_check(): x = LineGenerator("x", "mm", 0.0, 4.0, 5, alternate=True) y = LineGenerator("y", "mm", 0.0, 3.0, 4) gen = CompoundGenerator([y, x], [], []) plot_generator(gen)
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_validate(self): line1 = LineGenerator('y', 'mm', 0, 2, 3) line2 = LineGenerator('x', 'mm', 0, 2, 2) compound = CompoundGenerator([line1, line2], [], []) actual = self.b.validate(generator=compound, axesToMove=['x']) assert actual["generator"].to_dict() == compound.to_dict() assert actual["axesToMove"] == ['x']
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 prepare_half_run(self, duration=0.01, exception=0): line1 = LineGenerator('y', 'mm', 0, 2, 3) line2 = LineGenerator('x', 'mm', 0, 2, 2) compound = CompoundGenerator([line1, line2], [], [], duration) self.b.configure(generator=compound, axesToMove=['x'], exceptionStep=exception)
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_get_point_large_scan(self): s = SpiralGenerator(["x", "y"], "mm", [0, 0], 6, 1) #114 points z = LineGenerator("z", "mm", 0, 1, 100) w = LineGenerator("w", "mm", 0, 1, 5) t = LineGenerator("t", "mm", 0, 1, 5) rad1 = 2.8 r1 = CircularROI([1., 1.], rad1) e1 = ROIExcluder([r1], ["x", "y"]) rad2 = 2 r2 = CircularROI([0.5, 0.5], rad2) e2 = ROIExcluder([r2], ["y", "z"]) rad3 = 0.5 r3 = CircularROI([0.5, 0.5], rad3) e3 = ROIExcluder([r3], ["w", "t"]) g = CompoundGenerator([t, w, z, s], [e1, e2, e3], []) g.prepare() spiral = [(x, y) for (x, y) in zip(s.positions["x"], s.positions["y"])] zwt = [(z/99., w/4., t/4.) for t in range_(0, 5) for w in range_(0, 5) for z in range_(0, 100)] expected = [(x, y, z, w, t) for (z, w, t) in zwt for (x, y) in spiral] expected = [{"x":x, "y":y, "z":z, "w":w, "t":t} for (x,y,z,w,t) in expected if (x-1)*(x-1) + (y-1)*(y-1) <= rad1*rad1 and (y-0.5)*(y-0.5) + (z-0.5)*(z-0.5) <= rad2*rad2 and (w-0.5)*(w-0.5) + (t-0.5)*(t-0.5) <= rad3*rad3] points = [g.get_point(n) for n in range_(0, g.size)] pos = [p.positions for p in points] # assertEqual on a sequence of dicts is *really* slow for (e, p) in zip(expected, pos): self.assertEquals(e.keys(), p.keys()) for k in e.keys(): self.assertAlmostEqual(e[k], p[k])
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_three_dim_middle_alternates(self): tg = LineGenerator("t", "mm", 1, 5, 5) zg = LineGenerator("z", "mm", -1, 3, 5, True) spiral = SpiralGenerator(["s1", "s2"], "mm", [1, 1], 2, 1, True) yg = LineGenerator("y", "mm", 0, 4, 5) xg = LineGenerator("x", "mm", 0, 4, 5) r1 = CircularROI([0, 0], 1) e1 = ROIExcluder([r1], ["s1", "z"]) e2 = ROIExcluder([r1], ["y", "x"]) g = CompoundGenerator([tg, zg, spiral, yg, xg], [e2, e1], []) g.prepare() it = 0 iz = 0 iy = 0 ix = 0 tzs = [] points = [] for t in range_(1, 6): for z in (range_(-1, 4) if it % 2 == 0 else range_(3, -2, -1)): s1p = spiral.positions["s1"] if iz % 2 == 0 else spiral.positions["s1"][::-1] s2p = spiral.positions["s2"] if iz % 2 == 0 else spiral.positions["s2"][::-1] points += [(x, y, s1, s2, z, t) for (s1, s2) in zip(s1p, s2p) for y in range(0, 5) for x in range(0, 5) if s1*s1 + z*z <= 1 and y*y + x*x <= 1] iz += 1 it += 1 expected = [{"x":float(x), "y":float(y), "s1":s1, "s2":s2, "z":float(z), "t":float(t)} for (x, y, s1, s2, z, t) in points] actual = [p.positions for p in list(g.iterator())] for e, a in zip(expected, actual): self.assertEqual(e, a)
def test_init(self): genone = LineGenerator("x", "mm", 1.0, 9.0, 5) gentwo = LineGenerator("x", "mm", 13, 20, 5) g = ConcatGenerator([genone, gentwo]) self.assertEqual(["x"], g.axes) self.assertEqual(dict(x="mm"), g.axis_units()) self.assertEqual(10, g.size)
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_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_alternating_complex(self): tg = LineGenerator("t", "mm", 1, 5, 5) zg = LineGenerator("z", "mm", 1, 5, 5, True) yg = LineGenerator("y", "mm", 1, 5, 5, True) xg = LineGenerator("x", "mm", 1, 5, 5, True) r1 = RectangularROI([3., 3.], 2., 2.) e1 = ROIExcluder([r1], ["y", "x"]) e2 = ROIExcluder([r1], ["z", "y"]) g = CompoundGenerator([tg, zg, yg, xg], [e1, e2], []) g.debug = True g.prepare() points = [p.positions for p in list(g.iterator())] expected = [] zf, yf, xf = True, True, True for t in range_(1, 6): r_1 = range_(1,6) if zf else range_(5, 0, -1) zf = not zf for z in r_1: r_2 = range_(1,6) if yf else range_(5, 0, -1) yf = not yf for y in r_2: r_3 = range_(1, 6) if xf else range_(5, 0, -1) xf = not xf for x in r_3: expected.append( {"t":float(t), "z":float(z), "y":float(y), "x":float(x)}) expected = [p for p in expected if (p["y"] >= 3 and p["y"] <= 5 and p["x"] >= 3 and p["x"] <= 5) and (p["z"] >= 3 and p["z"] <= 5 and p["y"] >= 3 and p["y"] <= 5)] self.assertEqual(expected, points)
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 __init__(self, names, units, start, stop, num_points, alternate_direction=False): super(JLineGenerator2D, self).__init__() start = start.tolist() # Convert from array to list stop = stop.tolist() self.names = names self.generator = LineGenerator(names, units, start, stop, num_points, alternate_direction) logging.debug(self.generator.to_dict())
class JLineGenerator1D(JavaIteratorWrapper): """ Create a 1D LineGenerator and wrap the points into java Scalar objects """ def __init__(self, name, units, start, stop, num_points, alternate_direction=False): super(JLineGenerator1D, self).__init__() self.name = name self.generator = LineGenerator(name, units, start, stop, num_points, alternate_direction) logging.debug(self.generator.to_dict()) def _iterator(self): for point in self.generator.iterator(): index = point.indexes[0] position = point.positions[self.name] java_point = Scalar(self.name, index, position) yield java_point
class LineGeneratorTest(ScanPointGeneratorTest): def setUp(self): self.g = LineGenerator("x", "mm", 1, 0.1, 5) def test_init(self): self.assertEqual(self.g.position_units, dict(x="mm")) self.assertEqual(self.g.index_dims, [5]) self.assertEqual(self.g.index_names, ["x"]) def test_iterator(self): positions = [1.0, 1.1, 1.2, 1.3, 1.4] lower = [0.95, 1.05, 1.15, 1.25, 1.35] upper = [1.05, 1.15, 1.25, 1.35, 1.45] indexes = [0, 1, 2, 3, 4] for i, p in enumerate(self.g.iterator()): self.assertEqual(p.positions, dict(x=positions[i])) self.assertEqual(p.lower, dict(x=lower[i])) self.assertEqual(p.upper, dict(x=upper[i])) self.assertEqual(p.indexes, [indexes[i]]) self.assertEqual(i, 4)
def setUp(self): self.g = LineGenerator("x", "mm", 1, 0.1, 5)
def __init__(self, name, units, start, stop, num_points, alternate_direction=False): super(JLineGenerator1D, self).__init__() self.name = name self.generator = LineGenerator(name, units, start, stop, num_points, alternate_direction) logging.debug(self.generator.to_dict())