epicure.concatenate_movie

  1import napari
  2from napari import current_viewer
  3from magicgui import magicgui
  4from napari.utils.history import get_save_history 
  5import pathlib
  6import epicure.Utils as ut
  7import numpy as np
  8import os
  9from skimage.measure import regionprops_table
 10
 11from epicure.epicuring import EpiCure
 12from epicure.tracking import Tracking
 13
 14
 15"""
 16    Concatenate temporally two epicured movies (the intensity movie and the labels).
 17    The last frame of the first movie should be the same as the first frame of the second movie.
 18"""
 19    
 20def merge_epicures( first_movie, first_labels, second_movie, second_labels, fullname="fullmovie.tif" ):
 21    """ Do the concatenation """
 22
 23    ## open the two intensity movies
 24    ut.show_info("Reading and concatenating the intensity movies...")
 25    
 26    print("Reading first movie and EpiCure files")
 27    ## open the first movie and epicure data
 28    first_epicure = EpiCure()
 29    first_epicure.viewer = napari.Viewer(show=False)
 30    first_epicure.load_movie( first_movie )
 31    first_epicure.go_epicure( "epics", first_labels )
 32
 33    ## open the second movie
 34    print("Reading second movie and EpiCure files")
 35    second_epicure = EpiCure()
 36    second_epicure.viewer = napari.Viewer(show=False)
 37    second_epicure.load_movie( second_movie )
 38    second_epicure.go_epicure( "epics", second_labels )
 39    
 40    ## check that the last frame of first movie and first frame of second are the same
 41    if np.sum(first_epicure.img[first_epicure.nframes-1] - second_epicure.img[0]) != 0:
 42        ut.show_error("Error: the last frame of first movie is not the same of the first frame of the second movie, I cannot concatenate them.")
 43        return
 44    
 45    ## create the full movie
 46    full_mov = np.concatenate( (first_epicure.img, second_epicure.img[1:]), axis=0 )
 47    full_movie_name = os.path.join(os.path.dirname(first_epicure.imgpath), fullname) 
 48    ut.writeTif( full_mov, full_movie_name, first_epicure.epi_metadata["ScaleXY"], first_epicure.img.dtype, what="Full movie") 
 49    print("Full movie created")
 50
 51    ###### Read and merge the EpiCure data and merge the movie labels
 52    ut.show_info("Reading and concatenating the Epicured results...")
 53
 54    ### Create new EpiCure instance with the full movie
 55    epic = EpiCure()
 56    epic.viewer = napari.current_viewer()
 57    epic.load_movie(full_movie_name)
 58    epic.verbose = 1
 59    epic.set_names( "epics" )
 60    
 61    ## initialize groups to first movie groups
 62    epic.groups = first_epicure.groups
 63    
 64    ## initialize tracks to first movie tracks
 65    epic.tracking = Tracking(epic.viewer, epic)
 66    epic.tracking.track_data = first_epicure.tracking.track_data
 67
 68    ## initialize track graph to first movie graph
 69    if first_epicure.tracking.graph is not None:
 70        epic.tracking.graph = first_epicure.tracking.graph
 71    else:
 72        epic.tracking.graph = {}
 73
 74    ### Now, work on the labels
 75        
 76    ## track between last and first frame to associate the labels (can be a little different if corrections were done)
 77    parent_labels, labels = ut.match_labels( first_epicure.seg[first_epicure.nframes-1], second_epicure.seg[0] )
 78        
 79    #### Update all the labels in the second movie to match with the first movie
 80    nextlabels = first_epicure.get_free_labels(20)  ## prepare a list of unused labels
 81    used_labels = first_epicure.get_labels()
 82    used_labels = used_labels + nextlabels
 83    seconds = np.copy(second_epicure.seg)
 84    seconds_lab = np.unique(seconds)
 85    #second_tracks = np.copy(second_epicure.tracking.track_data)
 86    if second_epicure.tracking.graph is None:
 87        second_epicure.tracking.graph = {}
 88    second_graph = second_epicure.tracking.graph.copy()
 89    ## shift all values and keys in the graph, to be sure it's never the same
 90    shift = np.max(second_epicure.seg)+1
 91    keys = list(second_graph.keys())
 92    for key in keys:
 93        val = second_graph.pop(key)
 94        shift_val = []
 95        for v in val:
 96            shift_val.append(v+shift)
 97        second_graph[key+shift] = shift_val
 98
 99    for lab in seconds_lab:
