53 lines
2.1 KiB
Python
53 lines
2.1 KiB
Python
from itertools import cycle, chain
|
|
|
|
from pyscan.utils import convert_to_list
|
|
|
|
|
|
class VectorPositioner(object):
|
|
"""
|
|
Moves over the provided positions.
|
|
"""
|
|
|
|
def _validate_parameters(self):
|
|
if not all(len(convert_to_list(x)) == len(convert_to_list(self.positions[0])) for x in self.positions):
|
|
raise ValueError("All positions %s must have the same number of axis." % self.positions)
|
|
|
|
if not isinstance(self.passes, int) or self.passes < 1:
|
|
raise ValueError("Passes must be a positive integer value, but %s was given." % self.passes)
|
|
|
|
if self.offsets and (not len(self.offsets) == len(self.positions[0])):
|
|
raise ValueError("Number of offsets %s does not match the number of positions %s." %
|
|
(self.offsets, self.positions[0]))
|
|
|
|
def __init__(self, positions, passes=1, offsets=None):
|
|
self.positions = convert_to_list(positions)
|
|
self.passes = passes
|
|
self.offsets = convert_to_list(offsets)
|
|
|
|
self._validate_parameters()
|
|
|
|
# Number of positions to move to.
|
|
self.n_positions = len(self.positions)
|
|
|
|
# Fix the offset if provided.
|
|
if self.offsets:
|
|
for step_positions in self.positions:
|
|
step_positions[:] = [original_position + offset
|
|
for original_position, offset in zip(step_positions, self.offsets)]
|
|
|
|
def get_generator(self):
|
|
for _ in range(self.passes):
|
|
for position in self.positions:
|
|
yield position
|
|
|
|
|
|
class ZigZagVectorPositioner(VectorPositioner):
|
|
def get_generator(self):
|
|
# This creates a generator for [0, 1, 2, 3... n, n-1, n-2.. 2, 1, 0.....]
|
|
indexes = cycle(chain(range(0, self.n_positions, 1), range(self.n_positions - 2, 0, -1)))
|
|
# First pass has the full number of items, each subsequent has one less (extreme sequence item).
|
|
n_indexes = self.n_positions + ((self.passes - 1) * (self.n_positions - 1))
|
|
|
|
for x in range(n_indexes):
|
|
yield self.positions[next(indexes)]
|