'''
Created on 2 nov. 2017
@author: Colley JM
'''
import numpy as np
import matplotlib.pyplot as plt
from common.instru.array_convention import yzegp_to_ijdet_array
[docs]class ArraySquareCell(object):
'''
unit : cm, cm^2
'''
def __init__(self, ncel_x=1, ncel_y=1, size_cm=1.0):
'''
'''
self.max_ix = ncel_x - 1
self.max_iy = ncel_y - 1
self.size_cm = size_cm*1.0
self.surf_cell = self.size_cm**2
self.ar_val = np.zeros((ncel_x, ncel_y), dtype=np.float32)
self.to_origin_cm = np.array([0.0, 0.0], dtype=np.float32 )
self.l_verb = 0
[docs] def empty_like(self, p_asc):
"""
Initiation of current with parameter of ArraySquareCell p_asc
:param p_asc: array model
:type p_asc: ArraySquareCell
"""
assert isinstance(p_asc, ArraySquareCell)
self.max_ix = p_asc.max_ix
self.max_iy = p_asc.max_iy
self.size_cm = p_asc.size_cm
self.surf_cell = self.size_cm**2
self.ar_val = np.zeros((self.max_ix + 1, self.max_iy + 1), dtype=np.float32)
self.to_origin_cm = p_asc.to_origin_cm
# setter
[docs] def set_array(self, p_ar):
if (self.get_nb_cell_y() != p_ar.shape[1]):
return None
if (self.get_nb_cell_x() != p_ar.shape[0]):
return None
self.ar_val = np.copy(p_ar)
[docs] def add_hit(self, apos):
"""
Add one on pixel associated to position
:param apos: array plan position of photon
:type apos: numpy array (n,2)
"""
if apos.size == 0:
return
idx_pix = self.pos2idx_inf(apos)
it = np.nditer([idx_pix[:,0], idx_pix[:,1]], [], [['readonly'], ['readonly']])
for il, ic in it:
self.ar_val[il, ic] += 1
[docs] def set_origin_center(self):
self.to_origin_cm = self.get_sizecm()/2.0
[docs] def set_pos_corner_lb(self, p_pos_ori : np.array):
"""
vector OP where P=pos_array_lb and O: origin
"""
self.to_origin_cm = -p_pos_ori.copy()
[docs] def set_origin(self, p_pos_ori : np.array):
"""
vector PO where P=pos_array_lb and O: origin
"""
self.to_origin_cm = p_pos_ori.copy()
# getter
[docs] def get_nb_cell_x(self):
return self.ar_val.shape[0]
[docs] def get_nb_cell_y(self):
return self.ar_val.shape[1]
[docs] def get_nb_cell(self):
return self.ar_val.size
[docs] def get_sizecm(self):
array_size = np.array([0,0], dtype=np.float32 )
array_size[0] = self.ar_val.shape[0] * self.size_cm
array_size[1] = self.ar_val.shape[1] * self.size_cm
return array_size
[docs] def get_surface(self):
"""
return : [cm]^2
"""
array_size = self.get_sizecm()
return array_size[0]*array_size[1]
[docs] def pos_rect_array(self):
rect = np.empty((2,2), dtype=np.float32)
rect[0,:] = self.pos_corner_lb()
rect[1,:] = rect[0,:] + self.get_sizecm()
return rect
[docs] def pos_rect_cell(self, idx):
"""
for one cell
"""
rect = np.empty((2, 2), dtype=np.float32)
a_idx = np.array([idx])
rect[0,:] = self.idx2pos_inf(a_idx)
rect[1,:] = rect[0,:] + self.size_cm
return rect
[docs] def pos_rect_cells(self, aidx):
"""
for array index cells
"""
n_rect = aidx.shape[0]
arect = np.empty((n_rect,2,2), dtype=np.float32)
arect[:,0,:] = self.idx2pos_inf(aidx)
arect[:,1,:] = self.idx2pos_sup(aidx)
return arect
[docs] def pos_corner_lb(self):
"""
return : [cm] position corner 'l'eft 'b'ottom
"""
return -self.to_origin_cm
[docs] def pos_corner_ru(self):
"""
return : [cm] position corner 'r'ight 'u'pper
"""
return self.get_sizecm() - self.to_origin_cm
[docs] def pos_center_cells(self):
"""Return 2 array x and y with center cells
:return: 2 array x and y with center cells
:rtype: numpy array
"""
# AFINIR bonne convention de repere
x_center = np.arange(self.get_nb_cell_x()) * self.size_cm + self.size_cm / 2
x_center -= self.to_origin_cm[0]
y_center = np.arange(self.get_nb_cell_y()) * self.size_cm + self.size_cm / 2
y_center -= self.to_origin_cm[1]
return (x_center, y_center)
[docs] def value_at_pos_check(self, pos):
idx = self.pos2idx_inf(pos)
idx0 = idx[0]
if self.l_verb > 0:
print("Max: ",self.get_nb_cell_x(), self.get_nb_cell_y())
if idx0 < 0 or idx0 >= self.get_nb_cell_x():
print("ERROR value_at_pos_check(): out of index")
return None
idx1 = idx[1]
if idx1 < 0 or idx1 >= self.get_nb_cell_y():
print("ERROR value_at_pos_check(): out of index")
return None
return self.value(idx)
[docs] def value_at_pos(self, pos):
idx = self.pos2idx_inf(pos)
return self.value(idx)
[docs] def value(self, idx):
return self.ar_val[idx[0], idx[1]]
[docs] def value_array(self, aidx : np.array):
"""
aidx (n, 2)
"""
return self.ar_val[aidx[:,0], aidx[:,1]]
[docs] def get_shape(self):
return self.ar_val.shape
[docs] def set_val(self, p_val):
self.ar_val[:,:] = p_val
[docs] def get_ij_cell_surrounded_no_0(self):
a_ij = np.empty((0,2), dtype=np.int16)
p_ar = self.ar_val
for p_i in range(1, p_ar.shape[0]-1):
for p_j in range(1, p_ar.shape[1]-1):
#print(p_i,p_j)
if (p_ar[p_i+1, p_j-1]*p_ar[p_i+1, p_j]*p_ar[p_i+1, p_j+1] == 0.0):
continue
if (p_ar[p_i, p_j-1]*p_ar[p_i, p_j+1] == 0.0):
continue
if (p_ar[p_i-1, p_j-1]*p_ar[p_i-1, p_j]*p_ar[p_i-1, p_j+1] == 0.0):
continue
a_ij = np.vstack((a_ij, np.array([p_i, p_j], dtype=np.int16)))
return a_ij
# methods convert
[docs] def pos2idx_rect(self, p_rect, p_boundary=False):
"""
p_rect is one rectangle
"""
r_idx = np.empty((2,2), dtype=np.int8)
r_idx[0] = self.pos2idx_inf(p_rect[0])
r_idx[1] = self.pos2idx_inf(p_rect[1])
if p_boundary:
r_idx = np.where(r_idx < 0, 0, r_idx)
r_idx[:,0] = np.where(r_idx[:,0] > self.max_ix, self.max_ix, r_idx[:,0])
r_idx[:,1] = np.where(r_idx[:,1] > self.max_iy, self.max_iy, r_idx[:,1])
return r_idx
[docs] def idx2pos(self, array_idx, pos="CTR"):
"""return array position
:param array_idx: array index
:type array_idx: int
:param pos: pos = {Center: CTR, left bottom :LB, right up :RU}
:type pos: string
"""
array_idx_c = array_idx.copy().astype(np.float32)
if pos == "CTR":
array_idx_c += np.array([0.5, 0.5], dtype=np.float32)
elif pos == "RU":
array_idx_c += np.array([1, 1])
pos = array_idx_c*self.size_cm - self.to_origin_cm
return pos
[docs] def idx2pos_inf(self, array_idx):
return self.idx2pos(array_idx, "LB")
[docs] def idx2pos_sup(self, array_idx):
return self.idx2pos(array_idx, "RU")
[docs] def pos2idx(self, pos_cm, round_func = None):
array_idx = (pos_cm + self.to_origin_cm)/self.size_cm
if not round_func :
return (pos_cm + self.to_origin_cm)/self.size_cm
idx = round_func(array_idx).astype(int)
return idx
[docs] def pos2idx_inf(self, pos_cm):
return self.pos2idx(pos_cm, np.floor)
[docs] def pos2idx_sup(self, pos_cm):
return self.pos2idx(pos_cm, np.ceil)
# methods on all array in place
[docs] def random_value(self, pmin, pmax):
aa = np.random.randint(pmin, pmax + 1, self.ar_val.size).reshape((self.get_nb_cell_x(), -1))
self.set_array(aa)
[docs] def random_pos(self, nb_pos):
"""
random position in all array
:param nb_pos: number position to random
:type nb_pos: int
"""
msize = self.get_sizecm()
apos = np.empty((nb_pos,2), dtype=np.float32)
apos[:,0] = np.random.uniform(0, msize[0]-1e-5, nb_pos)
apos[:,1] = np.random.uniform(0, msize[1]-1e-5, nb_pos)
#print (self.to_origin_cm, apos.size)
retpos = apos - self.to_origin_cm
#print (retpos)
return retpos
[docs] def random_pos_rect(self, nb_pos, rec):
"""
random position in rectangle given by parameter
return : nb_pos random position in rec
"""
epsilon = 1e-5
apos = np.empty((nb_pos,2), dtype=np.float32)
apos[:,0] = np.random.uniform(rec[0,0]+epsilon, rec[1,0]-epsilon , nb_pos)
apos[:,1] = np.random.uniform(rec[0,1]+epsilon, rec[1,1]-epsilon, nb_pos)
return apos
[docs] def surf_intersection_rect(self, p_r1, p_r2):
inter_rec = self.intersection_rect(p_r1, p_r2)
surface = (inter_rec[1,0] - inter_rec[0,0])*(inter_rec[1,1] - inter_rec[0,1])
return surface
[docs] def intersection_rect(self, p_r1, p_r2):
rec_inter_0 = np.zeros((2,2), dtype=np.float32)
rec_inter = np.empty_like(rec_inter_0)
corner_lb_p = p_r1[0,:]
corner_ru_p = p_r1[1,:]
corner_lb_pp = p_r2[0,:]
corner_ru_pp = p_r2[1,:]
# corner lb intersection
if corner_lb_pp[0] < corner_lb_p[0]:
rec_inter[0,0] = corner_lb_p[0]
elif corner_lb_pp[0] < corner_ru_p[0]:
rec_inter[0,0] = corner_lb_pp[0]
else:
return rec_inter_0
if corner_lb_pp[1] < corner_lb_p[1]:
rec_inter[0,1] = corner_lb_p[1]
elif corner_lb_pp[1] < corner_ru_p[1]:
rec_inter[0,1] = corner_lb_pp[1]
else:
return rec_inter_0
if corner_ru_pp[0] < corner_lb_p[0]:
return rec_inter_0
elif corner_ru_pp[0] < corner_ru_p[0]:
rec_inter[1,0] = corner_ru_pp[0]
else:
rec_inter[1,0] = corner_ru_p[0]
if corner_ru_pp[1] < corner_lb_p[1]:
return rec_inter_0
elif corner_ru_pp[1] < corner_ru_p[1]:
rec_inter[1,1] = corner_ru_pp[1]
else:
rec_inter[1,1] = corner_ru_p[1]
return rec_inter
[docs] def intersection(self, o_asc , vec_trans):
"""
Intersection entre le tableau en attribut et un tableau passé en paramètre à translater
return [[x_lb, y_lb], [x_ru, y_ru]] rectangle intersection, lb: left bottom, ru: right uppper
"""
rec_inter_0 = np.zeros((2,2), dtype=np.float32)
rec_inter = np.empty_like(rec_inter_0)
corner_lb_p = self.pos_corner_lb()
corner_ru_p = self.pos_corner_ru()
corner_lb_pp = o_asc.pos_corner_lb() + vec_trans
corner_ru_pp = o_asc.pos_corner_ru() + vec_trans
# corner lb intersection
if corner_lb_pp[0] < corner_lb_p[0]:
rec_inter[0,0] = corner_lb_p[0]
elif corner_lb_pp[0] < corner_ru_p[0]:
rec_inter[0,0] = corner_lb_pp[0]
else:
return rec_inter_0
if corner_lb_pp[1] < corner_lb_p[1]:
rec_inter[0,1] = corner_lb_p[1]
elif corner_lb_pp[1] < corner_ru_p[1]:
rec_inter[0,1] = corner_lb_pp[1]
else:
return rec_inter_0
if corner_ru_pp[0] < corner_lb_p[0]:
return rec_inter_0
elif corner_ru_pp[0] < corner_ru_p[0]:
rec_inter[1,0] = corner_ru_pp[0]
else:
rec_inter[1,0] = corner_ru_p[0]
if corner_ru_pp[1] < corner_lb_p[1]:
return rec_inter_0
elif corner_ru_pp[1] < corner_ru_p[1]:
rec_inter[1,1] = corner_ru_pp[1]
else:
rec_inter[1,1] = corner_ru_p[1]
return rec_inter
[docs] def sample_up(self, pfact):
"""
pfact is int
result: repeat pfactxpfact each element
"""
o_asc = ArraySquareCell(self.get_nb_cell_x() * pfact, self.get_nb_cell_y() * pfact, self.size_cm / pfact)
su_ar = self.ar_val.repeat(pfact).reshape ((self.get_nb_cell_x(), self.get_nb_cell_y() * pfact)).T
su_ar = su_ar.repeat(pfact).reshape((self.get_nb_cell_x() * pfact, self.get_nb_cell_y() * pfact)).T
# plt.figure()
# plt.imshow(su_ar.T)
o_asc.set_array(su_ar)
return o_asc
# plot
[docs] def plot_ijdet(self, p_mes=""):
plt.figure()
plt.title(p_mes)
plt.imshow(yzegp_to_ijdet_array(self.ar_val))
plt.colorbar()
[docs] def plot(self, p_mes=""):
plt.figure()
plt.title(p_mes)
plt.imshow(np.transpose(self.ar_val) , origin='lower')
plt.colorbar()