/pixelscan

A Python library that provides functions to scan pixels on a grid in a variety of spatial patterns.

Primary LanguagePythonMIT LicenseMIT

pixelscan

Code Status Code Coverage Code Package

The pixelscan library provides functions to scan pixels on a grid in a variety of spatial patterns. The library consists of scan generators and coordinate transformations. Scan generators are Python generators that return pixel coordinates in a particular spatial pattern. Coordinate transformations are iterators that apply spatial transformations to the coordinates created by the scan generators. Transformation can be chained to yield very generic transformations.

Documentation

See the library API documentation here.

Usage

The typical calling syntax is

for x, y in transformation(generator(...), ...):
   foo(x,y)

For example, the following scans pixels in a clockwise circular pattern from the origin up to a radius of one

for x, y in snap(circlescan(0, 0, 0, 1)):
   print(x, y)

and will generate the following points

(0,0), (0,1), (1,1), (1,0), (1,-1), (0,-1), (-1,-1), (-1,0), (-1,1)

To skip every other pixel a skip transformation can be applied

for x, y in snap(skip(circlescan(0, 0, 0, 1), step=2)):
   print(x, y)

which will generate the following points

(0,0), (1,1), (1,-1), (-1,-1), (-1,1)

Scan Generators

The following are the currently available generators

Name Description
circlescan Generates pixels in a clockwise circular pattern
examples/circlescan.png
x0, y0, r1, r2 = 0, 0, 0, 2
for x, y in snap(circlescan(x0, y0, r1, r2)):
    print(x, y)

where

x0 = Circle x center
y0 = Circle y center
r1 = Initial radius
r2 = Final radius

produces the following points:

( 0, 0) ( 0, 1) ( 1, 1) ( 1, 0) ( 1,-1) ( 0,-1)
(-1,-1) (-1, 0) (-1, 1) ( 0, 2) ( 1, 2) ( 2, 1)
( 2, 0) ( 2,-1) ( 1,-2) ( 0,-2) (-1,-2) (-2,-1)
(-2, 0) (-2, 1) (-1, 2)
gridscan Generates pixels in rectangular grid pattern
examples/gridscan.png
xi, yi, xf, yf = 0, 0, 2, 2
for x, y in gridscan(xi, yi, xf, yf, stepx=1, stepy=1):
    print(x, y)

where

xi    = Initial x-coordinate
yi    = Initial y-coordinate
xf    = Final x-coordinate
yf    = Final y-coordinate
stepx = Step size in x-coordinate
stepy = Step size in y-coordinate

produces the following points:

(0,0) (1,0) (2,0) (0,1) (1,1) (2,1) (0,2) (1,2) (2,2)
hilbertscan Generates pixels in a Hilbert curve pattern
examples/hilbertscan.png
size, distance = 4, 16
for x, y in hilbertscan(size, distance):
    print(x, y)

where

size     = Size of enclosing square
distance = Distance along curve

produces the following points:

(0,0), (0,1), (1,1), (1,0), (2,0), (3,0), (3,1), (2,1)
(2,2), (3,2), (3,3), (2,3), (1,3), (1,2), (0,2), (0,3)
ringscan - chebyshev Generates pixels in a ring pattern (squares)
examples/chebyshev.png
x0, y0, r1, r2 = 0, 0, 0, 2
for x, y in ringscan(x0, y0, r1, r2, metric=chebyshev):
    print(x, y)

where

x0     = Circle x center
y0     = Circle y center
r1     = Initial radius
r2     = Final radius
r2     = Final radius
metric = Distance metric

produces the following points:

( 0, 0) ( 0, 1) ( 1, 1) ( 1, 0) ( 1,-1) ( 0,-1)
(-1,-1) (-1, 0) (-1, 1) ( 0, 2) ( 1, 2) ( 2, 2)
( 2, 1) ( 2, 0) ( 2,-1) ( 2,-2) ( 1,-2) ( 0,-2)
(-1,-2) (-2,-2) (-2,-1) (-2, 0) (-2, 1) (-2,2) (-1,2)
ringscan - manhattan Generates pixels in a ring pattern (diamonds)
examples/manhattan.png
x0, y0, r1, r2 = 0, 0, 0, 2
for x, y in ringscan(x0, y0, r1, r2, metric=manhattan):
    print(x, y)

where

