def _calc_arrays(self, offset): x0, y0 = self.centre[0], self.centre[1] A, B = self.x_max, self.y_max a, b = self.x_freq, self.y_freq d = self.phase_diff f = lambda t: y0 + A * np.sin(a * 2 * m.pi * (t+offset)/self.num + d) x = f(np.arange(self.num)) f = lambda t: B * np.sin(b * 2 * m.pi * (t+offset)/self.num) y = f(np.arange(self.num)) return x, y
def get_mesh_map(self, axis): """ Retrieve the mesh map (indices) for a given axis within the dimension. Args: axis (str): axis to get positions for Returns: Positions (np.array): Array of mesh indices """ # the points for this axis must be scaled and then indexed if not self._prepared: raise ValueError("Must call prepare first") # scale up points for axis gen = [g for g in self.generators if axis in g.axes][0] points = gen.positions[axis] # just get index of points instead of actual point value points = np.arange(len(points)) if gen.alternate: points = np.append(points, points[::-1]) tile = 0.5 if self.alternate else 1 repeat = 1 for g in self.generators[:self.generators.index(gen)]: tile *= g.size for g in self.generators[self.generators.index(gen) + 1:]: repeat *= g.size points = np.repeat(points, repeat) if tile % 1 != 0: p = np.tile(points, int(tile)) points = np.append(p, points[:int(len(points) // 2)]) else: points = np.tile(points, int(tile)) return points[self.indices]
def get_points(self, start, finish): """ Retrieve a Points object: a wrapper for an array of Point from the generator Args: start (int), finish (int): indices of the first point and final+1th point to include i.e. get_points(1, 5) would return a Points of Point 1, 2, 3 & 4 but not 5. Returns: Points: a wrapper object with the data of the requested Point [plural] """ if not self._prepared: raise ValueError("CompoundGenerator has not been prepared") ''' situations: dim N constant, dim N+1 constant (e.g. 1,1 -> 1,1) dim N constant, dim N+1 increasing: (e.g. n,1->n,5) dim N increasing, dim N+1 increasing: (n,1->n+1,2) N[n],N+1[start]->N[n],N+1[max]->N[n+1],N+1[0]->...->N[K],N+1[finish] dim N increasing, dim N+1 decreasing: (n,2->n+1,1) as above dim N increasing, dim N+1 constant: (n,1->n+1,1) as above for each pair of consecutive dim N, N+1 => must be first dim M where changes (even if it's outermost). => All dimensions outside M must have single point => M must be within single dimension "run" => All dimensions inside M must tile => M behaves like all dimensions within it innermost dim must be moving ''' if finish == start: return Points() indices = np.arange(start, finish, np.sign(finish - start)) indices = np.where(indices < 0, indices + self.size, indices) if max(indices) >= self.size: raise IndexError("Requested points extend out of range") length = len(indices) points = Points() for dim in self.dimensions: point_repeat = int(self._dim_meta[dim]["repeat"]) point_indices = indices // point_repeat # Number of point this step is on found_m = np.any( point_indices != point_indices[0]) # For alternating case if found_m: points.extract(self._points_from_below_m(dim, point_indices)) else: points.extract( self._points_above_m(dim, point_indices[0], length)) points.duration = np.full(length, self.duration) points.delay_after = np.full(length, self.delay_after) for m in self.mutators: points = m.mutate(points, indices) return points
def _calc_arrays(self, offset): # spiral equation : r = b * phi # scale = 2 * pi * b # parameterise phi with approximation: # phi(t) = k * sqrt(t) (for some k) # number of possible t is solved by sqrt(t) = max_r / b*k b = self.scale / (2 * m.pi) k = m.sqrt(4 * m.pi) # magic scaling factor for our angle steps size = (self.radius) / (b * k) size *= size size = int(size) + 1 # TODO: Why the +1 ??? phi_t = lambda t: k * np.sqrt(t + offset) phi = phi_t(np.arange(size)) x = self.centre[0] + b * phi * np.sin(phi) y = self.centre[1] + b * phi * np.cos(phi) return x, y
def prepare_bounds(self): self.bounds = self.prepare_arrays(np.arange(self.size + 1) - 0.5)
def prepare_positions(self): self.positions = self.prepare_arrays(np.arange(self.size))