epicure.concatenate_movie

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