예제 #1
0
    def _make_cell_map(self):
        #### Get the cell map according to this ####
        #
        # Pre: Requires both a Nucleus and Membrane map
        # Post: Sets a 'cell_map' in the 'segmentation_images'

        segmentation_images = self.get_data('segmentation_images').set_index(
            'segmentation_label')
        nucid = segmentation_images.loc['Nucleus', 'image_id']
        memid = segmentation_images.loc['Membrane', 'image_id']
        nuc = self.get_image(nucid)
        mem = self.get_image(memid)
        mids = map_image_ids(mem)
        coords = list(zip(mids['x'], mids['y']))
        center = median_id_coordinates(nuc, coords)
        im = mem.copy()
        im2 = mem.copy()
        orig = pd.DataFrame(mem.copy())

        for i, cell_index in enumerate(center.index):
            coord = (center.loc[cell_index]['x'], center.loc[cell_index]['y'])
            mask = flood(im2, (coord[1], coord[0]),
                         connectivity=1,
                         tolerance=0)
            if mask.sum().sum() >= 2000: continue
            im2[mask] = cell_index

        v = map_image_ids(im2, remove_zero=False)
        zeros = v.loc[v['id'] == 0]
        zeros = list(zip(zeros['x'], zeros['y']))
        start = v.loc[v['id'] != 0]
        start = list(zip(start['x'], start['y']))

        c1 = map_image_ids(im2).reset_index().rename(
            columns={'id': 'cell_index_1'})
        c2 = map_image_ids(im2).reset_index().rename(
            columns={'id': 'cell_index_2'})
        overlap = c1.merge(c2, on=['x',
                                   'y']).query('cell_index_1!=cell_index_2')
        if overlap.shape[0] > 0: raise ValueError("need to handle overlap")

        #print("DONE FILLING IN")
        cell_map_id = uuid4().hex
        self._images[cell_map_id] = im2.copy()
        increment = self.get_data('segmentation_images').index.max() + 1
        extra = pd.DataFrame(
            pd.Series(
                dict({
                    'db_id': increment,
                    'segmentation_label': 'cell_map',
                    'image_id': cell_map_id
                }))).T
        extra = pd.concat(
            [self.get_data('segmentation_images'),
             extra.set_index('db_id')])
        self.set_data('segmentation_images', extra)
예제 #2
0
    def make_cell_image(self):
        """
        Requires the 'cell_model' be set by **\*.set_cell_model(model)**

        Sets properties:
            - cell_image (numpy.array)
            - nucleus_image (numpy.array)
            - edge_image (numpy.array)
            - processed_image (numpy.array)

        Returns:
            - cell_image
            - edge_image
            - processed_image
        """
        if self.cell_model is None:
            raise ValueError("cell_model is required to be set. see the method .set_cell_model(model)")
        nuc = np.zeros(self.shape).astype(np.uint32)
        # Initialize the image to a pixel at the centroid
        for index,row in self.cell_model.cells.iterrows():
            #print((index,list(row.index)))
            nuc[row['y']][row['x']] = index
        nuc1 = nuc.copy() # work on the cell_image
        nuc2 = nuc.copy() # work on the nucleus_image
        sys.stderr.write("Making cell image\n")
        _total_count = self.cell_model.cells.shape[0]
        # Preserve a point list of the non-centroid points that we can watershed into.
        finish = map_image_ids(nuc1,remove_zero=False).query('id==0').apply(lambda x: (x['x'],x['y']),1)
        if finish.shape[0]==0: finish = []
        for index,row in self.cell_model.cells.iterrows():
            sys.stderr.write("Making cell "+str(index)+" of "+str(_total_count)+"         \r")
            start = [(row['x'],row['y'])] # Shared starting point

            # Fill in the cell_image
            nuc1 = watershed_image(nuc1,list(start),list(finish),fill_value=row.name,steps=self.cell_steps,border=0)

            # Fill in the nucleus
            nuc2 = watershed_image(nuc2,list(start),list(finish),fill_value=row.name,steps=math.ceil(self.cell_steps/4),border=0)

        sys.stderr.write("\n")
        self.nucleus_image = nuc2
        self.cell_image = nuc1
        self.edge_image = image_edges(nuc1)

        # Work on the processed image starting from the cell_image
        start = map_image_ids(nuc1,remove_zero=False).query('id!=0').apply(lambda x: (x['x'],x['y']),1)
        finish = map_image_ids(nuc1,remove_zero=False).query('id==0').apply(lambda x: (x['x'],x['y']),1)
        if start.shape[0]==0: start = []
        if finish.shape[0]==0: finish = []
        temp = watershed_image(nuc1,list(start),list(finish),steps=self.boundary_steps,border=0)
        self.processed_image = temp.astype(np.bool).astype(np.uint8)
        return
 def edge_map(self):
     """
     Return a dataframe of cells by ID's of coordinates only on the edge of the cells
     """
     if 'edge_map' not in list(
             self.get_data('segmentation_images')['segmentation_label']):
         return None
     cmid = self.get_data('segmentation_images').set_index(
         'segmentation_label').loc['edge_map', 'image_id']
     return map_image_ids(self.get_image(cmid)).\
                rename(columns={'id':'cell_index'})
 def cell_map(self):
     """
     Return a dataframe of cell ID's and locations
     """
     if 'cell_map' not in list(
             self.get_data('segmentation_images')['segmentation_label']):
         return None
     cmid = self.get_data('segmentation_images').set_index(
         'segmentation_label').loc['cell_map', 'image_id']
     return map_image_ids(
         self.get_image(cmid)).rename(columns={'id': 'cell_index'})