100        if lab > 0:
101            newlab = None
102            if lab in labels:
103                newlab = parent_labels[labels.index(lab)]
104                #track_indexes = second_epicure.tracking.get_track_indexes( lab )
105                ## Label from second movie has been associated to one from first movie
106                if newlab is not None:
107                    ### If the label is in one group in first or second movie, update its info in full movie
108                    fullmovie_group( epic, newlab, lab, second_epicure )
109                    np.place(second_epicure.seg, seconds==lab, newlab)
110                    #second_tracks[track_indexes, 0] = newlab
111            if newlab is None:
112                ## Label is a new cell (not present in first movie)
113                nextlabel = nextlabels.pop(0)
114                np.place(second_epicure.seg, seconds==lab, nextlabel)
115                newlab = nextlabel
116                #second_tracks[track_indexes, 0] = nextlabel
117                ### add group information if there is one
118                if second_epicure.groups is not None:
119                    second = second_epicure.find_group( lab )
120                    if second is not None:
121                        epic.cells_ingroup( [nextlabel], second )
122                if len(nextlabels) <= 0:
123                    ## the list of unused labels has been completly used, regenerates
124                    nextlabels = ut.get_free_labels( used_labels, 20 )
125                    used_labels = used_labels + nextlabels
126
127            # add division or merge if lab is in second movie graph
128            if (shift+lab) in second_graph.keys():
129                second_graph[newlab] = second_graph[shift+lab]
130            for key, vals in second_graph.items():
131                new_vals = []
132                for val in vals:
133                    if (shift+lab) == val:
134                        new_vals.append( newlab )
135                    else:
136                        new_vals.append( val )
137                second_graph[key] = new_vals
138
139    ### merge the two graphs
140    for key, vals in second_graph.items():
141        if key not in epic.tracking.graph.keys():
142            epic.tracking.graph[key] = vals
143        else:
144            print("Key "+str(key)+" present in both graph, something might be wrong ")
145
146    ### Ok, save the results
147    full_lab = np.concatenate( (first_epicure.seg, second_epicure.seg[1:]), axis=0 )
148    epic.seg = full_lab
149    epic.save_epicures()
150    print("Movie and EpiCure files merged; Suspects/Events (if any) are not merged, use inspect tracks on merged movie to generate them")
151
152def fullmovie_group( epic, first_label, second_label, second_epicure ):
153    """ Check if second_label is in a group, and add it to full movie groups if relevant """
154    first_group = epic.find_group( first_label )
155    second = None
156    if second_epicure.groups is not None:
157        second = second_epicure.find_group( second_label )
158    if (first_group is not None) and (second is not None):
159        ### label is present in the two movie groups
160        if first_group != second:
161            print("Label "+str(first_label)+" classified in group "+(first_group)+" in the first movie and in group "+second+" in the second movie")
162            print("Keep only the first movie group: "+first_group)
163    else:
164        if second is not None:
165            epic.cells_ingroup( [first_label], second )
166
167def concatenate_movies():
168    hist = get_save_history()
169    cdir = hist[0]
170    viewer = current_viewer()
171
172    def choose_first_movie():
173        """ First movie is chosen, suggest default labels file """
174        first = get_files.first_movie.value
175        imgname, imgdir, out = ut.extract_names( first, "epics", mkdir=False )
176        get_files.first_labels.value = pathlib.Path(out)
177        labname = ut.suggest_segfile(out, imgname)
178        if labname is not None:
179            get_files.first_labels.value = pathlib.Path(labname)
180    
181    def choose_second_movie():
182        """ Second movie is chosen, suggest default labels file """
183        second = get_files.second_movie.value
184        imgname, imgdir, out = ut.extract_names( second, "epics", mkdir=False )
185        get_files.second_labels.value = pathlib.Path(out)
186        labname = ut.suggest_segfile(out, imgname)
187        if labname is not None:
188            get_files.second_labels.value = pathlib.Path(labname)
189    
190    @magicgui(call_button="Concatenate",)
191    def get_files(
192            first_movie = pathlib.Path(cdir),
193            first_labels = pathlib.Path(cdir),
194            second_movie = pathlib.Path(cdir),
195            second_labels = pathlib.Path(cdir),
196            merged_movie_name = "fullmovie.tif"
197            ):
198        merge_epicures( first_movie, first_labels, second_movie, second_labels, merged_movie_name)
199        return
200    
201    get_files.first_movie.changed.connect(choose_first_movie)
202    get_files.second_movie.changed.connect(choose_second_movie)
203    return get_files
def merge_epicures( first_movie, first_labels, second_movie, second_labels, fullname='fullmovie.tif'):
 21def merge_epicures( first_movie, first_labels, second_movie, second_labels, fullname="fullmovie.tif" ):
 22    """ Do the concatenation """
 23
 24    ## open the two intensity movies
 25    ut.show_info("Reading and concatenating the intensity movies...")
 26    
 27    print("Reading first movie and EpiCure files")
 28    ## open the first movie and epicure data
 29    first_epicure = EpiCure()
 30    first_epicure.viewer = napari.Viewer(show=False)
 31    first_epicure.load_movie( first_movie )
 32    first_epicure.go_epicure( "epics", first_labels )
 33
 34    ## open the second movie
 35    print("Reading second movie and EpiCure files")
 36    second_epicure = EpiCure()
 37    second_epicure.viewer = napari.Viewer(show=False)
 38    second_epicure.load_movie( second_movie )
 39    second_epicure.go_epicure( "epics", second_labels )
 40    
 41    ## check that the last frame of first movie and first frame of second are the same
 42    if np.sum(first_epicure.img[first_epicure.nframes-1] - second_epicure.img[0]) != 0:
 43        ut.show_error("Error: the last frame of first movie is not the same of the first frame of the second movie, I cannot concatenate them.")
 44        return
 45    
 46    ## create the full movie
 47    full_mov = np.concatenate( (first_epicure.img, second_epicure.img[1:]), axis=0 )
 48    full_movie_name = os.path.join(os.path.dirname(first_epicure.imgpath), fullname) 
 49    ut.writeTif( full_mov, full_movie_name, first_epicure.epi_metadata["ScaleXY"], first_epicure.img.dtype, what="Full movie") 
 50    print("Full movie created")
 51
 52    ###### Read and merge the EpiCure data and merge the movie labels
 53    ut.show_info("Reading and concatenating the Epicured results...")
 54
 55    ### Create new EpiCure instance with the full movie
 56    epic = EpiCure()
 57    epic.viewer = napari.current_viewer()
 58    epic.load_movie(full_movie_name)
 59    epic.verbose = 1
 60    epic.set_names( "epics" )
 61    
 62    ## initialize groups to first movie groups
 63    epic.groups = first_epicure.groups
 64    
 65    ## initialize tracks to first movie tracks
 66    epic.tracking = Tracking(epic.viewer, epic)
 67    epic.tracking.track_data = first_epicure.tracking.track_data
 68
 69    ## initialize track graph to first movie graph
 70    if first_epicure.tracking.graph is not None:
 71        epic.tracking.graph = first_epicure.tracking.graph
 72    else:
 73        epic.tracking.graph = {}
 74
 75    ### Now, work on the labels
 76        
 77    ## track between last and first frame to associate the labels (can be a little different if corrections were done)
 78    parent_labels, labels = ut.match_labels( first_epicure.seg[first_epicure.nframes-1], second_epicure.seg[0] )
 79        
 80    #### Update all the labels in the second movie to match with the first movie
 81    nextlabels = first_epicure.get_free_labels(20)  ## prepare a list of unused labels
 82    used_labels = first_epicure.get_labels()
 83    used_labels = used_labels + nextlabels
 84    seconds = np.copy(second_epicure.seg)
 85    seconds_lab = np.unique(seconds)
 86    #second_tracks = np.copy(second_epicure.tracking.track_data)
 87    if second_epicure.tracking.graph is None:
 88        second_epicure.tracking.graph = {}
 89    second_graph = second_epicure.tracking.graph.copy()
 90    ## shift all values and keys in the graph, to be sure it's never the same
 91    shift = np.max(second_epicure.seg)+1
 92    keys = list(second_graph.keys())
 93    for key in keys:
 94        val = second_graph.pop(key)
 95        shift_val = []
 96        for v in val:
 97            shift_val.append(v+shift)
 98        second_graph[key+shift] = shift_val
 99
