<s> '''<STR_LIT>''' <EOL> import numpy as np <EOL> from centrosome . cpmorphology import all_connected_components <EOL> from centrosome . cpmorphology import fixup_scipy_ndimage_result as fix <EOL> from centrosome . cpmorphology import get_line_pts <EOL> from scipy . ndimage import binary_erosion , binary_fill_holes <EOL> from scipy . ndimage import mean as mean_of_labels <EOL> import cellprofiler . cpmodule as cpm <EOL> import cellprofiler . measurements as cpmeas <EOL> import cellprofiler . objects as cpo <EOL> import cellprofiler . preferences as cpprefs <EOL> import cellprofiler . settings as cps <EOL> import identify as I <EOL> from cellprofiler . settings import YES , NO <EOL> C_WORMS = "<STR_LIT>" <EOL> F_ANGLE = "<STR_LIT>" <EOL> M_ANGLE = "<STR_LIT:_>" . join ( ( C_WORMS , F_ANGLE ) ) <EOL> '''<STR_LIT>''' <EOL> MASK_ALPHA = <NUM_LIT> <EOL> '''<STR_LIT>''' <EOL> LABEL_ALPHA = <NUM_LIT:1.0> <EOL> '''<STR_LIT>''' <EOL> WORM_ALPHA = <NUM_LIT> <EOL> class IdentifyDeadWorms ( cpm . CPModule ) : <EOL> module_name = "<STR_LIT>" <EOL> variable_revision_number = <NUM_LIT:2> <EOL> category = [ "<STR_LIT>" , "<STR_LIT>" ] <EOL> def create_settings ( self ) : <EOL> """<STR_LIT>""" <EOL> self . image_name = cps . ImageNameSubscriber ( <EOL> "<STR_LIT>" , cps . NONE , doc = """<STR_LIT>""" ) <EOL> self . object_name = cps . ObjectNameProvider ( <EOL> "<STR_LIT>" , "<STR_LIT>" , doc = """<STR_LIT>""" ) <EOL> self . worm_width = cps . Integer ( <EOL> "<STR_LIT>" , <NUM_LIT:10> , minval = <NUM_LIT:1> , doc = """<STR_LIT>""" ) <EOL> self . worm_length = cps . Integer ( <EOL> "<STR_LIT>" , <NUM_LIT:100> , minval = <NUM_LIT:1> , doc = """<STR_LIT>""" ) <EOL> self . angle_count = cps . Integer ( <EOL> "<STR_LIT>" , <NUM_LIT:32> , minval = <NUM_LIT:1> , doc = """<STR_LIT>""" ) <EOL> self . wants_automatic_distance = cps . Binary ( <EOL> "<STR_LIT>" , True , doc = """<STR_LIT>""" % globals ( ) ) <EOL> self . space_distance = cps . Float ( <EOL> "<STR_LIT>" , <NUM_LIT:5> , minval = <NUM_LIT:1> , doc = """<STR_LIT>""" ) <EOL> self . angular_distance = cps . Float ( <EOL> "<STR_LIT>" , <NUM_LIT:30> , minval = <NUM_LIT:1> , doc = """<STR_LIT>""" ) <EOL> def settings ( self ) : <EOL> '''<STR_LIT>''' <EOL> return [ self . image_name , self . object_name , self . worm_width , <EOL> self . worm_length , self . angle_count , self . wants_automatic_distance , <EOL> self . space_distance , self . angular_distance ] <EOL> def visible_settings ( self ) : <EOL> '''<STR_LIT>''' <EOL> result = [ self . image_name , self . object_name , self . worm_width , <EOL> self . worm_length , self . angle_count , self . wants_automatic_distance ] <EOL> if not self . wants_automatic_distance : <EOL> result += [ self . space_distance , self . angular_distance ] <EOL> return result <EOL> def run ( self , workspace ) : <EOL> '''<STR_LIT>''' <EOL> image_set = workspace . image_set <EOL> image = image_set . get_image ( self . image_name . value , <EOL> must_be_binary = True ) <EOL> mask = image . pixel_data <EOL> if image . has_mask : <EOL> mask = mask & image . mask <EOL> angle_count = self . angle_count . value <EOL> i = np . zeros ( <NUM_LIT:0> , int ) <EOL> j = np . zeros ( <NUM_LIT:0> , int ) <EOL> a = np . zeros ( <NUM_LIT:0> , int ) <EOL> ig , jg = np . mgrid [ <NUM_LIT:0> : mask . shape [ <NUM_LIT:0> ] , <NUM_LIT:0> : mask . shape [ <NUM_LIT:1> ] ] <EOL> this_idx = <NUM_LIT:0> <EOL> for angle_number in range ( angle_count ) : <EOL> angle = float ( angle_number ) * np . pi / float ( angle_count ) <EOL> strel = self . get_diamond ( angle ) <EOL> erosion = binary_erosion ( mask , strel ) <EOL> this_count = np . sum ( erosion ) <EOL> i = np . hstack ( ( i , ig [ erosion ] ) ) <EOL> j = np . hstack ( ( j , jg [ erosion ] ) ) <EOL> a = np . hstack ( ( a , np . ones ( this_count , float ) * angle ) ) <EOL> first , second = self . find_adjacent_by_distance ( i , j , a ) <EOL> if len ( first ) > <NUM_LIT:0> : <EOL> ij_labels = all_connected_components ( first , second ) + <NUM_LIT:1> <EOL> nlabels = np . max ( ij_labels ) <EOL> label_indexes = np . arange ( <NUM_LIT:1> , nlabels + <NUM_LIT:1> ) <EOL> center_x = fix ( mean_of_labels ( j , ij_labels , label_indexes ) ) <EOL> center_y = fix ( mean_of_labels ( i , ij_labels , label_indexes ) ) <EOL> angles = fix ( mean_of_labels ( a , ij_labels , label_indexes ) ) <EOL> vangles = fix ( mean_of_labels ( ( a - angles [ ij_labels - <NUM_LIT:1> ] ) ** <NUM_LIT:2> , <EOL> ij_labels , label_indexes ) ) <EOL> aa = a . copy ( ) <EOL> aa [ a > np . pi / <NUM_LIT:2> ] -= np . pi <EOL> aangles = fix ( mean_of_labels ( aa , ij_labels , label_indexes ) ) <EOL> vaangles = fix ( mean_of_labels ( ( aa - aangles [ ij_labels - <NUM_LIT:1> ] ) ** <NUM_LIT:2> , <EOL> ij_labels , label_indexes ) ) <EOL> aangles [ aangles < <NUM_LIT:0> ] += np . pi <EOL> angles [ vaangles < vangles ] = aangles [ vaangles < vangles ] <EOL> labels = np . zeros ( mask . shape , int ) <EOL> labels [ i , j ] = ij_labels <EOL> else : <EOL> center_x = np . zeros ( <NUM_LIT:0> , int ) <EOL> center_y = np . zeros ( <NUM_LIT:0> , int ) <EOL> angles = np . zeros ( <NUM_LIT:0> ) <EOL> nlabels = <NUM_LIT:0> <EOL> label_indexes = np . zeros ( <NUM_LIT:0> , int ) <EOL> labels = np . zeros ( mask . shape , int ) <EOL> m = workspace . measurements <EOL> assert isinstance ( m , cpmeas . Measurements ) <EOL> object_name = self . object_name . value <EOL> m . add_measurement ( object_name , I . M_LOCATION_CENTER_X , center_x ) <EOL> m . add_measurement ( object_name , I . M_LOCATION_CENTER_Y , center_y ) <EOL> m . add_measurement ( object_name , M_ANGLE , angles * <NUM_LIT> / np . pi ) <EOL> m . add_measurement ( object_name , I . M_NUMBER_OBJECT_NUMBER , label_indexes ) <EOL> m . add_image_measurement ( I . FF_COUNT % object_name , nlabels ) <EOL> object_set = workspace . object_set <EOL> assert isinstance ( object_set , cpo . ObjectSet ) <EOL> objects = cpo . Objects ( ) <EOL> objects . segmented = labels <EOL> objects . parent_image = image <EOL> object_set . add_objects ( objects , object_name ) <EOL> if self . show_window : <EOL> workspace . display_data . i = center_y <EOL> workspace . display_data . j = center_x <EOL> workspace . display_data . angle = angles <EOL> workspace . display_data . mask = mask <EOL> workspace . display_data . labels = labels <EOL> workspace . display_data . count = nlabels <EOL> def display ( self , workspace , figure ) : <EOL> '''<STR_LIT>''' <EOL> import matplotlib <EOL> import cellprofiler . gui . cpfigure <EOL> figure . set_subplots ( ( <NUM_LIT:2> , <NUM_LIT:1> ) ) <EOL> assert isinstance ( figure , cellprofiler . gui . cpfigure . CPFigureFrame ) <EOL> i = workspace . display_data . i <EOL> j = workspace . display_data . j <EOL> angles = workspace . display_data . angle <EOL> mask = workspace . display_data . mask <EOL> labels = workspace . display_data . labels <EOL> count = workspace . display_data . count <EOL> color_image = np . zeros ( ( mask . shape [ <NUM_LIT:0> ] , mask . shape [ <NUM_LIT:1> ] , <NUM_LIT:4> ) ) <EOL> color_image [ mask , : ] = MASK_ALPHA <EOL> if count > <NUM_LIT:0> : <EOL> mappable = matplotlib . cm . ScalarMappable ( <EOL> cmap = matplotlib . cm . get_cmap ( cpprefs . get_default_colormap ( ) ) ) <EOL> np . random . seed ( <NUM_LIT:0> ) <EOL> colors = mappable . to_rgba ( np . random . permutation ( np . arange ( count ) ) ) <EOL> color_image [ labels > <NUM_LIT:0> , : ] += colors [ labels [ labels > <NUM_LIT:0> ] - <NUM_LIT:1> , : ] * LABEL_ALPHA <EOL> lcolors = colors * <NUM_LIT> + <NUM_LIT> <EOL> for ii in range ( count ) : <EOL> diamond = self . get_diamond ( angles [ ii ] ) <EOL> hshape = ( ( np . array ( diamond . shape ) - <NUM_LIT:1> ) / <NUM_LIT:2> ) . astype ( int ) <EOL> iii = i [ ii ] <EOL> jjj = j [ ii ] <EOL> color_image [ iii - hshape [ <NUM_LIT:0> ] : iii + hshape [ <NUM_LIT:0> ] + <NUM_LIT:1> , <EOL> jjj - hshape [ <NUM_LIT:1> ] : jjj + hshape [ <NUM_LIT:1> ] + <NUM_LIT:1> , : ] [ diamond , : ] += lcolors [ ii , : ] * WORM_ALPHA <EOL> color_image [ : , : , - <NUM_LIT:1> ] [ color_image [ : , : , - <NUM_LIT:1> ] == <NUM_LIT:0> ] = <NUM_LIT:1> <EOL> color_image [ : , : , : - <NUM_LIT:1> ] = ( color_image [ : , : , : - <NUM_LIT:1> ] / <EOL> color_image [ : , : , - <NUM_LIT:1> ] [ : , : , np . newaxis ] ) <EOL> plot00 = figure . subplot_imshow_bw ( <NUM_LIT:0> , <NUM_LIT:0> , mask , self . image_name . value ) <EOL> figure . subplot_imshow_color ( <NUM_LIT:1> , <NUM_LIT:0> , color_image [ : , : , : - <NUM_LIT:1> ] , <EOL> title = self . object_name . value , <EOL> normalize = False , <EOL> sharexy = plot00 ) <EOL> def get_diamond ( self , angle ) : <EOL> '''<STR_LIT>''' <EOL> worm_width = self . worm_width . value <EOL> worm_length = self . worm_length . value <EOL> x0 = int ( np . sin ( angle ) * worm_length / <NUM_LIT:2> ) <EOL> x1 = int ( np . cos ( angle ) * worm_width / <NUM_LIT:2> ) <EOL> x2 = - x0 <EOL> x3 = - x1 <EOL> y2 = int ( np . cos ( angle ) * worm_length / <NUM_LIT:2> ) <EOL> y1 = int ( np . sin ( angle ) * worm_width / <NUM_LIT:2> ) <EOL> y0 = - y2 <EOL> y3 = - y1 <EOL> xmax = np . max ( np . abs ( [ x0 , x1 , x2 , x3 ] ) ) <EOL> ymax = np . max ( np . abs ( [ y0 , y1 , y2 , y3 ] ) ) <EOL> strel = np . zeros ( ( ymax * <NUM_LIT:2> + <NUM_LIT:1> , <EOL> xmax * <NUM_LIT:2> + <NUM_LIT:1> ) , bool ) <EOL> index , count , i , j = get_line_pts ( np . array ( [ y0 , y1 , y2 , y3 ] ) + ymax , <EOL> np . array ( [ x0 , x1 , x2 , x3 ] ) + xmax , <EOL> np . array ( [ y1 , y2 , y3 , y0 ] ) + ymax , <EOL> np . array ( [ x1 , x2 , x3 , x0 ] ) + xmax ) <EOL> strel [ i , j ] = True <EOL> strel = binary_fill_holes ( strel ) <EOL> return strel <EOL> @ staticmethod <EOL> def find_adjacent ( img1 , offset1 , count1 , img2 , offset2 , count2 , first , second ) : <EOL> '''<STR_LIT>''' <EOL> numbering1 = np . zeros ( img1 . shape , int ) <EOL> numbering1 [ img1 ] = np . arange ( count1 ) + offset1 <EOL> numbering2 = np . zeros ( img1 . shape , int ) <EOL> numbering2 [ img2 ] = np . arange ( count2 ) + offset2 <EOL> f = np . zeros ( <NUM_LIT:0> , int ) <EOL> s = np . zeros ( <NUM_LIT:0> , int ) <EOL> for oi in ( - <NUM_LIT:1> , <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> for oj in ( - <NUM_LIT:1> , <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> f1 , s1 = IdentifyDeadWorms . find_adjacent_one ( <EOL> img1 , numbering1 , img2 , numbering2 , oi , oj ) <EOL> f = np . hstack ( ( f , f1 ) ) <EOL> s = np . hstack ( ( s , s1 ) ) <EOL> return np . hstack ( ( first , f ) ) , np . hstack ( ( second , s ) ) <EOL> @ staticmethod <EOL> def find_adjacent_same ( img , offset , count , first , second ) : <EOL> '''<STR_LIT>''' <EOL> numbering = np . zeros ( img . shape , int ) <EOL> numbering [ img ] = np . arange ( count ) + offset <EOL> f = np . zeros ( <NUM_LIT:0> , int ) <EOL> s = np . zeros ( <NUM_LIT:0> , int ) <EOL> for oi in ( <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> for oj in ( <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> f1 , s1 = IdentifyDeadWorms . find_adjacent_one ( <EOL> img , numbering , img , numbering , oi , oj ) <EOL> f = np . hstack ( ( f , f1 ) ) <EOL> s = np . hstack ( ( s , s1 ) ) <EOL> return np . hstack ( ( first , f ) ) , np . hstack ( ( second , s ) ) <EOL> @ staticmethod <EOL> def find_adjacent_one ( img1 , numbering1 , img2 , numbering2 , oi , oj ) : <EOL> '''<STR_LIT>''' <EOL> i1 , i2 = IdentifyDeadWorms . get_slices ( oi ) <EOL> j1 , j2 = IdentifyDeadWorms . get_slices ( oj ) <EOL> match = img1 [ i1 , j1 ] & img2 [ i2 , j2 ] <EOL> return numbering1 [ i1 , j1 ] [ match ] , numbering2 [ i2 , j2 ] [ match ] <EOL> def find_adjacent_by_distance ( self , i , j , a ) : <EOL> '''<STR_LIT>''' <EOL> if len ( i ) < <NUM_LIT:2> : <EOL> return np . zeros ( len ( i ) , int ) , np . zeros ( len ( i ) , int ) <EOL> if self . wants_automatic_distance : <EOL> space_distance = self . worm_width . value <EOL> angle_distance = np . arctan2 ( self . worm_width . value , <EOL> self . worm_length . value ) <EOL> angle_distance += np . pi / self . angle_count . value <EOL> else : <EOL> space_distance = self . space_distance . value <EOL> angle_distance = self . angular_distance . value * <NUM_LIT> / np . pi <EOL> order = np . lexsort ( ( a , j , i ) ) <EOL> i = i [ order ] <EOL> j = j [ order ] <EOL> a = a [ order ] <EOL> breakpoint = np . hstack ( ( [ False ] , i [ <NUM_LIT:1> : ] - i [ : - <NUM_LIT:1> ] > space_distance ) ) <EOL> if np . all ( ~ breakpoint ) : <EOL> first , second = np . mgrid [ <NUM_LIT:0> : len ( i ) , <NUM_LIT:0> : len ( i ) ] <EOL> else : <EOL> segment_number = np . cumsum ( breakpoint ) <EOL> member_count = np . bincount ( segment_number ) <EOL> member_idx = np . hstack ( ( [ <NUM_LIT:0> ] , np . cumsum ( member_count [ : - <NUM_LIT:1> ] ) ) ) <EOL> segment_start = member_idx [ segment_number ] <EOL> cross_size = member_count ** <NUM_LIT:2> <EOL> segment_idx = np . cumsum ( cross_size ) <EOL> first_start_idx = np . cumsum ( member_count [ segment_number [ : - <NUM_LIT:1> ] ] ) <EOL> first = np . zeros ( segment_idx [ - <NUM_LIT:1> ] , int ) <EOL> first [ first_start_idx ] = <NUM_LIT:1> <EOL> first = np . cumsum ( first ) <EOL> first_start_idx = np . hstack ( ( [ <NUM_LIT:0> ] , first_start_idx ) ) <EOL> second = ( np . arange ( len ( first ) ) - <EOL> first_start_idx [ first ] + segment_start [ first ] ) <EOL> mask = ( ( np . abs ( ( i [ first ] - i [ second ] ) ** <NUM_LIT:2> + <EOL> ( j [ first ] - j [ second ] ) ** <NUM_LIT:2> ) <= space_distance ** <NUM_LIT:2> ) & <EOL> ( ( np . abs ( a [ first ] - a [ second ] ) <= angle_distance ) | <EOL> ( a [ first ] + np . pi - a [ second ] <= angle_distance ) | <EOL> ( a [ second ] + np . pi - a [ first ] <= angle_distance ) ) ) <EOL> return order [ first [ mask ] ] , order [ second [ mask ] ] <EOL> @ staticmethod <EOL> def get_slices ( offset ) : <EOL> '''<STR_LIT>''' <EOL> if offset > <NUM_LIT:0> : <EOL> s0 , s1 = slice ( <NUM_LIT:0> , - offset ) , slice ( offset , np . iinfo ( int ) . max ) <EOL> elif offset < <NUM_LIT:0> : <EOL> s1 , s0 = IdentifyDeadWorms . get_slices ( - offset ) <EOL> else : <EOL> s0 = s1 = slice ( <NUM_LIT:0> , np . iinfo ( int ) . max ) <EOL> return s0 , s1 <EOL> def get_measurement_columns ( self , pipeline ) : <EOL> '''<STR_LIT>''' <EOL> object_name = self . object_name . value <EOL> return [ ( object_name , I . M_LOCATION_CENTER_X , cpmeas . COLTYPE_INTEGER ) , <EOL> ( object_name , I . M_LOCATION_CENTER_Y , cpmeas . COLTYPE_INTEGER ) , <EOL> ( object_name , M_ANGLE , cpmeas . COLTYPE_FLOAT ) , <EOL> ( object_name , I . M_NUMBER_OBJECT_NUMBER , cpmeas . COLTYPE_INTEGER ) , <EOL> ( cpmeas . IMAGE , I . FF_COUNT % object_name , cpmeas . COLTYPE_INTEGER ) ] <EOL> def get_categories ( self , pipeline , object_name ) : <EOL> if object_name == cpmeas . IMAGE : <EOL> return [ I . C_COUNT ] <EOL> elif object_name == self . object_name : <EOL> return [ I . C_LOCATION , I . C_NUMBER , C_WORMS ] <EOL> else : <EOL> return [ ] <EOL> def get_measurements ( self , pipeline , object_name , category ) : <EOL> if object_name == cpmeas . IMAGE and category == I . C_COUNT : <EOL> return [ self . object_name . value ] <EOL> elif object_name == self . object_name : <EOL> if category == I . C_LOCATION : <EOL> return [ I . FTR_CENTER_X , I . FTR_CENTER_Y ] <EOL> elif category == I . C_NUMBER : <EOL> return [ I . FTR_OBJECT_NUMBER ] <EOL> elif category == C_WORMS : <EOL> return [ F_ANGLE ] <EOL> return [ ] <EOL> def upgrade_settings ( self , setting_values , variable_revision_number , <EOL> module_name , from_matlab ) : <EOL> '''<STR_LIT>''' <EOL> if variable_revision_number == <NUM_LIT:1> : <EOL> setting_values = setting_values + [ <EOL> cps . YES , <NUM_LIT:5> , <NUM_LIT:30> ] <EOL> variable_revision_number = <NUM_LIT:2> <EOL> return setting_values , variable_revision_number , from_matlab </s>