예제 #5
0
 def get_coordinates(self):
     if self._coordinates is not None: return self._coordinates
     df = self.set_index(self.cdf.frame_columns+['shape']).stack().\
         reset_index().rename(columns={'level_7':'image_type',0:'image'}).\
         set_index(self.cdf.frame_columns+['shape','image_type'])
     imgs = []
     for i, r in df.iterrows():
         if self.verbose:
             sys.stderr.write("Extracting coordinates from " +
                              str(list(i)) + "\n")
         left = pd.DataFrame([i], columns=df.index.names)
         left['_key'] = 1
         img = map_image_ids(r['image']).groupby('id').apply(
             lambda x: list(zip(*x[['x', 'y']].apply(tuple).tolist())))
         img = img.reset_index().rename(columns={
             'id': 'cell_index',
             0: 'coords'
         })
         img['_key'] = 1
         img = left.merge(img, on='_key').drop(columns='_key')
         imgs.append(img)
     imgs = pd.concat(imgs)
     self._coordinates = imgs
     return imgs
예제 #6
0
    def get_segmentation_map_images(self,
                                    type='edge',
                                    subset_logic=None,
                                    color=None,
                                    watershed_steps=0,
                                    blank=(0, 0, 0, 255)):
        # if subset logic is set only plot those cells
        # if color is set color all cells that color
        if self.verbose: sys.stderr.write("getting segmap " + str(type) + "\n")
        ems = self.get_segmentation_maps(type=type)
        if subset_logic is not None:

            subset = self.cdf.subset(subset_logic)
            ems = ems.merge(subset.loc[:,
                                       subset.frame_columns + ['cell_index']],
                            on=subset.frame_columns + ['cell_index'])
        edf = ems.set_index(list(self.columns))
        imgs = []
        for i, r in self.iterrows():
            imsize = r['shape']
            img = pd.DataFrame(np.zeros(imsize))
            if subset.shape[0] == 0:  # case where there is nothing to do
                if self.verbose:
                    sys.stderr.write("Empty image for this phenotype subset\n")
                imgs.append(list(r) + [img])
                continue
            edfsub = edf.loc[tuple(r)]
            #if self.verbose: sys.stderr.write("make image and fill zeros\n")
            fullx = pd.DataFrame({'x': list(range(0, imsize[1]))})
            fullx['_key'] = 1
            fully = pd.DataFrame({'y': list(range(0, imsize[0]))})
            fully['_key'] = 1
            full = fullx.merge(fully, on='_key').merge(edfsub,
                                                       on=['x', 'y'],
                                                       how='left').fillna(0)
            img = np.array(
                full.pivot(columns='x', index='y',
                           values='cell_index').astype(int))
            #if self.verbose: sys.stderr.write("finished making image and fill zeros\n")
            if watershed_steps > 0:
                # get the zero and nonzero components
                mid = map_image_ids(img, remove_zero=False)
                midzero = list(
                    zip(*mid.query('id==0').copy()[['x', 'y']].apply(
                        tuple).tolist()))
                mid = list(
                    zip(*mid.query('id!=0').copy()[['x', 'y']].apply(
                        tuple).tolist()))
                img = watershed_image(np.array(img),
                                      mid,
                                      midzero,
                                      steps=watershed_steps)
            if color is not None:
                # we need to make a new image thats colored in
                fresh = np.zeros(list(imsize) + [len(color)]).astype(int)
                blank = tuple(list(blank)[0:len(color)])
                fresh[:][:] = blank
                # get our coordinates
                coords = np.array(
                    list(
                        zip(*map_image_ids(img)[['y', 'x']].apply(
                            tuple).tolist())))
                fresh[tuple([*coords.T])] = color
                #for i2,r2 in map_image_ids(img).iterrows():
                #    fresh[r2['y']][r2['x']] = color
                img = fresh
            imgs.append(list(r) + [img])
        imgs = pd.DataFrame(imgs, columns=list(self.columns) + ['image'])
        return imgs
