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_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_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_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_double_spiral_scan(self): line1 = LineGenerator(["l1"], "mm", -1, 2, 5) spiral_s = SpiralGenerator(["s1", "s2"], "mm", [1, 2], 5, 2.5, True) spiral_t = SpiralGenerator(["t1", "t2"], "mm", [0, 0], 5, 2.5, True) line2 = LineGenerator(["l2"], "mm", -1, 2, 5, True) r = CircularROI([0, 0], 1) e1 = ROIExcluder([r], ["s1", "l1"]) e2 = ROIExcluder([r], ["l2", "t1"]) g = CompoundGenerator([line1, spiral_s, spiral_t, line2], [e1, e2], []) g.prepare() points = [] l1s = [] tl2 = [] s_f = True for l1 in line1.positions["l1"]: sp = zip(spiral_s.positions['s1'], spiral_s.positions['s2']) sp = sp if s_f else list(sp)[::-1] s_f = not s_f l1s += [(s1, s2, l1) for (s1, s2) in sp] l2_f = True for (t1, t2) in zip(spiral_t.positions['t1'], spiral_t.positions['t2']): l2p = line2.positions['l2'] if l2_f else line2.positions['l2'][::-1] l2pu = line2.bounds['l2'][1:len(line2.positions['l2'])+1] l2pl = line2.bounds['l2'][0:len(line2.positions['l2'])] if not l2_f: l2pu, l2pl = l2pl[::-1], l2pu[::-1] l2_f = not l2_f tl2 += [(l2, l2u, l2l, t1, t2) for (l2, l2u, l2l) in zip(l2p, l2pu, l2pl) if l2*l2 + t1*t1 <= 1] t_f = True for (s1, s2, l1) in l1s: inner = tl2 if t_f else tl2[::-1] t_f = not t_f points += [(l2, l2u, l2l, t1, t2, s1, s2, l1) for (l2, l2u, l2l, t1, t2) in inner if s1*s1 + l1*l1 <= 1] l1s_original = l1s l1s = [(s1, s2, l1) for (s1, s2, l1) in l1s if s1*s1 + l1*l1 <= 1] expected = [{"l2":l2, "t1":t1, "t2":t2, "s1":s1, "s2":s2, "l1":l1} for (l2, l2u, l2l, t1, t2, s1, s2, l1) in points] expected_idx = [] t_f = (l1s_original.index(l1s[0])) % 2 == 0 # t_f is False for d1 in range_(len(l1s)): expected_idx += [[d1, d2] for d2 in (range_(len(tl2)) if t_f else range_(len(tl2) - 1, -1, -1))] t_f = not t_f expected_l2_lower = [l2l for (l2, l2u, l2l, t1, t2, s1, s2, l1) in points] expected_l2_upper = [l2u for (l2, l2u, l2l, t1, t2, s1, s2, l1) in points] gpoints = list(g.iterator()) self.assertEqual(expected, [p.positions for p in gpoints]) self.assertEqual(expected_idx, [p.indexes for p in gpoints]) self.assertEqual(expected_l2_lower, [p.lower["l2"] for p in gpoints]) self.assertEqual(expected_l2_upper, [p.upper["l2"] for p in gpoints])
def test_simple_mask(self): x = LineGenerator("x", "mm", -1.0, 1.0, 5, False) y = LineGenerator("y", "mm", -1.0, 1.0, 5, False) r = CircularROI([0, 0], 1) e = ROIExcluder([r], ["x", "y"]) g = CompoundGenerator([y, x], [e], []) g.prepare() 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[0].mask.tolist())
def test_iterator(self): x = LineGenerator("x", "mm", 1.0, 2.0, 5, False) y = LineGenerator("y", "mm", 1.0, 2.0, 5, False) g = CompoundGenerator([y, x], [], []) g.prepare() points = list(g.iterator()) expected_pos = [{"x":x/4., "y":y/4.} for y in range_(4, 9) for x in range_(4, 9)] self.assertEqual(expected_pos, [p.positions for p in points]) expected_indexes = [[y, x] for y in range_(0, 5) for x in range_(0, 5)] self.assertEqual(expected_indexes, [p.indexes for p in points])
def iterator(self): for i in range_(self.num): point = Point() for axis_index in range_(self.num_axes): point.positions[self.name[axis_index]] = self._calc(i, axis_index) point.lower[self.name[axis_index]] = self._calc(i - 0.5, axis_index) point.upper[self.name[axis_index]] = self._calc(i + 0.5, axis_index) point.indexes = [i] yield point
def test_double_mask(self): x = LineGenerator("x", "mm", -1.0, 1.0, 5, False) y = LineGenerator("y", "mm", -1.0, 1.0, 5, False) z = LineGenerator("z", "mm", -1.0, 1.0, 5, False) r = CircularROI([0.1, 0.2], 1) e1 = ROIExcluder([r], ["x", "y"]) e2 = ROIExcluder([r], ["y", "z"]) g = CompoundGenerator([z, y, x], [e1, e2], []) 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 - 0.1)**2 + (y - 0.2)**2 <= 1 for (x, y, z) in p] m2 = [(y - 0.1)**2 + (z - 0.2)**2 <= 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[0].mask.tolist())
def iterator(self): for i in range_(self.num): point = Point() for axis_index in range_(self.num_axes): axis_name = self.name[axis_index] start = self.start[axis_index] step = self.step[axis_index] point.positions[axis_name] = start + i * step point.lower[axis_name] = start + (i - 0.5) * step point.upper[axis_name] = start + (i + 0.5) * step point.indexes = [i] yield point
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 produce_points(self): self.points = {} self.points_lower = {} self.points_upper = {} for axis in range_(self.num_axes): axis_name = self.name[axis] start = self.start[axis] stop = self.stop[axis] d = stop - start if self.num == 1: self.points[axis_name] = np.array([start]) self.points_upper[axis_name] = np.array([start + 0.5 * d]) self.points_lower[axis_name] = np.array([start - 0.5 * d]) else: n = self.num - 1. s = d / n upper_start = start + 0.5 * d / n upper_stop = stop + 0.5 * d / n lower_start = start - 0.5 * d / n lower_stop = stop - 0.5 * d / n self.points[axis_name] = np.linspace( float(start), float(stop), self.num) self.points_upper[axis_name] = np.linspace( float(upper_start), float(upper_stop), self.num) self.points_lower[axis_name] = np.linspace( float(lower_start), float(lower_stop), self.num)
def test_simple_mask_alternating(self): x = LineGenerator("x", "mm", -1.0, 1.0, 5, alternate=True) y = LineGenerator("y", "mm", -1.0, 1.0, 5, alternate=True) r = CircularROI([0.5, 0], 1) e = ROIExcluder([r], ["x", "y"]) g = CompoundGenerator([y, x], [e], []) g.prepare() reverse = False p = [] for y in range_(-2, 3): if reverse: p += [(x / 2., y / 2.) for x in range_(2, -3, -1)] else: p += [(x / 2., y / 2.) for x in range_(-2, 3)] reverse = not reverse expected_mask = [(x - 0.5)**2 + y**2 <= 1**2 for (x, y) in p] self.assertEqual(expected_mask, g.dimensions[0].mask.tolist())
def point_gen(): for n in range_(10): p = Point() p.indexes = [n] p.positions = {"x": n / 10.} p.lower = {"x": (n - 0.5) / 10.} p.upper = {"x": (n + 0.5) / 10.} yield p
def __init__(self, name, units, start, stop, num, alternate_direction=False): """ Args: name (str/list(str)): The scannable name(s) E.g. "x" or ["x", "y"] units (str): The scannable units. E.g. "mm" start (float/list(float)): The first position to be generated. e.g. 1.0 or [1.0, 2.0] stop (float or list(float)): The first position to be generated. e.g. 5.0 or [5.0, 10.0] num (int): The number of points to generate. E.g. 5 alternate_direction(bool): Specifier to reverse direction if generator is nested """ self.name = to_list(name) self.start = to_list(start) self.stop = to_list(stop) self.alternate_direction = alternate_direction if len(self.name) != len(set(self.name)): raise ValueError("Axis names cannot be duplicated; given %s" % name) if len(self.name) != len(self.start) or \ len(self.name) != len(self.stop): raise ValueError("Dimensions of name, start and stop do not match") self.num = num self.num_axes = len(self.name) self.step = [] if self.num < 2: self.step = [0] * len(self.start) else: for axis in range_(len(self.start)): self.step.append( (self.stop[axis] - self.start[axis]) / (self.num - 1)) self.position_units = dict() for dimension in self.name: self.position_units[dimension] = units self.index_dims = [self.num] if len(self.name) > 1: gen_name = "Line" for axis_name in self.name[::-1]: gen_name = axis_name + "_" + gen_name self.index_names = [gen_name] else: self.index_names = self.name self.axes = self.name # For GDA
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_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_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 iterator(self): for i in range_(self.num): p = Point() p.positions[self.names[0]], p.positions[self.names[1]] = self._calc(i) p.lower[self.names[0]], p.lower[self.names[1]] = self._calc(i - 0.5) p.upper[self.names[0]], p.upper[self.names[1]] = self._calc(i + 0.5) p.indexes = [i] yield p
def __init__(self, name, units, start, stop, num, alternate_direction=False): """ Args: name (str/list(str)): The scannable name(s) E.g. "x" or ["x", "y"] units (str): The scannable units. E.g. "mm" start (float/list(float)): The first position to be generated. e.g. 1.0 or [1.0, 2.0] stop (float or list(float)): The first position to be generated. e.g. 5.0 or [5.0, 10.0] num (int): The number of points to generate. E.g. 5 alternate_direction(bool): Specifier to reverse direction if generator is nested """ self.name = to_list(name) self.start = to_list(start) self.stop = to_list(stop) self.alternate_direction = alternate_direction self.points = None self.points_lower = None self.points_upper = None self.units = units if len(self.name) != len(set(self.name)): raise ValueError("Axis names cannot be duplicated; given %s" % name) if len(self.name) != len(self.start) or \ len(self.name) != len(self.stop): raise ValueError( "Dimensions of name, start and stop do not match") self.num = num self.num_axes = len(self.name) self.step = [] if self.num < 2: self.step = [0]*len(self.start) else: for axis in range_(len(self.start)): self.step.append( (self.stop[axis] - self.start[axis])/(self.num - 1)) self.position_units = dict() for dimension in self.name: self.position_units[dimension] = units self.index_dims = [self.num] if len(self.name) > 1: gen_name = "Line" for axis_name in self.name[::-1]: gen_name = axis_name + "_" + gen_name self.index_names = [gen_name] else: self.index_names = self.name self.axes = self.name # For GDA
def iterator(self): """ Iterator yielding generator positions at each scan point Yields: Point: The next point """ if not self._prepared: raise ValueError("CompoundGenerator has not been prepared") it = (self.get_point(n) for n in range_(self.size)) for p in it: yield p
def test_alternating_with_region(self): 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], ["y", "x"]) g = CompoundGenerator([y, x], [e1], []) g.prepare() expected = [] x_f = True for y in range_(1, 6): r = range_(1, 6) if x_f else range(5, 0, -1) x_f = not x_f for x in r: expected.append({"y":float(y), "x":float(x)}) expected = [p for p in expected if ((p["x"]-3)**2 + (p["y"]-3)**2 <= 1.5**2)] expected_idx = [[xy] for xy in range_(len(expected))] 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((len(expected),), g.shape)
def test_get_point(self): x = LineGenerator("x", "mm", -1., 1, 5, False) y = LineGenerator("y", "mm", -1., 1, 5, False) z = LineGenerator("z", "mm", -1., 1, 5, False) r = CircularROI([0., 0.], 1) e = ROIExcluder([r], ["x", "y"]) g = CompoundGenerator([z, y, x], [e], []) g.prepare() points = [g.get_point(n) for n in range(0, g.size)] pos = [p.positions for p in points] idx = [p.indexes for p in points] xy_expected = [(x/2., y/2.) for y in range_(-2, 3) for x in range_(-2, 3)] xy_expected = [(x, y) for (x, y) in xy_expected if x*x + y*y <= 1] expected = [{"x":x, "y":y, "z":z/2.} for z in range_(-2, 3) for (x, y) in xy_expected] self.assertEqual(expected, pos) expected_idx = [[z, xy] for z in range_(5) for xy in range_(len(xy_expected))] self.assertEqual(expected_idx, idx)
def iterator(self): for i in range_(0, self._end_point(self.radius) + 1): p = Point() p.indexes = [i] i += 0.5 # Offset so lower bound of first point is not less than 0 p.positions[self.names[0]], p.positions[self.names[1]] = self._calc(i) p.upper[self.names[0]], p.upper[self.names[1]] = self._calc(i + 0.5) p.lower[self.names[0]], p.lower[self.names[1]] = self._calc(i - 0.5) yield p
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 _base_iterator(self): """ Iterator to generate points by nesting each generator in self.generators Yields: Point: Base points """ for point_num in range_(self.num): point = Point() for gen_index, points in enumerate(self.point_sets): axis_period = self.periods[gen_index] axis_length = len(points) # Can't use index_dims in case they have been flattened # by an excluder point_index = \ (point_num / (axis_period / axis_length)) % axis_length loop_number = point_num / axis_period # Floor floats to ints for indexing point_index = int(point_index) loop_number = int(loop_number) if self.alternate_direction[gen_index] and loop_number % 2: point_index = (axis_length - 1) - point_index reverse = True else: reverse = False current_point = points[point_index] # If innermost generator, use bounds if gen_index == len(self.point_sets) - 1: point.positions.update(current_point.positions) if reverse: # Swap bounds if reversing point.upper.update(current_point.lower) point.lower.update(current_point.upper) else: point.upper.update(current_point.upper) point.lower.update(current_point.lower) else: point.positions.update(current_point.positions) point.upper.update(current_point.positions) point.lower.update(current_point.positions) point.indexes += current_point.indexes logging.debug("Current point positions and indexes") logging.debug([current_point.positions, current_point.indexes]) yield point
def test_alternating_simple(self): y = LineGenerator("y", "mm", 1, 5, 5) x = LineGenerator("x", "mm", 1, 5, 5, alternate=True) g = CompoundGenerator([y, x], [], []) g.prepare() expected = [] expected_idx = [] expected_lower = [] expected_upper = [] for y in range_(1, 6): x_f = y % 2 == 1 r = range_(1, 6) if x_f else range_(5, 0, -1) for x in r: expected.append({"y": float(y), "x": float(x)}) expected_idx.append([y - 1, x - 1]) expected_lower.append(x + (-0.5 if x_f else 0.5)) expected_upper.append(x + (0.5 if x_f else -0.5)) 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_double_mask_spiral(self): zgen = LineGenerator("z", "mm", 0.0, 4.0, 5) spiral = SpiralGenerator(['x', 'y'], "mm", [0.0, 0.0], 3) #29 points r1 = RectangularROI([-2, -2], 4, 3) r2 = RectangularROI([-2, 0], 4, 3) e1 = ROIExcluder([r1], ["y", "x"]) e2 = ROIExcluder([r2], ["y", "z"]) g = CompoundGenerator([zgen, spiral], [e1, e2], []) g.prepare() p = list(zip(spiral.positions['x'], spiral.positions['y'])) p = [(x, y, z) for z in range_(0, 5) for (x, y) in p] expected = [x >= -2 and x <= 1 and y >= -2 and y <= 2 and z >= 0 and z <= 3 for (x, y, z) in p] actual = g.dimensions[0].mask.tolist() self.assertEqual(expected, actual)
def mask_points(self, points): x = points[0] y = points[1] v1 = self.points[-1] mask = np.full(len(x), False, dtype=bool) for i in range_(0, len(self.points)): v2 = self.points[i] if (v2[1] == v1[1]): # skip horizontal edges v1 = v2 continue vmask = ((y < v2[1]) & (y >= v1[1])) | ((y < v1[1]) & (y >= v2[1])) t = (y - v2[1]) / (v2[1] - v1[1]) vmask &= x < v1[0] + t * (v2[0] - v1[0]) mask ^= vmask v1 = v2 return mask
def test_intermediate_staticpointgen(self): x = LineGenerator("x", "mm", 0, 1, 3, False) y = LineGenerator("y", "cm", 2, 3, 4, False) m = StaticPointGenerator(5) g = CompoundGenerator([y, m, x], [], []) g.prepare() expected_positions = [] for yp in [2.0, 2 + 1. / 3, 2 + 2. / 3, 3.0]: for mp in range_(5): for xp in [0.0, 0.5, 1.0]: expected_positions.append({"y": yp, "x": xp}) positions = [point.positions for point in g.iterator()] self.assertEqual(expected_positions, positions) self.assertEqual(60, g.size) self.assertEqual((4, 5, 3), g.shape) self.assertEqual(["y", "x"], g.axes) self.assertEqual({"y": "cm", "x": "mm"}, g.units) self.assertEqual(3, len(g.dimensions))
def iterator(self): for i in range_(self.num): point = Point() for axis, coordinate in enumerate(self.points[i]): point.positions[self.name[axis]] = coordinate if self.upper_bounds is None: upper = self._calculate_upper_bound(i, axis, coordinate) else: upper = self.upper_bounds[i][axis] point.upper[self.name[axis]] = upper if self.lower_bounds is None: lower = self._calculate_lower_bound(i, axis, coordinate) else: lower = self.lower_bounds[i][axis] point.lower[self.name[axis]] = lower point.indexes = [i] yield point
def iterator(self): it = (self.get_point(n) for n in range_(self.num)) for m in self.mutators: it = m.mutate(it) for p in it: yield p