import numpy as np
from matplotlib import pyplot as plt
from .frameseries import frameseries
from .frameutils.arraysplit import arraysplit
[docs]class region(object):
component_regions = ()
logic = None
corner = np.array([0,0])
shape = np.array([0,0])
def __init__(self, component_regions, logic):
self.component_regions = component_regions
self.logic = logic
# reset of default somehow required
self.corner = np.array([0,0])
self.shape = np.array([0,0])
if component_regions.__class__ == tuple:
# top right corner
trc = np.array([0,0])
# interate over x, y coordinates
for i in range(2):
# bottom left corner
self.corner[i] = min(component_regions[0].corner[i], component_regions[1].corner[i])
# top right corner
trc[i] = max(component_regions[0].corner[i]+component_regions[0].shape[i],
component_regions[1].corner[i]+component_regions[1].shape[i])
# shape
self.shape[i] = trc[i] - self.corner[i]
else:
self.corner = component_regions.corner
def __and__(self, other):
return region((self, other), 'and')
def __or__(self, other):
return region((self, other), 'or')
def __xor__(self, other):
return region((self, other), 'xor')
def __invert__(self):
return region((self), 'not')
[docs] def getmask(self, frame):
if self.logic == 'and':
return self.component_regions[0].getmask(frame.copy()) & self.component_regions[1].getmask(frame.copy())
elif self.logic == 'or':
return self.component_regions[0].getmask(frame.copy()) | self.component_regions[1].getmask(frame.copy())
elif self.logic == 'xor':
return self.component_regions[0].getmask(frame.copy()) ^ self.component_regions[1].getmask(frame.copy())
elif self.logic == 'not':
return np.logical_not(self.component_regions.getmask(frame.copy()))
[docs] def plot(self, **kwargs):
if self.component_regions.__class__ == tuple:
for reg in self.component_regions:
reg.plot(**kwargs)
else:
self.component_regions.plot(**kwargs)
[docs] def isinregion(self):
pass
[docs] def getframeseries(self, fs, reshape = False, dtype=None):
'''
Select photon in region and obtain frameseries
Parameters
---------
fs : :class:`photonpacket.frameseries`
reshape : bool
Returns
---------
See Also
---------
Notes
---------
Examples
---------
'''
if dtype is None:
dtype = fs.dtype
photons = fs.photons.copy()
else:
photons = fs.photons.astype(dtype)
mask = self.getmask(photons[:,:2].copy())
cmask = np.r_[0, np.cumsum(mask)]
idxs = np.r_[0, cmask[fs.idxs[1:]]]
if reshape:
photons = self.reshape(photons)
return frameseries(photons[mask], idxs, self.shape, cut=False, dtype=dtype)
else:
return frameseries(photons[mask], idxs, fs.shape, cut=False, dtype=dtype)
[docs] def getcounts(self, fs):
'''
Get total photon number in each frame
Parameters
---------
fs : :class:`photonpacket.frameseries`
Returns
---------
counts : :class:`numpy.ndarray`
1D array of counts
See Also
---------
Notes
---------
Examples
---------
'''
cc_frames = np.array(fs.photons, dtype=np.uint32)
csum = np.cumsum(fs.N)
mask = self.getmask(cc_frames)
cmask = np.cumsum(mask)
cmask = np.insert(cmask, 0, 0)
# cmask length = total number of photons, csum length = total number of frames
# last element of csum = total number of photons
# last element of cmask = total number of photons in region
# we are selecting elements of cmask at points given by csum
# from this we obtain a cumsum of photon counts cN inside region
cN = cmask[csum]
cN = np.insert(cN, 0, 0)
# differentiation of cumsum photon photon counts from region
# giving counts in this region
N = cN - np.roll(cN, 1)
return N[1:]
[docs] def reshape(self, frame):
'''
Reshape frame to have (0,0) bottom-left corner
Parameters
---------
frane : :class:`numpy.ndarray`
Returns
---------
counts : :class:`numpy.ndarray`
photon frame
See Also
---------
Notes
---------
Examples
---------
'''
frame[:,0] -= self.corner[0]
frame[:,1] -= self.corner[1]
return frame
[docs]class circle(region):
'''
Circle region
'''
r = 0
x0 = 0
y0 = 0
shape = []
corner = np.array([])
def __init__(self, r, r0):
'''
Paramterers
---------
r : int
radius
r0=(x0, y0) : (int, int)
position of center
'''
(x0, y0) = r0
self.r = r
self.x0 = x0
self.y0 = y0
self.shape = [2*r, 2*r]
self.corner = np.array([self.x0-self.r, self.y0-self.r])
[docs] def plot(self,reshaped = False, **kwargs):
if 'ax' in kwargs:
ax=kwargs.pop('ax')
else:
ax=plt.gca()
if 'color' not in kwargs:
kwargs['color']='r'
if reshaped:
c1=plt.Circle((self.y0-self.corner[1],self.x0-self.corner[0]),self.r,fill=False,**kwargs)
else:
c1=plt.Circle((self.y0,self.x0),self.r,fill=False,**kwargs)
ax.add_artist(c1)
[docs] def r2dist(self,R):
return (self.x0-R[0])**2 + (self.y0-R[1])**2
[docs] def isinregion(self,R):
return (self.r2dist(R) < self.r**2)
[docs] def getmask(self, frame):
frame[:, 0] -= self.x0
frame[:, 1] -= self.y0
mask = np.sum(frame[:,0:2]**2,axis=1) < self.r**2
return mask
[docs]class rect(region):
'''
Rectangle region
'''
# TODO: add rotation angle?
x0 = 0
y0 = 0
x1 = 0
y1 = 0
shape = []
corner = np.array([])
def __init__(self, r0, r1):
'''
Paramterers
---------
r0=(x0, y0) : (int, int)
bottom left corner
r1=(x1, y1) : (int, int)
top right corner
'''
(x0,y0) = r0
(x1,y1) = r1
self.x0 = x0
self.y0 = y0
self.x1 = x1
self.y1 = y1
self.shape = [x1-x0, y1-y0]
self.corner = np.array([self.x0, self.y0])
[docs] def plot(self,color='r', **kwargs):
v1 = np.array([[self.y0,self.y1],[self.x0,self.x0]])
v2 = np.array([[self.y0,self.y0],[self.x0,self.x1]])
v3 = np.array([[self.y1,self.y0],[self.x1,self.x1]])
v4 = np.array([[self.y1,self.y1],[self.x1,self.x0]])
if 'ax' in kwargs:
ax = kwargs.pop('ax')
else:
ax=plt.gca()
ax.plot(v1[0],v1[1],color=color,**kwargs)
ax.plot(v2[0],v2[1],color=color,**kwargs)
ax.plot(v3[0],v3[1],color=color,**kwargs)
ax.plot(v4[0],v4[1],color=color,**kwargs)
[docs] def isinregion(self,R):
# TODO: implement
pass
[docs] def getmask(self, frame):
# frame[:,0] = frame[:,0] - self.x0
# frame[:,1] = frame[:,1] - self.y0
mask1 = frame[:,0] > self.x0
mask2 = frame[:,1] > self.y0
mask3 = frame[:,0] < self.x1
mask4 = frame[:,1] < self.y1
return mask1 * mask2 * mask3 * mask4
[docs]class rect2(rect):
'''
Rectangle defined by center
'''
def __init__(self, rc, rab):
'''
Paramterers
---------
rc=(xc, yc) : (int, int)
position of center
rab=(a, b) : (int, int)
horizontal and vertical extent
'''
(xc, yc) = rc
(a, b) = rab
x0 = xc - a
y0 = yc - b
x1 = xc + a
y1 = yc + b
super(rect2, self).__init__((x0, y0), (x1, y1))
[docs]class square(rect):
'''
Square region
'''
def __init__(self, a, rc):
'''
Paramterers
---------
a : int
extent
rc=(xc, yc) : (int, int)
position of center
'''
(xc, yc) = rc
x0 = xc - a
y0 = yc - a
x1 = xc + a
y1 = yc + a
super(square, self).__init__((x0, y0), (x1, y1))
[docs]class ring(region):
'''
Ring region
'''
r1 = 0
r2 = 0
x0 = 0
y0 = 0
shape = []
corner = np.array([])
def __init__(self,r1,r2, r0):
'''
Paramterers
---------
r1 : int
inner radius
r2 : int
outer radius
r0=(x0, y0) : (int, int)
position of center
'''
(x0,y0) = r0
self.r1 = r1
self.r2 = r2
self.x0 = x0
self.y0 = y0
self.shape = [2*r2, 2*r2]
self.corner = np.array([self.x0-self.r2,self.y0-self.r2])
[docs] def plot(self, reshaped = False):
ax=plt.gca()
if reshaped:
c1=plt.Circle((self.y0-self.corner[1],self.x0-self.corner[0]),self.r1,fill=False,color='r')
c2=plt.Circle((self.y0-self.corner[1],self.x0-self.corner[0]),self.r2,fill=False,color='g')
else:
c1=plt.Circle((self.y0,self.x0),self.r1,fill=False,color='r')
c2=plt.Circle((self.y0,self.x0),self.r2,fill=False,color='g')
ax.add_artist(c1)
ax.add_artist(c2)
[docs] def r2dist(self,R):
return (self.x0-R[0])**2+(self.y0-R[1])**2
[docs] def isinregion(self,R):
return ((self.r2dist(R)>self.r1**2) and (self.r2dist(R)<self.r2**2))
[docs] def getmask(self, frame):
frame[:,0] = frame[:,0]-self.x0
frame[:,1] = frame[:,1]-self.y0
mask1 = np.sum(frame[:,0:2]**2,axis=1) > self.r1**2
mask2 = np.sum(frame[:,0:2]**2,axis=1) < self.r2**2
return mask1 * mask2
[docs]class ellpise(region):
'''
Ellipse region
'''
a = 0
b = 0
x0 = 0
y0 = 0
angle = 0
frames = []
shape = []
corner = np.array([])
def __init__(self,a,b, r0,angle):
'''
Paramterers
---------
a : int
semi-major axis
b : int
semi-minor axis
r0=(x0,y0) : (int, int)
position of center
angle : float
rotation angle (in radians); not implemented
'''
(x0,y0) = r0
self.a = b
self.a = b
self.x0 = x0
self.y0 = y0
self.angle = angle
# TODO: rewrite shape calc
self.shape = [2*a, 2*b]
# TODO: rewrite corner calc
self.corner = np.array([self.x0-self.a,self.y0-self.b])
[docs] def plot(self):
ax=plt.gca()
e=plt.Ellipse(xy=(self.y0,self.x0),width=self.a,height=self.b,
angle=self.angle,fill=False,color='r')
ax.add_artist(e)
[docs] def r2dist(self,R):
return (self.x0-R[0])**2+(self.y0-R[1])**2
[docs] def isinregion(self,R):
# TODO: rewrite
return ((self.r2dist(R)>self.r1**2) and (self.r2dist(R)<self.r2**2))
[docs] def getmask(self, frame):
pass
[docs]class halfcircle(region):
'''
Halfcircle region
Not implemented
'''
r1 = 0
x0 = 0
y0 = 0
frames = []
shape = []
corner = np.array([])
def __init__(self,r,angle, r0):
'''
Paramterers
---------
r : int
radius
angle : float
rotation angle (in radians)
r0=(x0, y0) : (int, int)
position of center
'''
(x0,y0) = r0
self.r=r
self.angle=angle
self.x0=x0
self.y0=y0
# TODO: rewrite shape calc
self.shape = [2*r, 2*r]
# TODO: rewrite corner calc
self.corner = np.array([self.x0-self.r2,self.y0-self.r2])
[docs] def plot(self):
# TODO: rewrite plotting
ax=plt.gca()
c1=plt.Circle((self.y0,self.x0),self.r1,fill=False,color='r')
ax.add_artist(c1)
c2=plt.Circle((self.y0,self.x0),self.r2,fill=False,color='g')
ax.add_artist(c2)
[docs] def r2dist(self,R):
return (self.x0-R[0])**2+(self.y0-R[1])**2
[docs] def isinregion(self,R):
# TODO: rewrite
return ((self.r2dist(R)>self.r1**2) and (self.r2dist(R)<self.r2**2))
[docs] def getmask(self, frame):
pass
[docs]class line(region):
'''
1d line
'''
# TODO: add rotation angle?
x0 = 0
x1 = 0
shape = []
corner = np.array([])
def __init__(self, x0, x1):
'''
Paramterers
---------
r0=(x0, y0) : (int, int)
bottom left corner
r1=(x1, y1) : (int, int)
top right corner
'''
self.x0 = x0
self.x1 = x1
self.shape = [x1-x0, ]
self.corner = np.array([self.x0, 0])
[docs] def plot(self,color='r', **kwargs):
y0=0
y1=10
v1 = np.array([[self.x0,self.x0],[y0,y1]])
v2 = np.array([[self.x0,self.x1],[y0,y0]])
v3 = np.array([[self.x1,self.x1],[y1,y0]])
v4 = np.array([[self.x1,self.x0],[y1,y1]])
plt.plot(v1[0],v1[1],color=color,**kwargs)
plt.plot(v2[0],v2[1],color=color,**kwargs)
plt.plot(v3[0],v3[1],color=color,**kwargs)
plt.plot(v4[0],v4[1],color=color,**kwargs)
[docs] def isinregion(self,R):
# TODO: implement
pass
[docs] def getmask(self, frame):
mask1 = frame[:,0] > self.x0
mask2 = frame[:,0] < self.x1
return mask1 * mask2
[docs]class paramregion(region):
'''
Represtents abstract region in the space of additional photon paramters accesible via file loading with non-standard 'mode'
args:
fcomp - comparison function applied to an ARRAY of specified parameter values, yields true inside region
'''
paramid = 2 #subsequent radius redcution (SRR) step param by default
fcomp = lambda x:True #do not filter out anything by default
def __init__(self,fcomp,**kwargs):
self.fcomp = fcomp
if 'param' in kwargs:
if kwargs['param'] == 'step':
self.paramid = 2
elif kwargs['param'] == 'pixel_value':
self.paramid = 3
else:
print('Unrecognized param, possible values: "step" (id=2), "pixel_value" (id=3)')
[docs] def plot(self):
print(self.fcomp)
def __repr__(self):
print(self.fcomp, self.paramid)
[docs] def getmask(self,frame):
return self.fcomp(frame[:,self.paramid])