예제 #7
0
    def _make_cell_map_legacy(self):
        from pythologist_image_utilities import flood_fill
        #raise ValueError("legacy")

        segmentation_images = self.get_data('segmentation_images').set_index(
            'segmentation_label')
        nucid = segmentation_images.loc['Nucleus', 'image_id']
        nuc = self.get_image(nucid)
        nmap = map_image_ids(nuc)

        memid = segmentation_images.loc['Membrane', 'image_id']
        mem = self.get_image(memid)
        mem = pd.DataFrame(mem).astype(float).applymap(lambda x: 9999999
                                                       if x > 0 else x)
        mem = np.array(mem)
        points = self.get_data('cells')[['x', 'y']]
        #points = points.loc[points.index.isin(nmap['id'])] # we may need this .. not sure
        output = np.zeros(mem.shape).astype(int)
        for cell_index, v in points.iterrows():
            xi = v['x']
            yi = v['y']
            nums = flood_fill(mem,
                              xi,
                              yi,
                              lambda x: x != 0,
                              max_depth=1000,
                              border_trim=1)
            if len(nums) >= 2000: continue
            for num in nums:
                if output[num[1]][num[0]] != 0:
                    sys.stderr.write("Warning: skipping cell index overalap\n")
                    break
                output[num[1]][num[0]] = cell_index
        # Now fill out one point on all non-zeros into the zeros with watershed
        v = map_image_ids(output, remove_zero=False)
        zeros = v.loc[v['id'] == 0]
        zeros = list(zip(zeros['x'], zeros['y']))
        start = v.loc[v['id'] != 0]
        start = list(zip(start['x'], start['y']))
        output = watershed_image(output, start, zeros, steps=1,
                                 border=1).astype(int)
        # Now we need to clean up the image
        # Try to identify cells that are overlapping the processed image
        if self.processed_image_id is not None:
            ci = map_image_ids(output, remove_zero=False)
            pi = map_image_ids(self.processed_image, remove_zero=False)
            mi = ci.merge(pi, on=['x', 'y'])
            bad = mi.loc[(mi['id_y'] == 0) & (mi['id_x'] != 0),
                         'id_x'].unique()  # find the bad
            #if self.verbose: sys.stderr.write("Removing "+str(bad.shape)+" bad points")
            mi.loc[mi['id_x'].isin(bad), 'id_x'] = 0  # set the bad to zero
            output = np.array(mi.pivot(columns='x', index='y', values='id_x'))

        cell_map_id = uuid4().hex
        self._images[cell_map_id] = output.copy()
        increment = self.get_data('segmentation_images').index.max() + 1
        extra = pd.DataFrame(
            pd.Series(
                dict({
                    'db_id': increment,
                    'segmentation_label': 'cell_map',
                    'image_id': cell_map_id
                }))).T
        extra = pd.concat(
            [self.get_data('segmentation_images'),
             extra.set_index('db_id')])
        self.set_data('segmentation_images', extra)