x0 = Circle x center
y0 = Circle y center
r1 = Initial radius
r2 = Final radius
metric = Distance metric

produces the following points:

( 0, 0) ( 0, 1) ( 1, 0) ( 0,-1) (-1, 0) ( 0, 2)
( 1, 1) ( 2, 0) ( 1,-1) ( 0,-2) (-1,-1) (-2, 0) (-1, 1)
snakescan Generates pixels in a snake pattern along the x then y axis
examples/snakescan.png
xi, yi, xf, yf = 0, 0, 2, 2
for x, y in snakescan(xi, yi, xf, yf):
    print(x, y)

where

xi = Initial x-coordinate
yi = Initial y-coordinate
xf = Final x-coordinate
yf = Final y-coordinate

produces the following points:

( 0, 0) ( 1, 0) ( 2, 0) ( 2, 1) ( 1, 1) ( 0, 1)
( 0, 2) ( 1, 2) ( 2, 2)
walkscan Generates pixels in a random pattern using a random walk
examples/walkscan.png
random.seed(0)
x0, y0, = 0, 0
for x, y in skip(walkscan(x0, y0, xn=0.25, xp=0.25,
                          yn=0.25, yp=0.25), stop=8):
    print(x, y)

where

x0 = Initial x-coordinate
y0 = Initial y-coordinate
xn = Probability of moving in the negative x direction
xp = Probability of moving in the positive x direction
yn = Probability of moving in the negative y direction
yp = Probability of moving in the positive y direction

produces the following points:

( 0, 0) ( 0, 1) ( 0, 2) ( 1, 2) ( 2, 2) ( 2, 1)
( 3, 1) ( 3, 2) ( 4, 2)

Coordinate Transformations

The following are the currently available transformations

Name Description
clip Clips the coordinates at the given boundary

Syntax:

clip(scan,
     minx      = int,
     maxx      = int,
     miny      = int,
     maxy      = int,
     predicate = function,
     abort     = bool)

where

scan      = Pixel scan generator
minx      = Minimum x-coordinate (default = -sys.maxint)
maxx      = Maximum x-coordinate (default =  sys.maxint)
miny      = Minimum y-coordinate (default = -sys.maxint)
maxy      = Maximum y-coordinate (default =  sys.maxint)
predicate = Optional function that takes 2 arguments (x and y)
            and returns true if coordinate should be kept
            otherwise false (default = None)
abort     = Abort iteration if boundary is crossed
reflection Reflects the coordinates along the x and/or y axis

Syntax:

reflection(scan, rx = bool, ry = bool)

where

scan = Pixel scan generator
rx   = True if x-coordinate should be reflected (default=False)
ry   = True if y-coordinate should be reflected (default=False)
reservoir Randomly samples the pixels using reservoir sampling

Syntax:

reservoir(scan, npoints = int)

where

scan    = Pixel scan generator
npoints = Sample size
rotation Rotates the coordinates about the origin counter-clockwise

Syntax:

rotation(scan, angle = float)

where

scan  = Pixel scan generator
angle = Counter-clockwise angle in degrees (default=0)
sample Randomly samples the pixels with a given probability

Syntax:

sample(scan, probability = float)

where

scan        = Pixel scan generator
probability = Sampling probability in interval [0,1] (default=1)
scale Scales the coordinates with a given scale factors

Syntax:

scale(scan, sx = float, sy = float)

where

scan = Pixel scan generator
sx   = x-coordinate scale factor (default=1)
sy   = y-coordinate scale factor (default=1)
skip Skips the pixels with the given step size

Syntax:

skip(scan, start = int, stop = int, step = int)

where

scan  = Pixel scan generator
start = Iteration starting 0-based index (default = 0)
stop  = Iteration stopping 0-based index (default = sys.maxint)
step  = Iteration step size (default = 1)
snap Snap the x and y coordinates to the nearest grid point

Syntax:

snap(scan)

where

scan = Pixel scan generator
swap Swap the x and y coordinates

Syntax:

swap(scan)

where

scan = Pixel scan generator
translation Translates the coordinates by the given offsets

Syntax:

translation(scan, tx = float, ty = float)

where

scan = Pixel scan generator
tx   = x-coordinate translation offset (default = 0)
ty   = y-coordinate translation offset (default = 0)

Warnings

Scan Generators such as circlescan and Coordinate Transformations such as rotation can yield non-grid points. They can be snapped to a grid point using the snap transformation.