151 lines
4.3 KiB
Python
151 lines
4.3 KiB
Python
from numpy import ndarray, argmax, max, quantile, arange, where, convolve, ones
|
|
from scipy.optimize import curve_fit
|
|
from classes.science.border import Border
|
|
from function.utils import find_point, fill
|
|
|
|
class Plate:
|
|
"""
|
|
Matrix of pixel
|
|
"""
|
|
|
|
def __init__( self , data ):
|
|
if not isinstance( data , ndarray ):
|
|
raise TypeError( 'data must be a ndarray' )
|
|
self.data = data
|
|
self.set_border()
|
|
|
|
def set_border( self , factor = 10 ):
|
|
"""
|
|
Set current border (without area outside the plate)
|
|
"""
|
|
compressed = self.compress( factor )
|
|
|
|
points = self.get_points( compressed )
|
|
self.border = Border()
|
|
self.border.x.min = 0
|
|
self.border.x.max = compressed.shape[1] - 1
|
|
self.border.y.min = 0
|
|
self.border.y.max = compressed.shape[0] - 1
|
|
|
|
extremum = []
|
|
|
|
x_half = compressed.shape[1] // 2
|
|
y_half = compressed.shape[0] // 2
|
|
for index in range( len( points ) ):
|
|
point = points[ index ]
|
|
point[0] -= int( compressed.shape[0] == point[0] ) # keep in
|
|
point[1] -= int( compressed.shape[1] == point[1] ) # range
|
|
|
|
taken_points = fill(
|
|
compressed,
|
|
point ,
|
|
1000 , # intensity threshold
|
|
)
|
|
|
|
x = [ taken_point[1] for taken_point in taken_points ]
|
|
y = [ taken_point[0] for taken_point in taken_points ]
|
|
|
|
if max( x ) < x_half:
|
|
if self.border.x.min < max( x ):
|
|
self.border.x.min = max( x ) # biggest min
|
|
elif min( x ) > x_half: # elif to only accept one side
|
|
if self.border.x.max > min( x ):
|
|
self.border.x.max = min( x ) # smallest max
|
|
elif max( y ) < y_half:
|
|
if self.border.y.min < max( y ):
|
|
self.border.y.min = max( y ) # same
|
|
elif min( y ) > y_half:
|
|
if self.border.y.max > min( y ):
|
|
self.border.y.max = min( y ) # same
|
|
|
|
offset = 3
|
|
|
|
self.border.x.min += offset
|
|
self.border.y.min += offset
|
|
self.border.x.max -= offset
|
|
self.border.y.min -= offset
|
|
|
|
self.border.scale( factor )
|
|
|
|
def get_points( self , compressed ):
|
|
first_column = find_point(
|
|
compressed[
|
|
:,
|
|
0,
|
|
],
|
|
0,
|
|
)
|
|
last_column = find_point(
|
|
compressed[
|
|
: ,
|
|
- 1,
|
|
],
|
|
compressed.shape[1] - 1,
|
|
)
|
|
first_line = find_point(
|
|
compressed[
|
|
0,
|
|
:,
|
|
] ,
|
|
0 ,
|
|
'y',
|
|
)
|
|
|
|
if len( first_line ) < 2:
|
|
last_column = last_column[ 1 : ]
|
|
if len( first_line ) < 3:
|
|
first_line = []
|
|
else:
|
|
first_line = first_line[ 1 : - 1 ]
|
|
|
|
last_line = find_point(
|
|
compressed[
|
|
- 1,
|
|
: ,
|
|
] ,
|
|
compressed.shape[0] - 1,
|
|
'y' ,
|
|
)
|
|
|
|
if len( last_line ) < 2:
|
|
last_column = last_column[ : - 1 ]
|
|
if len( last_line ) < 3:
|
|
last_line = []
|
|
else:
|
|
last_line = last_line[ 1 : - 1 ]
|
|
|
|
return first_column + last_column + first_line + last_line
|
|
|
|
def compress( self , factor ):
|
|
return self.data[
|
|
: : factor,
|
|
: : factor,
|
|
]
|
|
|
|
def rotate( self ):
|
|
"""
|
|
Auto-rotate to be vertically and horizontally aligned
|
|
"""
|
|
maxes = max(
|
|
self.data[ self.border.slice() ],
|
|
axis = 0 ,
|
|
)
|
|
indexes = where(
|
|
maxes > quantile( maxes , 0.5 )
|
|
)
|
|
abciss = arange(
|
|
self.border.x.min,
|
|
self.border.x.max
|
|
)[ indexes ]
|
|
indexes_max = argmax(
|
|
self.data[ self.border.slice() ],
|
|
axis = 0 ,
|
|
)[ indexes ]
|
|
indexes_max = convolve(
|
|
indexes_max ,
|
|
ones( 100 ) ,
|
|
'same' ,
|
|
) / 100
|
|
import matplotlib.pyplot as plt
|
|
plt.plot( abciss , indexes_max )
|
|
plt.show()
|