100    for lab in seconds_lab:
101        if lab > 0:
102            newlab = None
103            if lab in labels:
104                newlab = parent_labels[labels.index(lab)]
105                #track_indexes = second_epicure.tracking.get_track_indexes( lab )
106                ## Label from second movie has been associated to one from first movie
107                if newlab is not None:
108                    ### If the label is in one group in first or second movie, update its info in full movie
109                    fullmovie_group( epic, newlab, lab, second_epicure )
110                    np.place(second_epicure.seg, seconds==lab, newlab)
111                    #second_tracks[track_indexes, 0] = newlab
112            if newlab is None:
113                ## Label is a new cell (not present in first movie)
114                nextlabel = nextlabels.pop(0)
115                np.place(second_epicure.seg, seconds==lab, nextlabel)
116                newlab = nextlabel
117                #second_tracks[track_indexes, 0] = nextlabel
118                ### add group information if there is one
119                if second_epicure.groups is not None:
120                    second = second_epicure.find_group( lab )
121                    if second is not None:
122                        epic.cells_ingroup( [nextlabel], second )
123                if len(nextlabels) <= 0:
124                    ## the list of unused labels has been completly used, regenerates
125                    nextlabels = ut.get_free_labels( used_labels, 20 )
126                    used_labels = used_labels + nextlabels
127
128            # add division or merge if lab is in second movie graph
129            if (shift+lab) in second_graph.keys():
130                second_graph[newlab] = second_graph[shift+lab]
131            for key, vals in second_graph.items():
132                new_vals = []
133                for val in vals:
134                    if (shift+lab) == val:
135                        new_vals.append( newlab )
136                    else:
137                        new_vals.append( val )
138                second_graph[key] = new_vals
139
140    ### merge the two graphs
141    for key, vals in second_graph.items():
142        if key not in epic.tracking.graph.keys():
143            epic.tracking.graph[key] = vals
144        else:
145            print("Key "+str(key)+" present in both graph, something might be wrong ")
146
147    ### Ok, save the results
148    full_lab = np.concatenate( (first_epicure.seg, second_epicure.seg[1:]), axis=0 )
149    epic.seg = full_lab
150    epic.save_epicures()
151    print("Movie and EpiCure files merged; Suspects/Events (if any) are not merged, use inspect tracks on merged movie to generate them")

