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()