Do the concatenation

def fullmovie_group(epic, first_label, second_label, second_epicure):
153def fullmovie_group( epic, first_label, second_label, second_epicure ):
154    """ Check if second_label is in a group, and add it to full movie groups if relevant """
155    first_group = epic.find_group( first_label )
156    second = None
157    if second_epicure.groups is not None:
158        second = second_epicure.find_group( second_label )
159    if (first_group is not None) and (second is not None):
160        ### label is present in the two movie groups
161        if first_group != second:
162            print("Label "+str(first_label)+" classified in group "+(first_group)+" in the first movie and in group "+second+" in the second movie")
163            print("Keep only the first movie group: "+first_group)
164    else:
165        if second is not None:
166            epic.cells_ingroup( [first_label], second )

Check if second_label is in a group, and add it to full movie groups if relevant

def concatenate_movies():
168def concatenate_movies():
169    hist = get_save_history()
170    cdir = hist[0]
171    viewer = current_viewer()
172
173    def choose_first_movie():
174        """ First movie is chosen, suggest default labels file """
175        first = get_files.first_movie.value
176        imgname, imgdir, out = ut.extract_names( first, "epics", mkdir=False )
177        get_files.first_labels.value = pathlib.Path(out)
178        labname = ut.suggest_segfile(out, imgname)
179        if labname is not None:
180            get_files.first_labels.value = pathlib.Path(labname)
181    
182    def choose_second_movie():
183        """ Second movie is chosen, suggest default labels file """
184        second = get_files.second_movie.value
185        imgname, imgdir, out = ut.extract_names( second, "epics", mkdir=False )
186        get_files.second_labels.value = pathlib.Path(out)
187        labname = ut.suggest_segfile(out, imgname)
188        if labname is not None:
189            get_files.second_labels.value = pathlib.Path(labname)
190    
191    @magicgui(call_button="Concatenate",)
192    def get_files(
193            first_movie = pathlib.Path(cdir),
194            first_labels = pathlib.Path(cdir),
195            second_movie = pathlib.Path(cdir),
196            second_labels = pathlib.Path(cdir),
197            merged_movie_name = "fullmovie.tif"
198            ):
199        merge_epicures( first_movie, first_labels, second_movie, second_labels, merged_movie_name)
200        return
201    
202    get_files.first_movie.changed.connect(choose_first_movie)
203    get_files.second_movie.changed.connect(choose_second_movie)
204    return get_files