Пример #1
0
def get_pore(img, percentile=75,edge_object_margin=1):
    """Extracts largest, non-border, darkest region from subimage - in context presumed to be the pore. Works out the
    values are 0.

    :param img: input image (section of full intensity leaf image with just stomate in it)
    :type img: numpy.ndarray
    :param percentile: the percentile of the intensity histogram below which values will be taken to be dark.
    :type percentile: int
    :param edge_object_margin: the width of border in which objects must lie to be removed as border objects, default = 1
    :return: binary numpy.ndaarray
    """
    dark_level = np.percentile(img, percentile )
    #imshow(img)
    cp = np.copy(img)
    cp[img > dark_level] = 0
    cp[img <= dark_level] = 1
    label_objects, nb_labels = ndimage.label(cp)
    removed = np.copy(label_objects)
    for o in edge_objects(label_objects, margin=edge_object_margin):
        removed[removed == o] = 0
    new_label_objects, new_nb_labels = ndimage.label(removed)
    props = measure.regionprops(new_label_objects, intensity_image=img)
    if len(props) > 0:
        area = max([i.area for i in props])
        biggest = [i for i, j in enumerate(props) if j.area == area]

        index_of_obj_to_keep = biggest[0]
        label_of_obj_to_keep = np.arange(1, new_nb_labels + 1)[index_of_obj_to_keep]
        new_label_objects[new_label_objects != label_of_obj_to_keep] = 0
        final_label_objects, final_nb_labels = ndimage.label(new_label_objects)
        return(final_label_objects)
    else: #no pore
        return(None)
Пример #2
0
def test_prediction_activity(out_dir, calcium_data, logged_ssvm_path, which_gt='gt', feats_unary='feats_pm', feats_pairwise='feats_xcorr_green'):

        img_x, img_y = 512, 512

        logger = pystruct_logger(logged_ssvm_path)
        ssvm = logger.load()
        print ssvm

        print "Build edge graph"
        edges = create_2d_edge_graph(img_x, img_y)

        for sub in calcium_data.subvolumes:

            print 'Preparing output directory for', sub.name
            out_folder = 'test_prediction_activity/%s/' % sub.name
            create_out_path(out_path=out_dir, except_on_exist=False)

            print 'Loading stuff for subvolume', sub.name
            gt = sub.get(which_gt).astype('uint8')
            unary_feats = sub.get(feats_unary)
            pairwise_feats = sub.get(feats_pairwise)
            x_single = (unary_feats, edges, pairwise_feats)
            y_single = gt.reshape(img_x * img_y)

            print "\tPredicting on subvolume"
            pred=ssvm.predict([x_single])
            pred=pred[0].reshape(img_x, img_y)

            print '\tScoring subvolume prediction'
            score = ssvm.score([x_single], [y_single])
            print 'Score on subvolume:', score

            print 'Getting connected components'
            cc_pred, cnt_obj_pred = ndimage.label(pred)
            cc_gt, cnt_obj_gt = ndimage.label(gt)

            print 'cc:', cnt_obj_pred

            print 'Saving vizzzz'
            for cc in xrange(1, cnt_obj_pred + 1):
                label_indices_xy = np.where(cc_pred == cc)
                tmp = np.zeros_like(gt)
                tmp[label_indices_xy] = 1
                tmp = tmp.reshape(img_x * img_y)
                label_indices_rshp = np.where(tmp == 1)
                label_indices_xy = np.asarray(label_indices_xy)
                label_polygons_pppx = sub.mpl_get_polygon_patches(['active_very_certain', 'active_mod_certain', 'uncertain'])
                label_polygons_ppp = sub.mpl_get_polygon_patches(['active_very_certain', 'active_mod_certain'])
                label_polygons_pp = sub.mpl_get_polygon_patches(['active_very_certain'])
                label_polygons = [label_polygons_pp, label_polygons_ppp, label_polygons_pppx]
                roi = Roi(indices=label_indices_rshp, xy=label_indices_xy, subvolume=sub, janelia_id=cc,
                          meta_info='Spike trains of predicted neurons for %s (score: %.02f)' % (sub.name, score))
                fig = roi.plot_like_annotation_labeler(prediction_image=pred, label_polygons=label_polygons)
                plt.savefig(out_dir + '%d.png' % roi.id, dpi=600)
                plt.close()

            plt.imsave(out_dir + 'cc_pred.png', cc_pred)
            plt.imsave(out_dir + 'cc_gt.png', cc_gt)
            print '\n============================================\n'
        print 'Done.'
Пример #3
0
def multithreshold(img,ignore_zeros=True,firstThreshold=20,nrThresholds=5):
    '''
    labeled,N = multithreshold(img, ignore_zeros = True)

    Performs multi thresholding (which is a form of oversegmentation).

    labeled is of the same size and type as img and contains different labels for 
    the N detected objects (the return of this function is  similar to that of scipy.ndimage.label())

    @param img: The input image
    @param ignore_zeros: Don't take zero pixels into account
    '''
    output=numpy.zeros_like(img)
    if ignore_zeros:
        pmin=nonzeromin(img)
    else:
        pmin=img.min()
    thresholds=pmin+firstThreshold+(img.max()-pmin-firstThreshold)//nrThresholds*numpy.arange(nrThresholds)
    Ts=[majority_filter(img>T) for T in thresholds]
    obj_count = 0
    Ts.append(Ts[0]*0)
    labeled0,N0=ndimage.label(Ts[0])
    for T1 in Ts[1:]:
        labeled1,N1=ndimage.label(T1)
        for obj in xrange(N0):
            binimg=(labeled0 == (obj+1))
            objects1=(labeled1*binimg)
            if not objects1.any() or ndimage.label(objects1)[1] == 1:
                obj_count += 1
                output[binimg]=obj_count
        labeled0=labeled1
        N0=N1

    return output,obj_count
Пример #4
0
def remove_small_objects(ar, min_size=64, connectivity=1, in_place=False):
    # Should use `issubdtype` for bool below, but there's a bug in numpy 1.7
    if not (ar.dtype == bool or np.issubdtype(ar.dtype, np.integer)):
        raise TypeError("Only bool or integer image types are supported. "
                        "Got %s." % ar.dtype)

    if in_place:
        out = ar
    else:
        out = ar.copy()

    if min_size == 0:  # shortcut for efficiency
        return out

    if out.dtype == bool:
        selem = nd.generate_binary_structure(ar.ndim, connectivity)
        ccs = np.zeros_like(ar, dtype=np.int32)
        nd.label(ar, selem, output=ccs)
    else:
        ccs = out

    try:
        component_sizes = np.bincount(ccs.ravel())
    except ValueError:
        raise ValueError("Negative value labels are not supported. Try "
                         "relabeling the input with `scipy.ndimage.label` or "
                         "`skimage.morphology.label`.")

    too_small = component_sizes < min_size
    too_small_mask = too_small[ccs]
    out[too_small_mask] = 0

    return out
Пример #5
0
def erode_to_connected(img,d=3,shape=3,rel_size=0.5,min_size=15, single=False):
    """
    erode to structure to specified relative size; safe version, which
    won't collapse to a single pixel with connectivity constraints

    """
    orig_size = np.count_nonzero(img)
    new_size = orig_size
    _,comp = ndimage.label(img)
    if(orig_size <= 0 or comp > 1):
        return img
    prev_img = img.copy()
    count = 0

    # run for d times, but terminate early if the size (relative or
    # absolute) is too small, or the image breaks into multiple pieces
    while new_size > rel_size * orig_size \
          and new_size > min_size \
          and comp < 2 \
          and count < d:
        prev_img = img.copy()
        img = erode(img,shape)
        new_size = np.count_nonzero(img)
        _,comp = ndimage.label(img)
        count += 1
    return prev_img
Пример #6
0
    def remove_small_blobs(img, threshold=1, debug=True):
        '''
        Find blobs/clusters of same label. Only keep blobs with more than threshold elements.
        This can be used for postprocessing.

        :param img: 3D Image
        :param threshold:
        :return:
        '''
        # mask, number_of_blobs = ndimage.label(img, structure=np.ones((3, 3, 3)))  #Also considers diagonal elements for determining if a element belongs to a blob
        mask, number_of_blobs = ndimage.label(img)
        print('Number of blobs before: ' + str(number_of_blobs))
        counts = np.bincount(mask.flatten())  # number of pixels in each blob
        if debug:
            print(counts)

        remove = counts <= threshold
        remove_idx = np.nonzero(remove)[0]  # somehow returns tupple with 1 value -> remove tupple, only keep value

        for idx in remove_idx:
            mask[mask == idx] = 0  # set blobs we remove to 0
        mask[mask > 0] = 1  # set everything else to 1

        if debug:
            mask_after, number_of_blobs_after = ndimage.label(mask)
            print('Number of blobs after: ' + str(number_of_blobs_after))

        return mask
Пример #7
0
def threshold_and_clean_tomo_layer(reconstruction_fbp,recon_thresh, noise_obj_size,min_hole_size,edge_cleaning_iter=None):
    binary_recon=reconstruction_fbp>recon_thresh

    #hard codeed cleaning, grinding sausage...
    binary_recon=img.morphology.binary_erosion(binary_recon,iterations=1)
    binary_recon=img.morphology.binary_dilation(binary_recon,iterations=4)

    
    labeled_img,num_labels=img.label(binary_recon)
    
    print('Cleaning...')
    print('Removing Noise...')
    for ii in np.arange(1,num_labels):
        obj1=np.where(labeled_img==ii)
        if obj1[0].shape[0]<noise_obj_size:
            binary_recon[obj1[0],obj1[1]]=0
    
    
    labeled_img,num_labels=img.label(binary_recon!=1)
    
    print('Closing Holes...')
    for ii in np.arange(1,num_labels):
    
        obj1=np.where(labeled_img==ii)
        if obj1[0].shape[0]>=1 and obj1[0].shape[0]<min_hole_size:
            binary_recon[obj1[0],obj1[1]]=1


    if edge_cleaning_iter is not None:
        binary_recon=img.morphology.binary_erosion(binary_recon,iterations=edge_cleaning_iter)
        binary_recon=img.morphology.binary_dilation(binary_recon,iterations=edge_cleaning_iter)
        
    return binary_recon
Пример #8
0
def threshold_segment(dna, threshold_method="otsu", smooth=None, median_size=5, min_obj_size=2500):
    """
    labeled = threshold_method(dna, threshold_method='otsu',median_size=5,min_obj_size=2500)

    Simple threshold-based segmentation

    Params
    ------
        * dna: either a pyslic.Image or a DNA image
        * threshold_method: thresholding method to use. Can be either a function or 
            string which denotes the name of a function in pyslic.imageprocessing.thresholding (default: otsu)
        * smooth: either None (no smoothing) or a sigma value for a gaussian blur (default: None)
        * median_size: median filter size (default: 5). Set to None to skip filtering.
        * min_obj_size: minimum object size (default: 2500)
    """
    if type(dna) == Image:
        with loadedimage(dna):
            return threshold_segment(dna.get("dna"), threshold_method, smooth, median_size, min_obj_size)
    if smooth is not None:
        dna = ndimage.gaussian_filter(dna, smooth)
    T = threshold(dna, threshold_method)
    binimg = dna > T
    if median_size is not None:
        binimg = majority_filter(binimg, median_size)
    L, N = ndimage.label(binimg)
    if N == 0:
        return L
    sizes = numpy.array(ndimage.sum(binimg, L, numpy.arange(N + 1)))
    for oid in numpy.where(sizes < min_obj_size)[0]:
        L[L == oid] = 0
    L, N = ndimage.label(L != 0)
    return L
Пример #9
0
def get_stomata(max_proj_image, min_obj_size=200, max_obj_size=1000):
    """Performs image segmentation from a max_proj_image.
     Disposes of objects in range min_obj_size to
    max_obj_size

    :param max_proj_image: the maximum projection image
    :type max_proj_image: numpy.ndarray, uint16
    :param min_obj_size: minimum size of object to keep
    :type min_obj_size: int
    :param max_obj_size: maximum size of object to keep
    :type max_obj_size: int
    :returns: list of [ [coordinates of kept objects - list of slice objects],
                        binary object image - numpy.ndarray,
                        labelled object image - numpy.ndarray
                     ]

    """

    # pore_margin = 10
    # max_obj_size = 1000
    # min_obj_size = 200
    # for prop, value in segment_options:
    #     if prop == 'pore_margin':
    #         pore_margin = value
    #     if prop == 'max_obj_size':
    #         max_obj_size = value
    #     if prop == 'min_obj_size':
    #         min_obj_size = value
    #
    # print(pore_margin)
    # print(max_obj_size)
    # print(min_obj_size)

    #rescale_min = 50
    #rescale_max= 100
    #rescaled = exposure.rescale_intensity(max_proj_image, in_range=(rescale_min,rescale_max))
    rescaled = max_proj_image
    seed = np.copy(rescaled)
    seed[1:-1, 1:-1] = rescaled.max()
    #mask = rescaled
    #if gamma != None:
    #    rescaled = exposure.adjust_gamma(max_proj_image, gamma)
    #filled = reconstruction(seed, mask, method='erosion')
    closed = dilation(rescaled)
    seed = np.copy(closed)
    seed[1:-1, 1:-1] = closed.max()
    mask = closed


    filled = reconstruction(seed, mask, method='erosion')
    label_objects, nb_labels = ndimage.label(filled)
    sizes = np.bincount(label_objects.ravel())
    mask_sizes = sizes
    mask_sizes = (sizes > min_obj_size) & (sizes < max_obj_size)
    #mask_sizes = (sizes > 200) & (sizes < 1000)
    mask_sizes[0] = 0
    big_objs = mask_sizes[label_objects]
    stomata, _ = ndimage.label(big_objs)
    obj_slices = ndimage.find_objects(stomata)
    return [obj_slices, big_objs, stomata]
Пример #10
0
def findPlantsCanny(stackVar, stackSum, showImages=True):
    edges = canny(stackVar)
    fill_stack = ndimage.binary_fill_holes(edges)
    label_objects, nb_labels = ndimage.label(fill_stack)
    sizes = np.bincount(label_objects.ravel())
    mask_sizes = sizes > 25
    
    for label in range(len(mask_sizes)):
        '''
        Get rid of lines in addition to the straight size threshold.
        '''
        pts = np.where(label_objects == label)
        xRange = (max(pts[0]) - min(pts[0]))
        yRange = (max(pts[1]) - min(pts[1]))
        areaCovered = float(len(pts[0])) / (xRange*yRange)
        if (areaCovered < .33) or (xRange < 3) or (yRange < 3):
            mask_sizes[label] = False

    mask_sizes[0] = 0
    plants_cleaned = mask_sizes[label_objects]
    labeled_plants, numPlants = ndimage.label(plants_cleaned)
    center = findCenters(labeled_plants, stackSum)
    
    if showImages:
        fig, axs = plt.subplots(1,3, figsize=(14,4), sharey=True)
        axs[0].imshow(stackVar)
        axs[1].imshow(stackVar, cmap=plt.cm.jet, interpolation='nearest') #@UndefinedVariable
        axs[1].contour(plants_cleaned, [0.5], linewidths=1.2, colors='y')
        axs[2].imshow(labeled_plants, cmap=plt.cm.spectral, interpolation='nearest') #@UndefinedVariable
        axs[2].scatter(np.array(center.tolist())[:,1], np.array(center.tolist())[:,0], 
                       color='grey')
        for ax in axs: ax.axis('off')
        fig.subplots_adjust(wspace=.01)
       
    return labeled_plants, center
Пример #11
0
def create_paths(pathimage):
    # shortest path through black then purple then cyan
    arr = np.transpose(pygame.surfarray.array3d(pathimage), [1,0,2])
    maxval = arr.max()
    black = (((arr == 0).sum(axis=2)) == 3)
    print "found %d black pixels"%(black.sum())
    purple = ((arr[:,:,0] == maxval) & (arr[:,:,1] == 0) & (arr[:,:,2] == maxval))
    print "found %d purple pixels"%(purple.sum())
    cyan = ((arr[:,:,0] == 0) & (arr[:,:,1] == maxval) & (arr[:,:,2] == maxval))
    print "found %d cyan pixels"%(cyan.sum())
    white = (((arr == arr.max()).sum(axis=2)) == 3)
    print "found %d white pixels"%(white.sum())


    mask = black | purple | cyan | white

    black_blobs, black_count = ndi.label(black)
    purple_blobs, purple_count = ndi.label(purple)
    cyan_blobs, cyan_count = ndi.label(cyan)

    print black_count, purple_count, cyan_count

    try:
        black_centers, purple_distances, cyan_distances = cPickle.load(open("distances.pickle"))
    except:
        black_centers = ndi.center_of_mass(np.ones(black_blobs.shape), black_blobs, range(1, black_count + 1))
        purple_distances = [masked_distance(purple_blobs == (b + 1), mask) for b in range(purple_count)]
        cyan_distances = [masked_distance(cyan_blobs == (b + 1), mask) for b in range(cyan_count)]
        cPickle.dump((black_centers, purple_distances, cyan_distances), open("distances.pickle", "w"))
    
    return black_centers, [purple_distances, cyan_distances]
Пример #12
0
def skeleton(seg):
    skel, dist = skmorph.medial_axis(seg, return_distance=True)
    node, edge, leaf = (spim.label(g, np.ones((3, 3), bool))[0] for g in skel2graph(skel))

    trim_edge = (edge != 0) & ~(skmorph.binary_dilation(node != 0, np.ones((3, 3), bool)) != 0)
    trim_edge = spim.label(trim_edge, np.ones((3, 3), bool))[0]

    leaf_edge_vals = skmorph.binary_dilation(leaf != 0, np.ones((3, 3), bool)) != 0
    leaf_edge_vals = np.unique(trim_edge[leaf_edge_vals])
    leaf_edge_vals = leaf_edge_vals[leaf_edge_vals > 0]
    leaf_edge = leaf != 0

    trim_edge = ndshm.fromndarray(trim_edge)
    leaf_edge = ndshm.fromndarray(leaf_edge)
    Parallel()(delayed(set_msk)(leaf_edge, trim_edge, l) for l in leaf_edge_vals)
    trim_edge = np.copy(trim_edge)
    leaf_edge = np.copy(leaf_edge)

    leaf_edge[(skmorph.binary_dilation(leaf_edge, np.ones((3, 3), bool)) != 0) & (edge != 0)] = True
    leaf_edge = spim.label(leaf_edge, np.ones((3, 3), bool))[0]

    leaf_edge_node = skmorph.binary_dilation(leaf_edge != 0, np.ones((3, 3), bool)) != 0
    leaf_edge_node = ((node != 0) & leaf_edge_node) | leaf_edge
    leaf_edge_node = spim.label(leaf_edge_node, np.ones((3, 3), bool))[0]

    cand_node = leaf_edge_node * (node != 0)
    cand_node = cand_node.nonzero()
    cand_node = np.transpose((leaf_edge_node[cand_node],) + cand_node + (2 * dist[cand_node],))

    cand_leaf = leaf_edge_node * (leaf != 0)
    cand_leaf = cand_leaf.nonzero()
    cand_leaf = np.transpose((leaf_edge_node[cand_leaf],) + cand_leaf)

    if len(cand_node) > 0 and len(cand_leaf) > 0:
        cand_leaf = ndshm.fromndarray(cand_leaf)
        cand_node = ndshm.fromndarray(cand_node)
        pruned = Parallel()(delayed(prune_leaves)(cand_leaf, cand_node, j) for j in np.unique(cand_node[:, 0]))
        cand_leaf = np.copy(cand_leaf)
        cand_node = np.copy(cand_node)

        pruned_ind = []
        for p in pruned:
            pruned_ind.extend(p)
        pruned_ind = tuple(np.transpose(pruned_ind))

        pruned = ~skel

        pruned = ndshm.fromndarray(pruned)
        leaf_edge = ndshm.fromndarray(leaf_edge)
        Parallel()(delayed(set_msk)(pruned, leaf_edge, l) for l in np.unique(leaf_edge[pruned_ind]))
        pruned = np.copy(pruned)
        leaf_edge = np.copy(leaf_edge)

        pruned = ~pruned
    else:
        pruned = skel

    return pruned
Пример #13
0
    def run(self, workspace):
        objects = workspace.object_set.get_objects(self.objects_name.value)
        assert isinstance(objects, cpo.Objects)
        labels = objects.segmented
        if self.relabel_option == OPTION_SPLIT:
            output_labels, count = scind.label(labels > 0, np.ones((3, 3), bool))
        else:
            if self.unify_option == UNIFY_DISTANCE:
                mask = labels > 0
                if self.distance_threshold.value > 0:
                    #
                    # Take the distance transform of the reverse of the mask
                    # and figure out what points are less than 1/2 of the
                    # distance from an object.
                    #
                    d = scind.distance_transform_edt(~mask)
                    mask = d < self.distance_threshold.value / 2 + 1
                output_labels, count = scind.label(mask, np.ones((3, 3), bool))
                output_labels[labels == 0] = 0
                if self.wants_image:
                    output_labels = self.filter_using_image(workspace, mask)
            elif self.unify_option == UNIFY_PARENT:
                parent_objects = workspace.object_set.get_objects(self.parent_object.value)
                output_labels = parent_objects.segmented.copy()
                output_labels[labels == 0] = 0

        output_objects = cpo.Objects()
        output_objects.segmented = output_labels
        if objects.has_small_removed_segmented:
            output_objects.small_removed_segmented = copy_labels(objects.small_removed_segmented, output_labels)
        if objects.has_unedited_segmented:
            output_objects.unedited_segmented = copy_labels(objects.unedited_segmented, output_labels)
        output_objects.parent_image = objects.parent_image
        workspace.object_set.add_objects(output_objects, self.output_objects_name.value)

        measurements = workspace.measurements
        add_object_count_measurements(measurements, self.output_objects_name.value, np.max(output_objects.segmented))
        add_object_location_measurements(measurements, self.output_objects_name.value, output_objects.segmented)

        #
        # Relate the output objects to the input ones and record
        # the relationship.
        #
        children_per_parent, parents_of_children = objects.relate_children(output_objects)
        measurements.add_measurement(
            self.objects_name.value, FF_CHILDREN_COUNT % self.output_objects_name.value, children_per_parent
        )
        measurements.add_measurement(
            self.output_objects_name.value, FF_PARENT % self.objects_name.value, parents_of_children
        )
        if self.wants_outlines:
            outlines = cellprofiler.cpmath.outline.outline(output_labels)
            outline_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(self.outlines_name.value, outline_image)

        if workspace.frame is not None:
            workspace.display_data.orig_labels = objects.segmented
            workspace.display_data.output_labels = output_objects.segmented
Пример #14
0
def find_peaks(file):
  #read image data
  f=pyfits.open(file)
  img=f[0].data

  #set NaN pixels (empty pixels) to zero
  img[img != img]=0.0
  img[img<0.]=0.0
  if dim==4:
    img=img[0,0,:,:] #gets rid of 3 and 4 dimensions, since FIRST fits files have four axis but only first two have data
    
  T=ndimage.standard_deviation(img)
  sourcelabels,num_sources=ndimage.label(img>T)
  backgroundlabels,num_background=ndimage.label(img<T)
  # define an 8-connected neighbourhood
  neighborhood = generate_binary_structure(2,2)
  fimg=img*sourcelabels
  #apply the local maximum filter; all pixel of maximal value 
  #in their neighbourhood are set to 1
  local_max=maximum_filter(fimg,footprint=neighborhood)==fimg
  #In order to isolate the peaks we must remove the background from the mask.
  #we create the mask of the background
  background=img*backgroundlabels
  #we must erode the background in order to 
  #successfully subtract it form local_max, otherwise a line will 
  #appear along the background border (artifact of the local maximum filter)
  eroded_background=binary_erosion(background,structure=neighborhood,border_value=1)
  
  #we obtain the final mask, containing only peaks, 
  #by removing the background from the local_max mask
  detected_peaks=local_max-eroded_background
  #contains some peaks not in source (background bright features), but code can remove these
  #now need to find positions of these maximum
  #label peaks
  peaklabels,num_peaks=ndimage.measurements.label(detected_peaks)
  
  #get peak positions  
  slices = ndimage.find_objects(peaklabels)
  x, y = [], []
  for dy,dx in slices:
      x_center = (dx.start + dx.stop - 1)/2
      x.append(x_center)
      y_center = (dy.start + dy.stop - 1)/2    
      y.append(y_center)
      
  peak_positions=zip(x,y)
  
  #get peak values, in Jy/beam
  peak_fluxes=[]
  for coord in peak_positions:
      peak_fluxes.append(img[coord[1],coord[0]])
  peaks=zip(peak_positions,peak_fluxes)
  
  #sort by peak_fluxes. Two brightest peaks will be the first two in the list
  peaks=sorted(peaks,key=lambda l: l[1])  
  peaks.reverse()
  return peaks,img,f
Пример #15
0
def test_connect_regions_with_grid():
    lena = sp.lena()
    mask = lena > 50
    graph = grid_to_graph(*lena.shape, **{"mask": mask})
    assert_equal(ndimage.label(mask)[1], cs_graph_components(graph)[0])

    mask = lena > 150
    graph = grid_to_graph(*lena.shape, **{"mask": mask, "dtype": None})
    assert_equal(ndimage.label(mask)[1], cs_graph_components(graph)[0])
Пример #16
0
def split_up_binary_regions(seq_block, opening_param = 3, mshape = ((0,1,0),(1,1,1),(0,1,0)), min_size = 20):

    # for each region:
    #                  dilate, relabel, create stack with eroded single regions
    #                  delete overlapping pixels, recombine, assigning unique labels

    zdim, xdim, ydim = seq_block.shape
    splitblock = np.zeros_like(seq_block)

    for sidx in range(zdim):
        num_labels = int(np.max(seq_block[sidx]))
        if num_labels <= 1:
            continue
        max_label = num_labels
        for lidx in range(num_labels):
            comp = extract_region(seq_block[sidx], lidx+1)
            if np.sum(comp) < min_size:
                continue
            component = ndi.binary_erosion(comp,structure = mshape,iterations = opening_param)
            component, numnewcomponents = ndi.label(component)
            if numnewcomponents == 1:  # component is not split up by erosion
                #component[component>0] = 1
                #component = ndi.binary_dilation(component,structure = mshape,iterations = opening_param)
                splitblock[sidx][comp > 0] = int(lidx+1)
            else:
                compstack = np.zeros((numnewcomponents,xdim,ydim))
                for cidx in range(numnewcomponents):
                    compstack[cidx] = ndi.binary_dilation(extract_region(component, cidx+1),structure = mshape,iterations = opening_param)
                    compstack[cidx] = ndi.binary_dilation(compstack[cidx],structure = ((0,1,0),(1,1,1),(0,1,0)),iterations = 2)
                overlapmask = np.sum(compstack, axis = 0)
                comp[overlapmask > 1] = 0
                comp, numnewcomponents2 = ndi.label(comp)
                #if numnewcomponents != numnewcomponents2:
                    #print "Lost something on the way: C1 = " + str(numnewcomponents) + ", C2 = " + str(numnewcomponents2)

                for cidx in range(numnewcomponents2):
                    component = extract_region(comp, cidx+1)
                    if np.sum(component) < min_size:
                        continue
                    #compstack[cidx] = compstack[cidx] * overlapmask
                    #if np.sum(compstack[cidx]) > 0:
                    max_label = max_label + 1
                    #compstack[cidx] = compstack[cidx] * max_label
                    splitblock[sidx] = splitblock[sidx] + component.astype(int) * int(max_label)

                #splitblock[sidx] = splitblock[sidx] + np.sum(compstack,axis = 0).astype(int)

        # relabel components to unique labels
        all_labels = np.sort(np.unique(splitblock[sidx]))
        dum = np.zeros_like(splitblock[sidx])
        l_idx = 1
        for label in all_labels:
            if label >0:
                dum[splitblock[sidx]==label] = l_idx
                l_idx = l_idx + 1

    return splitblock
Пример #17
0
def isolatefilaments(skel_img, size_threshold, pad_size=5):
  '''
  This function separates each filament, over a threshold of number of
  pixels, into its own array with the same dimensions as the inputed image.

  Parameters
  ----------
  skel_img : numpy.ndarray
             the resultant skeletons from the Medial Axis Transform

  mask : numpy.ndarray
         the binary mask from adaptive thresholding

  size_threshold : int
                   sets the pixel size on the size of objects

  Returns
  -------
  skelton_arrays : list
              contains the individual arrays for each skeleton
  mask : numpy.ndarray
         Updated version of the mask where small objects have been eliminated
  num : int
        Number of filaments
  corners : list
            Contains the indices where each skeleton array was taken from
            the original

  '''

  skeleton_arrays = []; pix_val = []; corners = []
  labels,num = nd.label(skel_img,eight_con())

  sums = nd.sum(skel_img,labels,range(num))
  for n in range(num):
    if sums[n]<size_threshold:
      x,y = np.where(labels==n)
      for i in range(len(x)):
        skel_img[x[i],y[i]]=0

  # Relabel after deleting short skeletons.
  labels,num = nd.label(skel_img,eight_con())
  # Split each skeleton into its own array.
  for n in range(1,num+1):
    x,y = np.where(labels==n)
    # Make an array shaped to the skeletons size and padded on each edge
    shapes = (x.max()-x.min()+2*pad_size, y.max()-y.min()+2*pad_size)
    eachfil = np.zeros(shapes)
    for i in range(len(x)):
      eachfil[x[i]-x.min()+pad_size,y[i]-y.min()+pad_size] = 1
    skeleton_arrays.append(eachfil)
    # Keep the coordinates from the original image
    lower = (x.min()-pad_size,y.min()-pad_size)
    upper = (x.max()+pad_size,y.max()+pad_size)
    corners.append([lower,upper])

  return skeleton_arrays, num, corners
Пример #18
0
def test_connect_regions_with_grid():
    lena = sp.misc.lena()
    mask = lena > 50
    graph = grid_to_graph(*lena.shape, mask=mask)
    assert_equal(ndimage.label(mask)[1], cs_graph_components(graph)[0])

    mask = lena > 150
    graph = grid_to_graph(*lena.shape, mask=mask, dtype=None)
    assert_equal(ndimage.label(mask)[1], cs_graph_components(graph)[0])
Пример #19
0
def test_connect_regions_with_grid():
    lena = sp.lena()
    mask = lena > 50
    graph = grid_to_graph(*lena.shape, **{'mask' : mask})
    nose.tools.assert_equal(ndimage.label(mask)[1],
                            cs_graph_components(graph)[0])

    mask = lena > 150
    graph = grid_to_graph(*lena.shape, **{'mask' : mask, 'dtype' : None})
    nose.tools.assert_equal(ndimage.label(mask)[1],
                            cs_graph_components(graph)[0])
Пример #20
0
def plot_filled(y, ax=None, thresh=None, plot_thresh=True, color='k', lw=2, facecolor='0.8', two_tailed=False, thresh_color='k', autoset_ylim=True, label=None):
	'''
	Plot a filled cluster.
	
	(This function should only be used through **spm1d.plot.plot_spmi**)
	'''
	y        = np.asarray(y, dtype=float)
	x        = _getQ(None, y.size)
	ax       = _gca(ax)
	if thresh==None:
		thresh      = 0
	x0,y0,ind0      = x.copy(), y.copy(), np.arange(y.size)
	### threshold:
	if two_tailed:
		L,n      = ndimage.label(np.abs(y)>thresh)
	else:
		L,n      = ndimage.label(y>thresh)
	### plot:
	ax.plot(x0, y0, color=color, lw=lw, label=label)
	### create patches if needed:
	if n>0:
		polyg = []
		for i in range(n):
			ind         = ind0[L==i+1].tolist()
			x           = x0[L==i+1].tolist()
			y           = y0[L==i+1].tolist()
			csign       = np.sign(y[0])
			### insert extra nodes for interpolation:
			x           = [x[0]] + x + [x[-1]]
			y           = [csign*thresh] + y + [csign*thresh]
			### interpolate if necessary:
			if ind[0]  != ind0[0]:
				dx      = x0[ind[0]] - x0[ind[0]-1]
				dy      = (csign*thresh - y0[ind[0]])  / (y0[ind[0]] - y0[ind[0]-1])
				x[0]   += dy*dx
			if ind[-1] != ind0[-1]:
				dx      = x0[ind[-1]+1] - x0[ind[-1]]
				dy      = (csign*thresh - y0[ind[-1]])  / (y0[ind[-1]+1] - y0[ind[-1]])
				x[-1]  += dy*dx
			polyg.append(  Polygon(list(zip(x,y)))  )
		patches         = PatchCollection(polyg, edgecolors=None)
		ax.add_collection(patches)
		pyplot.setp(patches, facecolor=facecolor, edgecolor=facecolor)
	#set axis limits:
	# pyplot.setp(ax, xlim=(x0.min(), x0.max()), ylim=(y0.min(), y0.max()))
	pyplot.setp(ax, xlim=(x0.min(), x0.max())  )
	#plot threshold(s):
	if (thresh!=None) and plot_thresh:
		h      = [ax.hlines(thresh, x0.min(), x0.max())]
		if two_tailed:
			h.append( ax.hlines(-thresh, x0.min(), x0.max()) )
		pyplot.setp(h, color=thresh_color, lw=1, linestyle='--')
	if autoset_ylim:
		_set_ylim(ax)
Пример #21
0
def find_dead_ends_once(arr):
    """Called by find_dead_ends"""
    Nx, Ny = arr.shape

    # Surround whole grid with border of False values to avoid index errors
    arr = np.append(arr, np.full((Nx, 1), False, dtype=bool), axis=1)
    arr = np.append(arr, np.full((1, Ny + 1), False, dtype=np.bool), axis=0)
    arr = np.insert(arr, 0, False, axis=1)
    arr = np.insert(arr, 0, False, axis=0)

    # Kernels used in convolution to identify possible dead ends
    x_kernel = np.array([[1], [0], [1]])
    y_kernel = np.array([[1, 0, 1]])

    conv_x = convolve(arr, y_kernel, 'same')
    conv_y = convolve(arr, x_kernel, 'same')

    inds_x = np.logical_and(arr, conv_x == 0)
    inds_x_labels, nxlabels = label(inds_x)

    inds_y = np.logical_and(arr, conv_y == 0)
    inds_y_labels, nylabels = label(inds_y)

    # Find inds in first direction
    for i in np.r_[1:nxlabels+1]:
        args_i = np.argwhere(inds_x_labels == i)
        y_inds = args_i[[0, -1], 0] + np.r_[-1, 1]
        x_ind = args_i[0, 1]

        if np.all(arr[y_inds, x_ind]):
            # Not a dead end, water on both sides
            inds_x_labels[inds_x_labels == i] = 0

    inds_x = inds_x_labels > 0

    # Same for second direction
    for i in np.r_[1:nylabels+1]:
        args_i = np.argwhere(inds_y_labels == i)
        y_ind = args_i[0, 0]
        x_inds = args_i[[0, -1], 1] + np.r_[-1, 1]

        if np.all(arr[y_ind, x_inds]):
            # Not a dead end, water on both sides
            inds_y_labels[inds_y_labels == i] = 0

    inds_y = inds_y_labels > 0

    dead_end_inds = np.logical_or(inds_x, inds_y)

    # Account for border of False values added at start
    dead_end_inds = dead_end_inds[1:-1, 1:-1]

    return dead_end_inds
Пример #22
0
def feature_vector_from_rgb(image, sample_size=None):
    """Compute a feature vector from the composite images.

    The channels are assumed to be in the following order:
     - Red: MCF-7
     - Green: cytoplasm GFP
     - Blue: DAPI/Hoechst

    Parameters
    ----------
    im : array, shape (M, N, 3)
        The input image.
    sample_size : int, optional
        For features based on quantiles, sample this many objects
        rather than computing full distribution. This can considerably
        speed up computation with little cost to feature accuracy.

    Returns
    -------
    fs : 1D array of float
        The features of the image.
    names : list of string
        The feature names.
    """
    all_fs, all_names = [], []
    ims = np.rollaxis(image[..., :3], -1, 0) # toss out alpha chan if present
    mcf, cells, nuclei = ims
    prefixes = ['mcf', 'cells', 'nuclei']
    for im, prefix in zip(ims, prefixes):
        fs, names = features.intensity_object_features(im,
                                                       sample_size=sample_size)
        names = [prefix + '-' + name for name in names]
        all_fs.append(fs)
        all_names.extend(names)
    nuclei_mean = nd.label(nuclei > np.mean(nuclei))[0]
    fs, names = features.nearest_neighbors(nuclei_mean)
    all_fs.append(fs)
    all_names.extend(['nuclei-' + name for name in names])
    mcf_mean = nd.label(mcf)[0]
    fs, names = features.fraction_positive(nuclei_mean, mcf_mean,
                                           positive_name='mcf')
    all_fs.append(fs)
    all_names.extend(names)
    cells_t_otsu = cells > threshold_otsu(cells)
    cells_t_adapt = threshold_adaptive(cells, 51)
    fs, names = features.nuclei_per_cell_histogram(nuclei_mean, cells_t_otsu)
    all_fs.append(fs)
    all_names.extend(['otsu-' + name for name in names])
    fs, names = features.nuclei_per_cell_histogram(nuclei_mean, cells_t_adapt)
    all_fs.append(fs)
    all_names.extend(['adapt-' + name for name in names])
    return np.concatenate(all_fs), all_names
Пример #23
0
def _process_B(B):
    L,N = ndimage.label(~B)
    bg = 0
    bg_size = (L==bg).sum()
    for i in xrange(1,N+1):
        i_size = (L == i).sum()
        if i_size > bg_size:
            bg_size = i_size
            bg = i
        if i_size < _min_obj_size:
            L[L==i] = 0 
    L[L==bg]=0
    L,_ = ndimage.label(L!=0)
    return L
Пример #24
0
def test_connect_regions_with_grid():
    try:
        face = sp.face(gray=True)
    except AttributeError:
        # Newer versions of scipy have face in misc
        from scipy import misc
        face = misc.face(gray=True)
    mask = face > 50
    graph = grid_to_graph(*face.shape, mask=mask)
    assert_equal(ndimage.label(mask)[1], connected_components(graph)[0])

    mask = face > 150
    graph = grid_to_graph(*face.shape, mask=mask, dtype=None)
    assert_equal(ndimage.label(mask)[1], connected_components(graph)[0])
Пример #25
0
 def findNeuronsFromStDev(self,applyFilter=False,sigmax=3,sigmay=3,tRange=None,sizeLimit=40,distanceLimit=6):
     stdFrame = np.zeros(np.shape(self.motionCorrectedMovie.mov[0]))
     h,w = np.shape(stdFrame)
     for r in range(h):
         for c in range(w):
             stdFrame[r][c] = np.std(self.motionCorrectedMovie.mov[:,r,c])
     if applyFilter:
         stdFrame = gaussian_filter(stdFrame,[sigmax,sigmay])
     if tRange == None:
         med = np.median(stdFrame)
         stdStd = np.std(stdFrame)
         tRange = [med + 5*stdStd, med + 4*stdStd, med + 3*stdStd, med + 2*stdStd, med + stdStd, med]
     conmat = np.ones((3,3)) #np.array([[0,1,0],[1,1,1],[0,1,0]])
     ntot = 0
     for threshold in tRange:
         stdFrameFree = stdFrame
         for m in self.neuronMasks:
             stdFrameFree = stdFrameFree * (1-(m>0))
         mask = stdFrameFree*(stdFrameFree > threshold)
         mask, n = label(mask > 0, conmat)
         nRejected = 0
         nPruned = 0
         avgPixelsPruned = 0
         for i in range(1,n+1):
             iROI = (mask == i)
             iSize = np.sum(iROI)
             stdROI = iROI * stdFrameFree
             [[rmax],[cmax]] = np.where(stdROI == np.max(stdROI))
             r,c = np.where(iROI == 1)
             for j in range(len(r)):
                 if ((r[j]-rmax)**2 + (c[j]-cmax)**2)**0.5 < distanceLimit:
                     iROI[r[j],c[j]] = 0
             mask = mask * (1-iROI)
             diff = np.sum(iROI)
             iSizePruned = iSize - diff
             if iSizePruned < sizeLimit:
                 iROI = (mask == i)
                 mask = mask * (1-iROI)
                 nRejected = nRejected + 1
             elif diff > 0:
                 nPruned = nPruned + 1
                 avgPixelsPruned = avgPixelsPruned + diff
         avgPixelsPruned = avgPixelsPruned / float(nPruned)
         mask, nfinal = label(mask > 0, conmat)
         self.neuronMasks.append(mask)
         print '%i potential neurons found above threshold %f' % (n,threshold)
         print '%i rejected after pruning for having size < %i' % (nRejected,sizeLimit)
         print '%i kept neurons pruned, average %i pixels removed' % (nPruned,avgPixelsPruned)
         ntot = ntot + n - nRejected
     return ntot
Пример #26
0
def all_alive(board):
    black_groups, black_count = nd.label(board == 1)
    empty_adjacent_count = nd.filters.convolve((board == 0).astype(np.uint8),
                                               np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]),
                                               mode='constant')
    black_adjacent_max = nd.maximum(empty_adjacent_count, black_groups,
                                    np.arange(1, black_count))
    if np.any(black_adjacent_max == 0):
        return False
    white_groups, white_count = nd.label(board == 2)
    white_adjacenet_max = nd.maximum(empty_adjacent_count, white_groups,
                                     np.arange(1, white_count))
    if np.any(white_adjacenet_max == 0):
        return False
    return True
    def find_albino_features(self, T, im):
        import scipy.ndimage as ndi

        binarized = zeros_like(T)
        binarized[T > self.albino_threshold] = True
        (labels, nlabels) = ndi.label(binarized)
        slices = ndi.find_objects(labels)

        intensities = []
        transform_means = []

        if len(slices) < 2:
            return (None, None)

        for s in slices:

            transform_means.append(mean(T[s]))
            intensities.append(mean(im[s]))

        sorted_transform_means = argsort(transform_means)
        candidate1 = sorted_transform_means[-1]
        candidate2 = sorted_transform_means[-2]

        c1_center = array(ndi.center_of_mass(im, labels, candidate1 + 1))
        c2_center = array(ndi.center_of_mass(im, labels, candidate2 + 1))

        if intensities[candidate1] > intensities[candidate2]:
            return (c2_center, c1_center)
        else:
            return (c1_center, c2_center)
Пример #28
0
def test_connect_regions():
    lena = sp.lena()
    for thr in (50, 150):
        mask = lena > thr
        graph = img_to_graph(lena, mask)
        nose.tools.assert_equal(ndimage.label(mask)[1],
                                cs_graph_components(graph)[0])
Пример #29
0
	def quantify_fibers2(self, args, vis_pix, thresholded_copix, im_co, rgb_pix): #label feature with number (2)
		vis_pix_matrix = vis_pix.reshape(im_co.size[1],im_co.size[0])
		all_array, num_features = si.label(vis_pix_matrix,structure=[[1,1,1],[1,1,1],[1,1,1]])
		co_fiber_sizes = []
		for fiber_slice in si.find_objects(all_array):
			fiber_pix = (thresholded_copix[fiber_slice].flatten()) > 0
			fiber_types = collections.Counter(all_array[fiber_slice].flatten())
			max_type = None
			if len(fiber_types) > 2:
				max_count = 0
				for ft in fiber_types:
					if ft > 0 and fiber_types[ft] > max_count:
						max_type = ft
						max_count = fiber_types[ft]
			if float(np.sum(fiber_pix))/float(fiber_pix.size) > .3: #if > 30% of the pixels are colocalized call entire fiber slow
				slow_fiber_size = 0
				for i in xrange(fiber_slice[0].start,fiber_slice[0].stop):
					for j in xrange(fiber_slice[1].start,fiber_slice[1].stop):
						if vis_pix_matrix[i][j] == 1:
							if max_type:
								if all_array[i][j] == max_type:
									vis_pix_matrix[i][j] = 2
									rgb_pix[i*im_co.size[0] + j] = (255, 255, 0)
									slow_fiber_size += 1
							else:
								vis_pix_matrix[i][j] = 2
								rgb_pix[i*im_co.size[0] + j] = (255, 255, 0)
								slow_fiber_size += 1
				co_fiber_sizes.append(slow_fiber_size)				
		vis_pix = vis_pix_matrix.flatten()
		return np.array(co_fiber_sizes)
						
Пример #30
0
        def mark_lalo_anomoly(lat, lon):
            """mask pixels with abnormal values (0, etc.)
            This is found on sentinelStack multiple swath lookup table file.
            """
            # ignore pixels with zero value
            zero_mask = np.multiply(lat != 0., lon != 0.)

            # ignore anomaly non-zero values 
            # by get the most common data range (d_min, d_max) based on histogram
            mask = np.array(zero_mask, np.bool_)
            for data in [lat, lon]:
                bin_value, bin_edge = np.histogram(data[mask], bins=10)                
                # if there is anomaly, histogram won't be evenly distributed
                while np.max(bin_value) > np.sum(zero_mask) * 0.3:
                    # find the continous bins where the largest bin is --> normal data range
                    bin_value_thres = ut.median_abs_deviation_threshold(bin_value, cutoff=3)
                    bin_label = ndimage.label(bin_value > bin_value_thres)[0]
                    idx = np.where(bin_label == bin_label[np.argmax(bin_value)])[0]
                    # convert to min/max data value
                    bin_step = bin_edge[1] - bin_edge[0]
                    d_min = bin_edge[idx[0]] - bin_step / 2.
                    d_max = bin_edge[idx[-1]+1] + bin_step / 2.
                    mask *= np.multiply(data >= d_min, data <= d_max)
                    bin_value, bin_edge = np.histogram(data[mask], bins=10)
            lat[mask == 0] = 90.
            lon[mask == 0] = 0.
            return lat, lon, mask
Пример #31
0
        draw_line_endpoints(img, linesEndpoints)

        lower = np.array(lower,
                         dtype="uint8")  # brojevi su svelije nijanse sive
        upper = np.array(upper, dtype="uint8")
        mask = cv2.inRange(img, lower, upper)
        # cv2.imshow("maska", mask)
        img0 = 1.0 * mask

        img0 = cv2.dilate(
            img0, kernel
        )  #ako je broj prekriven sumom, dilatacija ce popuniti te praznine na samoj cifri
        img0 = cv2.dilate(img0, kernel)  #jedna dilatacija nije bila dovoljna
        #cv2.imshow("dilat", img0)

        labeled, nr_objects = ndimage.label(img0)
        objects = ndimage.find_objects(labeled)
        for i in range(nr_objects):
            loc = objects[i]
            (xc, yc) = (int((loc[1].stop + loc[1].start) / 2),
                        int((loc[0].stop + loc[0].start) / 2))
            (dxc, dyc) = (int(loc[1].stop - loc[1].start),
                          int(loc[0].stop - loc[0].start))

            if (dxc < 12 and dyc < 12):
                continue

            cv2.circle(img, (xc, yc), 16, (25, 25, 255), 1)
            elem = {'center': (xc, yc), 'size': (dxc, dyc), 't': t}

            lst = inRange(20, elem, elements)
Пример #32
0
def compute_metrics(pred_mask_binary, mask, metrics, img_name):
    '''Read an image and return post-processed prediction according to a model.
    
    Keyword arguments:
    pred_mask_binary -- predicted mask
    mask -- true mask
    metrics -- pandas dataframe to store image-wise metrics
    img_name -- name of the image to be processed

    Return:
    metrics -- pandas dataframe with image-wise metrics
    '''
    # extract predicted objects and counts
    pred_label, pred_count = ndimage.label(pred_mask_binary)
    pred_objs = ndimage.find_objects(pred_label)

    # compute centers of predicted objects
    pred_centers = []
    for ob in pred_objs:
        pred_centers.append(((int(
            (ob[0].stop - ob[0].start) / 2) + ob[0].start), (int(
                (ob[1].stop - ob[1].start) / 2) + ob[1].start)))

    # extract target objects and counts
    targ_label, targ_count = ndimage.label(mask)
    targ_objs = ndimage.find_objects(targ_label)

    # compute centers of target objects
    targ_center = []
    for ob in targ_objs:
        targ_center.append(((int(
            (ob[0].stop - ob[0].start) / 2) + ob[0].start), (int(
                (ob[1].stop - ob[1].start) / 2) + ob[1].start)))

    # associate matching objects, true positives
    tp = 0
    fp = 0
    for pred_idx, pred_obj in enumerate(pred_objs):

        min_dist = 30  # 1.5-cells distance is the maximum accepted
        TP_flag = 0

        for targ_idx, targ_obj in enumerate(targ_objs):

            dist = hypot(pred_centers[pred_idx][0] - targ_center[targ_idx][0],
                         pred_centers[pred_idx][1] - targ_center[targ_idx][1])

            if dist < min_dist:

                TP_flag = 1
                min_dist = dist
                index = targ_idx

        if TP_flag == 1:
            tp += 1
            TP_flag = 0

            targ_center.pop(index)
            targ_objs.pop(index)

    # derive false negatives and false positives
    fn = targ_count - tp
    fp = pred_count - tp

    # update metrics dataframe
    metrics.loc[img_name] = [tp, fp, fn, targ_count, pred_count]

    return (metrics)
Пример #33
0
def old_make_single_chipmask(fibparms,
                             meansep,
                             masktype='stellar',
                             exclude_top_and_bottom=False,
                             nx=4112,
                             ny=4096):
    """OLD ROUTINE, NOT CURRENTLY IN USE!!!"""

    # some housekeeping...
    while masktype.lower() not in [
            "stellar", "sky2", "sky3", "lfc", "thxe", "background", "bg"
    ]:
        print('ERROR: chipmask "type" not recognized!!!')
        masktype = raw_input(
            'Please enter "type" - valid options are ["object" / "sky2" / "sky3" / "LFC" / "ThXe" / "background" or "bg"]:  '
        )

    # ny, nx = img.shape
    chipmask = np.zeros((ny, nx))

    # now actually make the "chipmask"
    for pix in np.arange(nx):

        if (pix + 1) % 100 == 0:
            print('Pixel column ' + str(pix + 1) + '/4112')

        for order in sorted(fibparms.keys()):

            if masktype.lower() == 'stellar':
                # for the object-fibres chipmask, take the middle between the last object fibre and first sky fibre at each end (ie the "gaps")
                f_upper = 0.5 * (fibparms[order]['fibre_04']['mu_fit'] +
                                 fibparms[order]['fibre_06']['mu_fit'])
                f_lower = 0.5 * (fibparms[order]['fibre_24']['mu_fit'] +
                                 fibparms[order]['fibre_26']['mu_fit'])
            elif masktype.lower() == 'sky2':
                # for the 2 sky fibres near the ThXe, we use the "gap" as the upper bound, and as the lower bound the trace of the lowermost sky fibre
                # minus half the average fibre separation for this order and pixel location, ie halfway between the lowermost sky fibre and the ThXe fibre
                f_upper = 0.5 * (fibparms[order]['fibre_24']['mu_fit'] +
                                 fibparms[order]['fibre_26']['mu_fit'])
                f_lower = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower.coefficients[-1] -= 0.5 * meansep[order][pix]
            elif masktype.lower() == 'sky3':
                # for the 3 sky fibres near the LFC, we use the "gap" as the lower bound, and as the upper bound the trace of the uppermost sky fibre
                # plus half the average fibre separation for this order and pixel location, ie halfway between the uppermost sky fibre and the LFC fibre
                f_upper = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_upper.coefficients[-1] += 0.5 * meansep[order][pix]
                f_lower = 0.5 * (fibparms[order]['fibre_04']['mu_fit'] +
                                 fibparms[order]['fibre_06']['mu_fit'])
            elif masktype.lower() == 'lfc':
                # for the LFC fibre, we assume as the lower bound the trace of the uppermost sky fibre plus half the average fibre separation for this order and pixel location,
                # ie halfway between the uppermost sky fibre and the LFC fibre, and as the upper bound the trace of the uppermost sky fibre plus two times the average
                # fibre separation for this order and pixel location
                f_upper = 1 * fibparms[order]['fibre_02']['mu_fit']
                f_upper.coefficients[-1] += 2. * meansep[order][pix]
                f_lower = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower.coefficients[-1] += 0.5 * meansep[order][pix]
            elif masktype.lower() == 'thxe':
                # for the ThXe fibre, we assume as the upper bound the trace of the lowermost sky fibre minus half the average fibre separation for this order and pixel location,
                # ie halfway between the lowermost sky fibre and the ThXe fibre, and as the lower bound the trace of the lowermost sky fibre minus two times the average
                # fibre separation for this order and pixel location
                f_upper = 1 * fibparms[order]['fibre_27']['mu_fit']
                f_upper.coefficients[-1] -= 0.5 * meansep[order][pix]
                f_lower = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower.coefficients[-1] -= 2. * meansep[order][pix]
            elif masktype.lower() in ['background', 'bg']:
                # could either do sth like 1. - np.sum(chipmask_i), but can also just use the lower bound of ThXe and the upper bound of LFC
                f_upper = 1 * fibparms[order]['fibre_02']['mu_fit']
                f_upper.coefficients[-1] += 2. * meansep[order][pix]
                f_lower = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower.coefficients[-1] -= 2. * meansep[order][pix]
            else:
                print(
                    'ERROR: Nightmare! That should never happen  --  must be an error in the Matrix...'
                )
                return

            ymin = f_lower(pix)
            ymax = f_upper(pix)

            # these are the pixels that fall completely in the range
            # NOTE THAT THE CO-ORDINATES ARE CENTRED ON THE PIXELS, HENCE THE 0.5s...
            full_range = np.arange(
                np.maximum(np.ceil(ymin + 0.5), 0),
                np.minimum(np.floor(ymax - 0.5) + 1, ny - 1)).astype(int)
            if len(full_range) > 0:
                chipmask[full_range, pix] = 1.

            # bottom edge pixel
            if ymin > -0.5 and ymin < ny - 1 + 0.5:
                qlow = np.ceil(ymin - 0.5) - ymin + 0.5
                chipmask[np.floor(ymin + 0.5).astype(int), pix] = qlow

            # top edge pixel
            if ymax > -0.5 and ymax < ny - 1 + 0.5:
                qtop = ymax - np.floor(ymax - 0.5) - 0.5
                chipmask[np.ceil(ymax - 0.5).astype(int), pix] = qtop

    # for the background we have to invert that mask and (optionally) exclude the top and bottom regions
    # which still include fainter orders etc (same as in "extract_background")
    if masktype.lower() == 'background':
        chipmask = 1. - chipmask
        if exclude_top_and_bottom:
            print(
                'WARNING: this fix works for the current Veloce CCD layout only!!!'
            )
            labelled_mask, nobj = label(chipmask)
            # WARNING: this fix works for the current Veloce CCD layout only!!!
            topleftnumber = labelled_mask[ny - 1, 0]
            # toprightnumber = labelled_mask[ny-1,nx-1]
            # bottomleftnumber = labelled_mask[0,0]
            bottomrightnumber = labelled_mask[0, nx - 1]
            chipmask[labelled_mask == topleftnumber] = False
            # chipmask[labelled_mask == toprightnumber] = False
            chipmask[labelled_mask == bottomrightnumber] = False

    return chipmask
                           cmap=cm)

fig.savefig(
    os.path.join(fig_dir,
                 'distribution_embedding_genotype_tbins=%d.pdf' % tbins))

#watershed it

from scipy import ndimage as ndi
from skimage.morphology import watershed
from skimage.feature import peak_local_max

local_maxi = peak_local_max(Y_xy, indices=False, footprint=np.ones((7, 7)))
local_maxi = peak_local_max(Y_xy, indices=False, footprint=np.ones((10, 10)))

markers = ndi.label(local_maxi)[0]
labels = watershed(-Y_xy, markers)  #, mask=image)

#classify points

Y_idx = np.array(np.round(
    (Y - [xmin, ymin]) / [xmax - xmin, ymax - ymin] * (npts - 1)),
                 dtype=int)
Y_idx[Y_idx < 0] = 0
Y_idx[Y_idx > npts - 1] = npts - 1
Y_class = labels[Y_idx[:, 0], Y_idx[:, 1]]

cmap = 'jet'
cmap = 'nipy_spectral'
cmap = 'hsv'
cmap = 'gist_ncar'
Пример #35
0
def Kristen_render(name_pattern,
                   group_id,
                   mCherry,
                   extranuclear_mCherry_pad,
                   GFP_orig,
                   mCherry_orig, output,
                   save=False, directory_to_save_to='verification'):
    labels, _ = ndi.label(extranuclear_mCherry_pad)
    unique_segmented_cells_labels = np.unique(labels)[1:]
    mCherry_cutoff = np.zeros_like(mCherry)
    qualifying_cell_label = []
    qualifying_regression_stats = []

    for cell_label in unique_segmented_cells_labels:
        mCherry_2 = np.zeros_like(mCherry)
        my_mask = labels == cell_label
        average_apply_mask = np.mean(mCherry[my_mask])
        intensity = np.sum(mCherry[my_mask])
        binary_pad = np.zeros_like(mCherry)
        binary_pad[my_mask] = 1
        pixel = np.sum(binary_pad[my_mask])

        if (average_apply_mask > .05 or intensity > 300) and pixel > 4000:

            GFP_limited_to_cell_mask = cf._3d_stack_2d_filter(GFP_orig, my_mask)
            mCherry_limited_to_cell_mask = cf._3d_stack_2d_filter(mCherry_orig, my_mask)

            qualifying_3d_GFP = GFP_limited_to_cell_mask[mCherry_limited_to_cell_mask>50]
            average_3d_GFP = np.mean(qualifying_3d_GFP)
            median_3d_GFP = np.median(qualifying_3d_GFP)
            std_3d_GFP = np.std(qualifying_3d_GFP)
            sum_qualifying_GFP = np.sum(qualifying_3d_GFP)

            nonqualifying_3d_GFP = GFP_limited_to_cell_mask[mCherry_limited_to_cell_mask<=50]
            average_nonqualifying_3d_GFP = np.mean(nonqualifying_3d_GFP)
            median_nonqualifying_3d_GFP = np.median(nonqualifying_3d_GFP)
            std_nonqualifying_3d_GFP = np.std(nonqualifying_3d_GFP)
            sum_nonqualifying_GFP = np.sum(nonqualifying_3d_GFP)

            sum_total_GFP = sum_qualifying_GFP + sum_nonqualifying_GFP
            percent_qualifying_over_total_GFP = sum_qualifying_GFP/sum_total_GFP
            # report the percentage too or sums are sufficient?

            GFP_orig_qualifying = cf._3d_stack_2d_filter(GFP_orig, my_mask)
            mCherry_orig_qualifying = cf._3d_stack_2d_filter(mCherry_orig, my_mask)
            mCherry_1d = mCherry_orig_qualifying[mCherry_orig_qualifying > 50]
            GFP_1d = GFP_orig_qualifying[mCherry_orig_qualifying>50]
            regression_results = stats.linregress(GFP_1d, mCherry_1d)

            mCherry_2[my_mask] = mCherry[my_mask]
            mCherry_cutoff[my_mask] = mCherry[my_mask]
            qualifying_cell_label.append(cell_label)
            qualifying_regression_stats.append((regression_results[0], regression_results[2], regression_results[3]))

            name_pattern_split = name_pattern.split(' - ')
            transfection_label = name_pattern_split[0]
            cell_type = name_pattern_split[1]
            exp_time = name_pattern_split[2]
            image_number = name_pattern_split[4]

            with open(output, 'ab') as output_file:
                writer = csv_writer(output_file, delimiter='\t')
                writer.writerow([transfection_label, cell_type, exp_time, image_number, cell_label, sum_qualifying_GFP, sum_total_GFP, average_3d_GFP, median_3d_GFP, std_3d_GFP, average_nonqualifying_3d_GFP, median_nonqualifying_3d_GFP, std_nonqualifying_3d_GFP, regression_results[0], regression_results[2], regression_results[3]])

            plt.figure(figsize=(26.0, 15.0))
            plt.title('Kristen\'s Data')
            plt.suptitle(name_pattern)

            main_ax = plt.subplot(221)
            plt.subplot(221, sharex=main_ax, sharey=main_ax)
            plt.title('mCherry Binary')
            im = plt.imshow(extranuclear_mCherry_pad, interpolation='nearest', cmap = 'hot')
            plt.colorbar(im)
            plt.subplot(222, sharex=main_ax, sharey=main_ax)
            plt.title('mCherry')
            plt.imshow(mCherry, interpolation='nearest')
            plt.contour(extranuclear_mCherry_pad, [0.5], colors='k')
            plt.subplot(223)
            dplt.better2D_desisty_plot(GFP_1d, mCherry_1d)
            plt.title('mCherry Intensity as a Function of GFP Voxel')
            plt.xlabel('GFP Voxel')
            plt.ylabel('mCherry Intensity')
            plt.subplot(224, sharex=main_ax, sharey=main_ax)
            plt.title('mCherry-cutoff applied')
            plt.imshow(mCherry_2, interpolation='nearest')

            if not save:
                plt.show()

            else:
                name_puck = directory_to_save_to + '/' + 'Kristen-' + name_pattern+ '_cell' + str(cell_label)+ '.png'
                plt.savefig(name_puck)
                plt.close()
    plt.figure(figsize=(26.0, 15.0))
    main_ax = plt.subplot(121)
    plt.subplot(121, sharex=main_ax, sharey=main_ax)
    plt.suptitle('mCherry Before and After Qualifying Cell Cutoff is Applied')
    plt.title('mCherry')
    im = plt.imshow(mCherry, interpolation='nearest')
    plt.colorbar(im)
    plt.subplot(122, sharex=main_ax, sharey=main_ax)
    plt.title('mCherry')
    plt.imshow(mCherry_cutoff, interpolation='nearest')
    if not save:
        plt.show()

    else:
        name_puck = directory_to_save_to + '/' + 'Kristen-' + name_pattern + 'cutoff_app' + '.png'
        plt.savefig(name_puck)
        plt.close()

    return qualifying_regression_stats
Пример #36
0
    def generate_saliency(self, input, target):

        #self.model.zero_grad()

        output = self.model(input)

        #index: 0 layer: HP
        # index: 1 layer: Ship
        # index: 2 layer: Small Towers
        # index: 3 layer: Big Towers
        # index: 4 layer: Small Cities
        # index: 5 layer: Big Cities
        # index: 6 layer: Friend
        # index: 7 layer: Enemy


        #return (input.grad.clone()[0] * input)
        input2 = input.cpu().clone()
        image = np.zeros((40, 40))
        input2 = input2.view(40, 40, 8)

        #logical or of the input images to get the original image
        #only do or over small big cities and towers to get proper coordinates of cities and towers
        #otherwise it will include enemy ship too if enemy channel is included which will cause object to
        #be merged with tower or city object
        for i in range(2,6):
            if i!= 0:
                image = np.logical_or(image, input2[:, :, i].numpy())*1

        #get the number of objects in the image
        labeled_array, num_objects = label(image)

        indices = []
        for i in range(num_objects):
            indices.append(np.argwhere(labeled_array == i+1))



        #special stuff for ship channel
        ship_image = input2[:, :, 1].clone().numpy()
        ship_image[19][20] = 0
        ship_image[20][20] = 0
        ship_image[21][20] = 0
        ship_array, ships = label(ship_image)
        ship_indices = []
        for i in range(ships):
            ship_indices.append(np.argwhere(ship_array == i+1))
        #self.generate_file(ship_array, 'mod_ship_array')

        hp_array, hp = label(input2[:, :, 0].numpy())
        hp_indices = []
        for i in range(hp):
            hp_indices.append(np.argwhere(hp_array == i+1))


        values = torch.zeros(40*40*5)
        values = values.view(40, 40, 5)
        input2 = input.clone()
        input2 = input2.view(40, 40, 8)

        # index: 0 layer: HP
        # index: 1 layer: Ship
        # index: 2 layer: Small Towers
        # index: 3 layer: Big Towers
        # index: 4 layer: Small Cities
        # index: 5 layer: Big Cities
        # index: 6 layer: Friend
        # index: 7 layer: Enemy

        #output layers:
        #0 HP
        #1 agent
        #2 size
        #3 type
        # friend/enemy

        #here i refers to the output salient layers
        #print('num_objects', num_objects)

        for i in range(5):
            if i==0:# output HP
                for j in range(hp):
                    for k in range(hp_indices[j].shape[0]):
                        x = hp_indices[j][k][0]
                        y = hp_indices[j][k][1]
                        temp = 0.3*input2[:, :, 0][x][y]
                        input2[:, :, 0][x][y] += temp
                    perturbed_output = self.model(input2.view(1, 12800))
                    gradient = (perturbed_output - output)/temp
                    input2 = input.clone()
                    input2 = input2.view(40, 40, 8)

                    for k in range(hp_indices[j].shape[0]):
                        x = hp_indices[j][k][0]
                        y = hp_indices[j][k][1]
                        values[:, :, 0][x][y] = gradient[:, target]
            elif i==1:#output agent
                for j in range(ships):
                    for k in range(ship_indices[j].shape[0]):
                        x = ship_indices[j][k][0]
                        y = ship_indices[j][k][1]
                        if input2[:, :, 1][x][y] == 1:
                            input2[:, :, 1][x][y] = 0
                    perturbed_output = self.model(input2.view(1, 12800))
                    gradient = (perturbed_output - output)
                    input2 = input.clone()
                    input2 = input2.view(40, 40, 8)

                    for k in range(ship_indices[j].shape[0]):
                        x = ship_indices[j][k][0]
                        y = ship_indices[j][k][1]
                        values[:, :, 1][x][y] = gradient[:, target]
            elif i==2: #output size
                #print('in i== 2')
                for l in range(2, 6):
                    #print('layer: ',l)
                    for j in range(num_objects):
                    #    print('object: ',j)
                        s = 0
                        for k in range(indices[j].shape[0]):
                            x = indices[j][k][0]
                            y = indices[j][k][1]
                            # print('x: '+str(x)+' y: '+str(y))
                            # print('Value of input: '+str(input2[:, :, i][x][y]))
                    #        print(input2[:, :, l][x][y])
                            if l == 2 or l==4: #small tower/city
                                if input2[:, :, l][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l+1][x][y] = 1
                            else: #big tower/city
                                if input2[:, :, l ][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l-1][x][y] = 1

                        perturbed_output = self.model(input2.view(1, 12800))
                        gradient = (perturbed_output - output)
                        #print(saliency)
                        input2 = input.clone()
                        input2 = input2.view(40, 40, 8)
                        if s==1:
                            for k in range(indices[j].shape[0]):
                                x = indices[j][k][0]
                                y = indices[j][k][1]
                                values[:, :, 2][x][y] = gradient[:, target]
                #print(saliency[0][target])
            elif i==3: #output type
                for l in range(2, 6):
                    for j in range(num_objects):
                        s = 0
                        for k in range(indices[j].shape[0]):
                            x = indices[j][k][0]
                            y = indices[j][k][1]
                            # print('x: '+str(x)+' y: '+str(y))
                            # print('Value of input: '+str(input2[:, :, i][x][y]))
                            if l == 2 or l == 3: #small tower/city
                                if input2[:, :, l][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l+2][x][y] = 1
                            else: #big tower/city
                                if input2[:, :, l ][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l-2][x][y] = 1

                        perturbed_output = self.model(input2.view(1, 12800))
                        gradient = (perturbed_output - output)
                        #print(saliency)
                        input2 = input.clone()
                        input2 = input2.view(40, 40, 8)
                        if s==1:
                            for k in range(indices[j].shape[0]):
                                x = indices[j][k][0]
                                y = indices[j][k][1]
                                values[:, :, 3][x][y] = gradient[:, target]

            else:# output frenemy
                for l in range(6, 8):
                    for j in range(num_objects):
                        s = 0
                        for k in range(indices[j].shape[0]):
                            x = indices[j][k][0]
                            y = indices[j][k][1]

                            if l == 6:
                                if input2[:, :, l][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l+1][x][y] = 1
                            else:
                                if input2[:, :, l][x][y] == 1:
                                    s = 1
                                    input2[:, :, l][x][y] = 0
                                    input2[:, :, l-1][x][y] = 1
                        perturbed_output = self.model(input2.view(1, 12800))
                        gradient = (perturbed_output - output)
                        #print(s)
                        input2 = input.clone()
                        input2 = input2.view(40, 40, 8)
                        if s==1:
                            for k in range(indices[j].shape[0]):
                                x = indices[j][k][0]
                                y = indices[j][k][1]
                                values[:, :, 4][x][y] = gradient[:, target]






                    #for l in range(6):
                    #    torchvision.utils.save_image(saliency[:, :, l], "Image perturbed: "+str(i) + "/" + "object perturbed: "+str(j)+ "/" + str(l) + ".png", normalize=True)




        return (values.view(1, 40*40*5))
Пример #37
0
"""
Display a labels layer above of an image layer using the add_labels and
add_image APIs
"""

from skimage import data
from scipy import ndimage as ndi
from napari_animation import Animation
import napari

blobs = data.binary_blobs(length=128, volume_fraction=0.1, n_dim=3)
viewer = napari.view_image(blobs.astype(float), name='blobs')
labeled = ndi.label(blobs)[0]
viewer.add_labels(labeled, name='blob ID')

animation = Animation(viewer)
viewer.update_console({'animation': animation})

animation.capture_keyframe()
viewer.camera.zoom = 0.2
animation.capture_keyframe()
viewer.camera.zoom = 10.0
viewer.camera.center = (0, 40.0, 10.0)
animation.capture_keyframe()
viewer.dims.current_step = (60, 0, 0)
animation.capture_keyframe(steps=60)
viewer.dims.current_step = (0, 0, 0)
animation.capture_keyframe(steps=60)
viewer.reset_view()
animation.capture_keyframe()
Пример #38
0
def compute_metrics2D(bin_im, dist_trsf_im, AP_pos=None, vs=None):
    """
    Given an isotropic 2D binary image `bin_im`, a distance transform image
    `dist_trsf_im` of `bin_im`, a 2D position and a voxel size `vs`,
    computes the length, the width, the aspect ratio, the solidity,
    the sphericity, the volume and the surface of the binary image.
    Notes: - `bin_im` has to be isotropic otherwise the distances won't be
           computed correctly
           - `bin_im` and `dist_trsf_im` must share the same shape

    Parameters
    ----------
    bin_im : array_like
        A n*m*l binary array with one single connected component
    dist_trsf_im : array_like
        A distance transformation of the bin_im array
    AP_pos : ((float, float), (float, float)) optional
        x, y position of the anterior part of the Neural Tube
    vs : float optional (default 1.)
        The size of the isotropic voxel in order to get measurements
        in physical units

    Returns
    -------
    length : float
        The length of the masked object in the binary image
    width_spl : scipy.interpolate.InterpolatedUnivariateSpline
        The interpolated width along the masked object
        in the binary image
    width_median : float
        Median of the width along the masked object in the binary image
    AR : float
        The aspect ratio of the masked object in the binary image
        `length/median(width)`
    solidity : float
        The solidity of the masked object in the binary image
        Ratio of pixels in the region to pixels of the convex hull image.
    surface :
        The surface of the masked object in the binary image
        Number of voxels in the region
    perimeter :
        The perimeter of the masked object in the binary image
    circularity :
        The circularity of the masked object in the binary image
        4*pi*(`surface`/(`perimeter`**2))
    """

    # Extract the largest connected component
    label_im = nd.label(bin_im)[0]
    labels = np.unique(label_im)
    labels = labels[labels != 0]
    surfaces = nd.sum(np.ones_like(label_im), index=labels, labels=label_im)
    final_cc = labels[np.argmax(surfaces)]
    bin_im = (label_im == final_cc).astype(np.uint8)

    # Compute the surface, perimeter, circularity and solidity
    if vs is None:
        vs = 1.
    props = measure.regionprops(bin_im.astype(np.uint8))[0]
    surface = props.area * vs**2
    perimeter = props.perimeter * vs
    circularity = 4 * np.pi * (surface / perimeter**2)
    solidity = props.solidity

    # Skeletonize the mask and retrieve the coordinates of the skeleton
    skel_im = morphology.skeletonize(bin_im).astype(np.uint8)
    pos_arr = np.argwhere(skel_im)
    pos = dict(zip(range(len(pos_arr)), pos_arr))
    nodes = set(pos)
    neighb = {}
    to_treat = set([min(nodes)])
    done = set()
    # Builds the tree of the skeleton
    # The nodes are the coordinates
    # Two nodes are linked iff they are 4-connected
    while 0 < len(to_treat):
        curr = to_treat.pop()
        done.add(curr)
        dist = np.abs(pos_arr[curr] - pos_arr)
        N = set(np.where(np.max(dist, axis=1) == 1)[0])
        for ni in N:
            neighb.setdefault(curr, []).append(ni)
        to_treat.update(N.difference(done))

    # Finds the leaves of the tree
    extremities = [k for k, v in neighb.items() if len(v) == 1]
    D_out = {}
    # For each leaf, finds the most distant leaf
    # Using Dijkstra algorithm
    with Pool() as pool:
        mapping = [(nodes, neighb, e) for e in extremities]
        out = pool.map(Dijkstra, mapping)
        pool.terminate()
        pool.close()
    D_out = dict(zip(extremities, out))
    # Finds the pair (e1, e2) of most distant leaves
    e1 = max(D_out, key=lambda x: D_out.get(x)[1])
    e2 = D_out[e1][0]
    prev = D_out[e1][2]
    curr = e2

    # Retrieve and smooth the longest path of the skeleton tree
    skel_im[skel_im != 0] = 1
    path = []
    while curr in prev:
        path += [pos[curr]]
        curr = prev[curr]
    X, Y = zip(*path)
    X_smoothed = np.round(nd.filters.gaussian_filter1d(X, sigma=2)).astype(
        np.uint16)
    Y_smoothed = np.round(nd.filters.gaussian_filter1d(Y, sigma=2)).astype(
        np.uint16)
    for x, y in zip(X_smoothed, Y_smoothed):
        skel_im[tuple([x, y])] = 2

    # Build the graph containing the longest path of the skeleton tree
    pos_arr = np.argwhere(skel_im == 2)
    pos = dict(zip(range(len(pos_arr)), pos_arr))
    nodes = set(pos)
    neighb = {}
    to_treat = set([min(nodes)])
    done = set()
    while 0 < len(to_treat):
        curr = to_treat.pop()
        done.add(curr)
        dist = np.abs(pos_arr[curr] - pos_arr)
        N = set(np.where(np.max(dist, axis=1) == 1)[0])
        for ni in N:
            neighb.setdefault(curr, []).append(ni)
        to_treat.update(N.difference(done))

    # Retrieve the x, y, z coordinates of the longest path
    first = list(neighb.keys())[0]
    last, b, prev = Dijkstra((nodes, neighb, first))
    last, b, prev = Dijkstra((nodes, neighb, last))
    current = last
    ordered_pos = [pos[current]]
    while prev.get(current, -1) != -1:
        current = prev[current]
        ordered_pos += [pos[current]]

    # Gets the closest points of the skeleton to
    # the manually informed posterior and anterior positions
    if AP_pos is not None:
        A_pos, P_pos = AP_pos
        A_pos = np.array(A_pos)
        P_pos = np.array(P_pos)
        dist_to_A = np.linalg.norm(ordered_pos - A_pos, axis=1)
        A_pos = np.argmin(dist_to_A)

        dist_to_P = np.linalg.norm(ordered_pos - P_pos, axis=1)
        P_pos = np.argmin(dist_to_P)

        # Crop and reorder (if necessary) the skeleton
        if A_pos < P_pos:
            ordered_pos = ordered_pos[A_pos:P_pos + 1]
            ordered_pos = ordered_pos[::-1]
            P_pos, A_pos = A_pos, P_pos
        else:
            ordered_pos = ordered_pos[P_pos:A_pos + 1]

    # Computes, smooth and interpolate the width along the longest path
    dist_trsf_im *= vs
    x, y = zip(*ordered_pos)
    width = dist_trsf_im[(x, y)].flatten()
    width = nd.filters.gaussian_filter1d(width.astype(np.float), sigma=4)
    X = np.linspace(0, 1, len(width))
    width_spl = InterpolatedUnivariateSpline(X, width)
    # Computes the length of the longest path in physical units (given by vs)
    tmp = np.array(list(zip(x, y))) * vs
    length = np.sum(np.linalg.norm(tmp[:-1] - tmp[1:], axis=1))
    # Computes the Aspect Ration as the length over the median width
    AR = length / np.median(width)

    return (length, width_spl, np.median(width), AR, solidity, surface,
            perimeter, circularity)
def Fragmenter():
    tmpOb = Config.Load(
        frgSpec,
        pth.expanduser(
            '~/korenbergNAS/3D_database/Working/configuration_files/SidescapeRelateBlockface/M{0}/section_{1}/section_{1}_frag0.yaml'
            .format(secOb.mkyNum, secOb.secNum)))
    dictBuild = {}
    #Load in the whole image so that the fragment can cropped out
    ssiSrc, bfiSrc, ssiMsk, bfiMsk = Loader(tmpOb, ca.MEM_HOST)

    #Because some of the functions only woth with gray images
    bfiGry = ca.Image3D(bfiSrc.grid(), bfiSrc.memType())
    ca.Copy(bfiGry, bfiSrc, 1)

    lblSsi, _ = ndimage.label(np.squeeze(ssiMsk.asnp()) > 0)
    lblBfi, _ = ndimage.label(np.squeeze(bfiMsk.asnp()) > 0)

    seedPt = np.squeeze(pp.LandmarkPicker([lblBfi, lblSsi]))
    subMskBfi = common.ImFromNPArr(lblBfi == lblBfi[seedPt[0, 0],
                                                    seedPt[0,
                                                           1]].astype('int8'),
                                   sp=bfiSrc.spacing(),
                                   orig=bfiSrc.origin())
    subMskSsi = common.ImFromNPArr(lblSsi == lblSsi[seedPt[1, 0],
                                                    seedPt[1,
                                                           1]].astype('int8'),
                                   sp=ssiSrc.spacing(),
                                   orig=ssiSrc.origin())

    bfiGry *= subMskBfi
    bfiSrc *= subMskBfi
    ssiSrc *= subMskSsi
    #Pick points that are the bounding box of the desired subvolume
    corners = np.array(
        pp.LandmarkPicker(
            [np.squeeze(bfiGry.asnp()),
             np.squeeze(ssiSrc.asnp())]))
    bfiCds = corners[:, 0]
    ssiCds = corners[:, 1]

    #Extract the region from the source images
    bfiRgn = cc.SubVol(bfiSrc,
                       xrng=[bfiCds[0, 0], bfiCds[1, 0]],
                       yrng=[bfiCds[0, 1], bfiCds[1, 1]])
    ssiRgn = cc.SubVol(ssiSrc,
                       xrng=[ssiCds[0, 0], ssiCds[1, 0]],
                       yrng=[ssiCds[0, 1], ssiCds[1, 1]])

    #Extract the region from the mask images
    rgnMskSsi = cc.SubVol(subMskSsi,
                          xrng=[ssiCds[0, 0], ssiCds[1, 0]],
                          yrng=[ssiCds[0, 1], ssiCds[1, 1]])
    rgnMskBfi = cc.SubVol(subMskBfi,
                          xrng=[bfiCds[0, 0], bfiCds[1, 0]],
                          yrng=[bfiCds[0, 1], bfiCds[1, 1]])

    dictBuild['rgnBfi'] = np.divide(
        bfiCds, np.array(bfiSrc.size().tolist()[0:2], 'float')).tolist()
    dictBuild['rgnSsi'] = np.divide(
        ssiCds, np.array(ssiSrc.size().tolist()[0:2], 'float')).tolist()

    #Check the output directory for the source files of the fragment
    if not pth.exists(
            pth.expanduser(secOb.ssiSrcPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.ssiSrcPath + 'frag{0}'.format(frgNum)))
    if not pth.exists(
            pth.expanduser(secOb.bfiSrcPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.bfiSrcPath + 'frag{0}'.format(frgNum)))
    #Check the output directory for the mask files of the fragment
    if not pth.exists(
            pth.expanduser(secOb.ssiMskPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.ssiMskPath + 'frag{0}'.format(frgNum)))
    if not pth.exists(
            pth.expanduser(secOb.bfiMskPath + 'frag{0}'.format(frgNum))):
        os.mkdir(pth.expanduser(secOb.bfiMskPath + 'frag{0}'.format(frgNum)))

    dictBuild[
        'ssiSrcName'] = 'frag{0}/M{1}_01_ssi_section_{2}_frag1.tif'.format(
            frgNum, secOb.mkyNum, secOb.secNum)
    dictBuild[
        'bfiSrcName'] = 'frag{0}/M{1}_01_bfi_section_{2}_frag1.mha'.format(
            frgNum, secOb.mkyNum, secOb.secNum)
    dictBuild[
        'ssiMskName'] = 'frag{0}/M{1}_01_ssi_section_{2}_frag1_mask.tif'.format(
            frgNum, secOb.mkyNum, secOb.secNum)
    dictBuild[
        'bfiMskName'] = 'frag{0}/M{1}_01_bfi_section_{2}_frag1_mask.tif'.format(
            frgNum, secOb.mkyNum, secOb.secNum)

    #Write out the masked and cropped images so that they can be loaded from the YAML file
    #The BFI region needs to be saved as color and mha format so that the grid information is carried over.
    common.SaveITKImage(
        ssiRgn, pth.expanduser(secOb.ssiSrcPath + dictBuild['ssiSrcName']))
    cc.WriteColorMHA(
        bfiRgn, pth.expanduser(secOb.bfiSrcPath + dictBuild['bfiSrcName']))
    common.SaveITKImage(
        rgnMskSsi, pth.expanduser(secOb.ssiMskPath + dictBuild['ssiMskName']))
    common.SaveITKImage(
        rgnMskBfi, pth.expanduser(secOb.bfiMskPath + dictBuild['bfiMskName']))

    frgOb = Config.MkConfig(dictBuild, frgSpec)
    updateFragOb(frgOb)

    return None
Пример #40
0
# We can solve this by applying some smoothing to the image data.
# Here we apply a 2D Gaussian smoothing function to the data.
data2 = ndimage.gaussian_filter(aiamap.data * ~mask, 14)

##############################################################################
# The issue with the filtering is that it create pixels where the values are
# small (<100), so when we go on later to label this array,
# we get one large region which encompasses the entire array.
# If you want to see, just remove this line.
data2[data2 < 100] = 0

##############################################################################
# Now we will make a second SunPy map with this smoothed data.
aiamap2 = sunpy.map.Map(data2, aiamap.meta)

##############################################################################
# The function `scipy.ndimage.label` counts the number of contiguous regions
# in an image.
labels, n = ndimage.label(aiamap2.data)

##############################################################################
# Finally, we plot the smoothed bright image data, along with the estimate of
# the number of distinct regions. We can see that approximately 6 distinct hot
# regions are present above the 10% of the maximum level.
plt.figure()
ax = plt.subplot(projection=aiamap)
aiamap.plot()
plt.contour(labels)
plt.figtext(0.3, 0.2, f'Number of regions = {n}', color='white')
plt.show()
Пример #41
0
def make_single_chipmask(fibparms,
                         meansep,
                         masktype='stellar',
                         exclude_top_and_bottom=True,
                         nx=4112,
                         ny=4096,
                         use_lfc=False,
                         debug_level=0,
                         timit=False):
    if timit:
        start_time = time.time()

    # some housekeeping...
    while masktype.lower() not in [
            "stellar", "sky2", "sky3", "lfc", "thxe", "background", "bg"
    ]:
        print('ERROR: chipmask "type" not recognized!!!')
        masktype = raw_input(
            'Please enter "type" - valid options are ["object" / "sky2" / "sky3" / "LFC" / "ThXe" / "background" or "bg"]:  '
        )

    # ny, nx = img.shape
    chipmask = np.zeros((ny, nx))
    xx = np.arange(nx)
    yy = np.arange(ny)
    XX, YY = np.meshgrid(xx, yy)

    # now identify regions of the chip
    for order in sorted(fibparms.keys()):

        if debug_level >= 1:
            print('Checking ' + order)

        if masktype.lower() == 'stellar':
            # for the object-fibres chipmask, take the middle between the last object fibre and first sky fibre at each end (ie the "gaps")
            f_upper = 0.5 * (fibparms[order]['fibre_04']['mu_fit'] +
                             fibparms[order]['fibre_06']['mu_fit'])
            f_lower = 0.5 * (fibparms[order]['fibre_24']['mu_fit'] +
                             fibparms[order]['fibre_26']['mu_fit'])
        elif masktype.lower() == 'sky2':
            # for the 2 sky fibres near the ThXe, we use the "gap" as the upper bound, and as the lower bound either (i) the midpoint between the lowest sky2 fibre and
            # the simThXe fibre, or (ii) the trace of the lowermost sky fibre minus half the average fibre separation for this order and pixel location
            f_upper = 0.5 * (fibparms[order]['fibre_24']['mu_fit'] +
                             fibparms[order]['fibre_26']['mu_fit'])
            try:
                f_lower = 0.5 * (fibparms[order]['fibre_27']['mu_fit'] +
                                 fibparms[order]['fibre_28']['mu_fit'])
            except:
                f_lower = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower -= 0.5 * meansep[order]
        elif masktype.lower() == 'sky3':
            # for the 3 sky fibres near the LFC, we use the "gap" as the lower bound, and as the upper bound either (i) the midpoint between the uppermost sky3 fibre and
            # the LFC fibre, or (ii) the trace of the uppermost sky fibre plus half the average fibre separation for this order and pixel location
            if use_lfc:
                try:
                    f_upper = 0.5 * (fibparms[order]['fibre_02']['mu_fit'] +
                                     fibparms[order]['fibre_01']['mu_fit'])
                except:
                    f_upper = 1 * fibparms[order]['fibre_02'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_upper += 0.5 * meansep[order]
            else:
                f_upper = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_upper += 0.5 * meansep[order]
            f_lower = 0.5 * (fibparms[order]['fibre_04']['mu_fit'] +
                             fibparms[order]['fibre_06']['mu_fit'])
        elif masktype.lower() == 'lfc':
            # for the LFC fibre, we assume as the lower bound either (i) the midpoint between the uppermost sky3 fibre and the LFC fibre, or (ii) the trace of the uppermost
            # sky fibre plus half the average fibre separation for this order and pixel location; as the upper bound either (i) the trace of the LFC fibre plus half the average
            # fibre separation for this order and pixel location, or (ii) the trace of the uppermost sky3 fibre plus one and a half times the average fibre separation for this
            # order and pixel location
            if use_lfc:
                try:
                    f_upper = 1 * fibparms[order]['fibre_01'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_upper += 0.5 * meansep[order]
                    f_lower = 0.5 * (fibparms[order]['fibre_01']['mu_fit'] +
                                     fibparms[order]['fibre_02']['mu_fit'])
                except:
                    f_upper = 1 * fibparms[order]['fibre_02'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_upper += 1.5 * meansep[order]
                    f_lower = 1 * fibparms[order]['fibre_02'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_lower += 0.5 * meansep[order]
            else:
                f_upper = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_upper += 1.5 * meansep[order]
                f_lower = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower += 0.5 * meansep[order]
        elif masktype.lower() == 'thxe':
            # for the simThXe fibre, we assume as the lower bound either (i) the trace of the simThXe fibre minus half the average fibre separation for this order and pixel
            # location, or (ii) the trace of the lowermost sky2 fibre minus one and a half times the average fibre separation for this order and pixel location; as the upper
            # bound either (i) the midpoint between the lowermost sky2 fibre and the simThXe fibre, or (ii) the trace of the lowermost sky2 fibre minus one a half times the
            # average fibre separation for this order and pixel location
            try:
                f_upper = 0.5 * (fibparms[order]['fibre_27']['mu_fit'] +
                                 fibparms[order]['fibre_28']['mu_fit'])
                f_lower = 1 * fibparms[order]['fibre_28'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower -= 0.5 * meansep[order]
            except:
                f_upper = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_upper -= 0.5 * meansep[order]
                f_lower = 1 * fibparms[order]['fibre_27'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_lower -= 1.5 * meansep[order]
        elif masktype.lower() in ['background', 'bg']:
            # could either do sth like 1. - np.sum(chipmask_i), but we can also just use the lower bound of ThXe and the upper bound of LFC
            # identify what is NOT background, and later "invert" that
            if use_lfc:
                try:
                    f_upper = 1 * fibparms[order]['fibre_01'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_upper += 1. * meansep[
                        order]  # use whole meansep here to avoid contamination from the calib sources a bit more
                    f_lower = 1 * fibparms[order]['fibre_28'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_lower -= 1. * meansep[
                        order]  # use whole meansep here to avoid contamination from the calib sources a bit more
                except:
                    f_upper = 1 * fibparms[order]['fibre_02'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_upper += 2. * meansep[
                        order]  # use 2 here to avoid contamination from the calib sources a bit more
                    f_lower = 1 * fibparms[order]['fibre_27'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_lower -= 2. * meansep[
                        order]  # use 2 here to avoid contamination from the calib sources a bit more
            else:
                f_upper = 1 * fibparms[order]['fibre_02'][
                    'mu_fit']  # the multiplication with one acts like a copy
                f_upper += 2. * meansep[
                    order]  # use 2 here to avoid contamination from the calib sources a bit more
                try:
                    f_lower = 1 * fibparms[order]['fibre_28'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_lower -= 1. * meansep[order]
                except:
                    f_lower = 1 * fibparms[order]['fibre_27'][
                        'mu_fit']  # the multiplication with one acts like a copy
                    f_lower -= 2. * meansep[
                        order]  # use 2 here to avoid contamination from the calib sources a bit more

        # get indices of the pixels that fall into the respective regions
        order_stripe = (YY < f_upper) & (YY > f_lower)
        chipmask = np.logical_or(chipmask, order_stripe)

    # for the background we have to invert that mask and (optionally) exclude the top and bottom regions
    # which still include fainter orders etc (same as in "extract_background")
    if masktype.lower() in ['bg', 'background']:
        chipmask = np.invert(chipmask)
        if exclude_top_and_bottom:
            if debug_level >= 1:
                print(
                    'WARNING: this fix works for the current Veloce CCD layout only!!!'
                )
            labelled_mask, nobj = label(chipmask)
            # WARNING: this fix works for the current Veloce CCD layout only!!!
            topleftnumber = labelled_mask[ny - 1, 0]
            # toprightnumber = labelled_mask[ny-1,nx-1]
            # bottomleftnumber = labelled_mask[0,0]
            bottomrightnumber = labelled_mask[0, nx - 1]
            chipmask[labelled_mask == topleftnumber] = False
            # chipmask[labelled_mask == toprightnumber] = False
            chipmask[labelled_mask == bottomrightnumber] = False

    return chipmask
Пример #42
0
    def ndimage_alg(self, img, opts):
        """Island detection using scipy.ndimage

        Use scipy.ndimage.label to detect islands of emission in the image.
        Island is defined as group of tightly connected (8-connectivity
        for 2D images) pixels with emission.

        The following cuts are applied:
         - pixel is considered to have emission if it is 'thresh_isl' times
           higher than RMS.
         - Island should have at least 'minsize' active pixels
         - There should be at lease 1 pixel in the island which is 'thresh_pix'
           times higher than noise (peak clip).

        Parameters:
        image, mask: arrays with image data and mask
        mean, rms: arrays with mean & rms maps
        thresh_isl: threshold for 'active pixels'
        thresh_pix: threshold for peak
        minsize: minimal acceptable island size

        Function returns a list of Island objects.
        """
        ### islands detection
        mylog = mylogger.logging.getLogger("PyBDSM." + img.log + "Islands")

        image = img.ch0_arr
        mask = img.mask_arr
        rms = img.rms_arr
        mean = img.mean_arr
        thresh_isl = opts.thresh_isl
        thresh_pix = img.thresh_pix
        clipped_mean = img.clipped_mean
        saverank = opts.savefits_rankim

        # act_pixels is true if significant emission
        if img.masked:
            act_pixels = ~(mask.copy())
            act_pixels[~mask] = (image[~mask] -
                                 mean[~mask]) / thresh_isl >= rms[~mask]
        else:
            act_pixels = (image - mean) / thresh_isl >= rms

            # dimension of image
        rank = len(image.shape)
        # generates matrix for connectivity, in this case, 8-conn
        connectivity = nd.generate_binary_structure(rank, rank)
        # labels = matrix with value = (initial) island number
        labels, count = nd.label(act_pixels, connectivity)
        # slices has limits of bounding box of each such island
        slices = nd.find_objects(labels)
        img.island_labels = labels

        ### apply cuts on island size and peak value
        pyrank = N.zeros(image.shape, dtype=N.int32)
        res = []
        islid = 0
        for idx, s in enumerate(slices):
            idx += 1  # nd.labels indices are counted from 1
            # number of pixels inside bounding box which are in island
            isl_size = (labels[s] == idx).sum()
            isl_peak = nd.maximum(image[s], labels[s], idx)
            isl_maxposn = tuple(N.array(N.unravel_index(N.nanargmax(image[s]), image[s].shape))+\
                          N.array((s[0].start, s[1].start)))
            if (isl_size >= img.minpix_isl
                ) and (isl_peak -
                       mean[isl_maxposn]) / thresh_pix > rms[isl_maxposn]:
                isl = Island(image, mask, mean, rms, labels, s, idx,
                             img.pixel_beamarea())
                res.append(isl)
                pyrank[tuple(
                    isl.bbox)] += N.invert(isl.mask_active) * idx // idx

        return res
Пример #43
0
# 4. label the junctions and extract information

#prepares to write in excel
excelpath = parent_dir + "/Outlines.xlsx"
Workbook().save(filename=excelpath)
book = load_workbook(excelpath)
writer = pd.ExcelWriter(excelpath, engine='openpyxl')
writer.book = book

s = [[1, 1, 1], [1, 1, 1], [1, 1, 1]]  #structure parameter
print("detecting Outlines...")
for file in sorted(glob.glob(image_j2_dir)):  #loops over cut Outlines
    read = io.imread(file)
    #labels the junctions
    mask = read == 1
    label_mask, num_labels = ndimage.label(mask, structure=s)
    #     imwrite(parent_dir+"/Outlines_cut/Outlines_id_"+file[-7:-4]+".tif", np.uint16(label_mask))
    #     junctionlabels = color.label2rgb(label_mask, bg_label=0)
    #     plt.imshow(junctionlabels)
    #gets info from junctions
    props = regionprops_table(
        label_mask, properties=['label', 'area', 'coords', "centroid"])
    df1 = pd.DataFrame(props)
    df1.to_excel(writer, sheet_name="Outline_t" + file[-7:-4])

#     centroids2=data2["centroids"].tolist()
print("saved Outlines.xlsx")
writer.save()
writer.close()

#-----------------------------------------------------------------------------
Пример #44
0
def label(mask):
    labeled, nr_true = ndimage.label(mask)
    return labeled
Пример #45
0
def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('--path_run', help='path to the prediction folder.')
    parser.add_argument('--s_min', default=50, type=int, help='min spine size')
    parser.add_argument('--s_max',
                        default=45000,
                        type=int,
                        help='max spine size')
    parsed_args = parser.parse_args(sys.argv[1:])

    path_run = parsed_args.path_run  # get prediction folder
    s_min = parsed_args.s_min  # get min size
    s_max = parsed_args.s_max  # get max size

    path_pred = os.path.join(path_run, "prediction")

    # initialization
    header = ['FP', 'FN', 'TP', 'Sens.', 'Precision']
    FP_global = list()
    FN_global = list()
    TP_global = list()
    SENS_global = list()
    PREC_global = list()
    FP_d = list()
    FN_d = list()
    TP_d = list()
    SENS_d = list()
    PREC_d = list()
    threshold_global = list()
    validation_cases = list()

    for index in range(0, 10, 1):  # threshold scan

        coinc_thr = index / 10  # from 0 to 1 in 0.1 steps

        FP_thr = np.array([])
        FN_thr = np.array([])
        TP_thr = np.array([])

        dir = listdir(path_pred)

        for case_folder in dir:  # for each case

            path, val_case = os.path.split(case_folder)

            # load gt and prediction files
            truth_file = os.path.join(path_pred, case_folder, "truth.nii.gz")
            truth_image = nib.load(truth_file)
            truth = truth_image.get_data()

            prediction_file = os.path.join(path_pred, case_folder,
                                           "prediction.nii.gz")
            prediction_image = nib.load(prediction_file)
            prediction = prediction_image.get_data()
            '''  DENDRITE  '''

            if index == 0:  # run just the first time

                print("dendrite case: " + case_folder)

                # get dendrite coords fot GT and prediction
                den_pred = np.where(prediction == [150])
                den_gt = np.where(truth == [150])

                # transpose
                den_pred_t = np.transpose(np.asarray(den_pred))
                den_gt_t = np.transpose(np.asarray(den_gt))

                tp_d = 0  # init

                # count number of coincident coords
                for element in den_pred_t:
                    find = np.where((den_gt_t == element).all(axis=1))
                    if find[0].size == 1:
                        tp_d = tp_d + 1

                # calculate evaluation metrics
                fp_d = den_pred_t.shape[0] - tp_d
                fn_d = den_gt_t.shape[0] - tp_d

                # append dendrite metrics
                FP_d.append(fp_d)
                FN_d.append(fn_d)
                TP_d.append(tp_d)
                SENS_d.append(tp_d / (tp_d + fn_d))
                PREC_d.append(tp_d / (tp_d + fp_d))
                validation_cases.append(val_case)
            '''  SPINE  '''

            # init
            tp_case = 0
            fn_case = 0
            used_list = list()  # already detected spines

            # delete dendrite from GT and prediction
            prediction[den_pred[0], den_pred[1], den_pred[2]] = 0
            truth[den_gt[0], den_gt[1], den_gt[2]] = 0

            # get gt and prediction labels
            label_prediction, num_labels_prediction = label(prediction)
            label_truth, num_labels_truth = label(truth)

            # get gt and predictions spines
            props_pred = regionprops(label_prediction)  # get prediction blobs
            props_truth = regionprops(label_truth)

            # preprocess prediction spines
            for spinePred in range(num_labels_prediction):  # for each spine
                size = props_pred[spinePred].area  # get size
                if size <= s_min or size >= s_max:  # if not in between thresholds
                    prediction[
                        props_pred[spinePred].coords[:, 0],
                        props_pred[spinePred].coords[:, 1],
                        props_pred[spinePred].coords[:, 2]] = 0  # delete spine

            # get new prediction labels and spines
            label_prediction, num_labels_prediction = label(prediction)
            props_pred = regionprops(label_prediction)

            for spineGT in range(
                    num_labels_truth):  # for each spine in gt (spineGT)

                # print progression
                prog = (spineGT / num_labels_truth) * 100
                print("case: " + case_folder + " - Progreso gt to pred: " +
                      str(round(prog, 1)) + "%")

                # init
                coincide_list_GT = list()
                coincide_list_Pred = list()

                coordsGT = props_truth[spineGT].coords  # get spineGT coords

                for spinePred in range(
                        num_labels_prediction
                ):  # for each spine in prediction (spinePred)

                    # init
                    counter_sp_coord = 0

                    coordsPred = props_pred[
                        spinePred].coords  # get spinePred coords

                    for pos in coordsGT:  # for each pixel in SpineGT
                        find = np.where((coordsPred == pos).all(
                            axis=1))  # look if it is in spinePred
                        if find[0].size == 1:  # if it is, count 1
                            counter_sp_coord += 1

                    # calculate % of pixels found, respect gt and pred size
                    percentageGT = counter_sp_coord / props_truth[spineGT].area
                    percentagePred = counter_sp_coord / props_pred[
                        spinePred].area

                    # save %
                    coincide_list_GT.append(percentageGT)
                    coincide_list_Pred.append(percentagePred)

                # delete % from positions of already detected spines
                for ind in used_list:
                    coincide_list_GT[ind] = 0
                    coincide_list_Pred[ind] = 0

                # get maximum mean score
                coincide_list_mean = [
                    (x + y) / 2
                    for x, y in zip(coincide_list_GT, coincide_list_Pred)
                ]  # scores mean
                max_coinc = max(coincide_list_mean)  # max mean score
                max_index = coincide_list_mean.index(
                    max_coinc)  # max mean score index

                # check if spine is detected
                if max_coinc > coinc_thr:  # if max_coinc is > than coinc_thr
                    tp_case = tp_case + 1  # tp + 1
                    used_list.append(max_index)  # spine detected
                else:
                    fn_case = fn_case + 1  # if not, fn + 1

            fp_case = num_labels_prediction - tp_case  # get fp as the difference between detected spines and tp

            # save case metrics
            FP_thr = np.append(FP_thr, fp_case)
            FN_thr = np.append(FN_thr, fn_case)
            TP_thr = np.append(TP_thr, tp_case)

        # save dendrite results on csv
        dendrite_csv = ({
            header[0]: FP_d,
            header[1]: FN_d,
            header[2]: TP_d,
            header[3]: SENS_d,
            header[4]: PREC_d
        })
        df = pd.DataFrame.from_records(dendrite_csv, index=validation_cases)
        df.to_csv(path_run + "/dendrite_scores.csv")

        # calculate and save threshold metrics
        FP_sum = np.sum(FP_thr)
        FN_sum = np.sum(FN_thr)
        TP_sum = np.sum(TP_thr)

        SENS_thr = TP_sum / (TP_sum + FN_sum)
        PREC_thr = TP_sum / (TP_sum + FP_sum)

        FP_global.append(FP_sum)
        FN_global.append(FN_sum)
        TP_global.append(TP_sum)
        SENS_global.append(SENS_thr)
        PREC_global.append(PREC_thr)
        threshold_global.append(coinc_thr)

    # save spine results on csv
    spine_csv = ({
        header[0]: FP_global,
        header[1]: FN_global,
        header[2]: TP_global,
        header[3]: SENS_global,
        header[4]: PREC_global
    })
    df = pd.DataFrame.from_records(spine_csv, index=threshold_global)
    df.to_csv(path_run + "/spine_scores.csv")
Пример #46
0
def process_signal(audio_plot, audio_signal, parameters, time_stamps):
    # partition the audio history into blocks of type:
    #   1. noise, where the volume is greater than noise_threshold
    #   2. silence, where the volume is less than noise_threshold
    noise = audio_signal > parameters['noise_threshold']
    silent = audio_signal < parameters['noise_threshold']

    # join "noise blocks" that are closer together than min_quiet_time
    crying_blocks = []
    if np.any(noise):
        silent_labels, _ = ndimage.label(silent)
        silent_ranges = ndimage.find_objects(silent_labels)
        for silent_block in silent_ranges:
            start = silent_block[0].start
            stop = silent_block[0].stop

            # don't join silence blocks at the beginning or end
            if start == 0:
                continue

            interval_length = time_stamps[stop - 1] - time_stamps[start]
            if interval_length < parameters['min_quiet_time']:
                noise[start:stop] = True

        # find noise blocks start times and duration
        crying_labels, num_crying_blocks = ndimage.label(noise)
        crying_ranges = ndimage.find_objects(crying_labels)
        for cry in crying_ranges:
            start = time_stamps[cry[0].start]
            stop = time_stamps[cry[0].stop - 1]
            duration = stop - start

            # ignore isolated noises (i.e. with a duration less than min_noise_time)
            if duration < parameters['min_noise_time']:
                continue

            # save some info about the noise block
            crying_blocks.append({
                'start':
                start,
                'start_str':
                datetime.fromtimestamp(start).strftime("%I:%M:%S %p").lstrip(
                    '0'),
                'stop':
                stop,
                'duration':
                format_time_difference(start, stop)
            })

    # determine how long have we been in the current state
    time_current = time.time()
    time_crying = ""
    time_quiet = ""
    str_crying = "Drone noise for "
    str_quiet = "Drone quiet for "
    if len(crying_blocks) == 0:
        time_quiet = str_quiet + format_time_difference(
            time_stamps[0], time_current)
    else:
        if time_current - crying_blocks[-1]['stop'] < parameters[
                'min_quiet_time']:
            time_crying = str_crying + format_time_difference(
                crying_blocks[-1]['start'], time_current)
        else:
            time_quiet = str_quiet + format_time_difference(
                crying_blocks[-1]['stop'], time_current)

    results = {
        'audio_plot': audio_plot,
        'crying_blocks': crying_blocks,
        'time_crying': time_crying,
        'time_quiet': time_quiet
    }
    return results
Пример #47
0
    def fill(self, coord, new_label, refresh=True):
        """Replace an existing label with a new label, either just at the
        connected component if the `contiguous` flag is `True` or everywhere
        if it is `False`, working either just in the current slice if
        the `n_dimensional` flag is `False` or on the entire data if it is
        `True`.

        Parameters
        ----------
        coord : sequence of float
            Position of mouse cursor in image coordinates.
        new_label : int
            Value of the new label to be filled in.
        refresh : bool
            Whether to refresh view slice or not. Set to False to batch paint
            calls.
        """
        int_coord = tuple(np.round(coord).astype(int))
        # If requested fill location is outside data shape then return
        if np.any(np.less(int_coord, 0)) or np.any(
            np.greater_equal(int_coord, self.data.shape)
        ):
            return

        # If requested new label doesn't change old label then return
        old_label = self.data[int_coord]
        if old_label == new_label or (
            self.preserve_labels and old_label != self._background_label
        ):
            return

        if refresh is True:
            self._save_history()

        if self.n_dimensional or self.ndim == 2:
            # work with entire image
            labels = self.data
            slice_coord = tuple(int_coord)
        else:
            # work with just the sliced image
            labels = self._data_raw
            slice_coord = tuple(int_coord[d] for d in self.dims.displayed)

        matches = labels == old_label
        if self.contiguous:
            # if contiguous replace only selected connected component
            labeled_matches, num_features = ndi.label(matches)
            if num_features != 1:
                match_label = labeled_matches[slice_coord]
                matches = np.logical_and(
                    matches, labeled_matches == match_label
                )

        # Replace target pixels with new_label
        labels[matches] = new_label

        if not (self.n_dimensional or self.ndim == 2):
            # if working with just the slice, update the rest of the raw data
            self.data[tuple(self._slice_indices)] = labels

        if refresh is True:
            self.refresh()
Пример #48
0
def DivideInNeighborhoods(data, number_of_spots, scale, sensitivity_limit=100):
    """
    Given an image that includes N spots, divides it in N subimages with each of them
    to include one spot. Briefly, it filters the image, finds the N “brightest” spots
    and crops the region around them generating the subimages. This process is repeated
    until image division is feasible.
    data (model.DataArray): 2D array containing the intensity of each pixel
    number_of_spots (int,int): The number of CL spots
    scale (float): Distance between spots in optical grid (in pixels)
    sensitivity_limit (int): Limit of sensitivity
    returns subimages (List of DataArrays): One subimage per spot
            subimage_coordinates (List of tuples): The coordinates of the center of each
                                                subimage with respect to the overall image
    """
    # Denoise
    filtered_image = ndimage.median_filter(data, 3)

    # Bold spots
    # Third parameter must be a length in pixels somewhat larger than a typical
    # spot
    filtered_image = _BandPassFilter(filtered_image, 1, 20)

    image = model.DataArray(filtered_image, data.metadata)
    avg_intensity = numpy.average(image)

    spot_factor = 10
    step = 1
    sensitivity = 4

    # After filtering based on optical scale there is no need to adjust
    # filter window size
    filter_window_size = 8

    # Increase sensitivity until expected number of spots is detected
    while sensitivity <= sensitivity_limit:
        subimage_coordinates = []
        subimages = []

        i_max, j_max = unravel_index(image.argmax(), image.shape)
        i_min, j_min = unravel_index(image.argmin(), image.shape)
        max_diff = image[i_max, j_max] - image[i_min, j_min]
        data_max = filters.maximum_filter(image, filter_window_size)
        data_min = filters.minimum_filter(image, filter_window_size)

        # Determine threshold
        i = sensitivity
        threshold = max_diff / i

        # Filter the parts of the image with variance in intensity greater
        # than the threshold
        maxima = (image == data_max)
        diff = ((data_max - data_min) > threshold)
        maxima[diff == 0] = 0

        labeled, num_objects = ndimage.label(maxima)

        slices = ndimage.find_objects(labeled)

        (x_center_last, y_center_last) = (-10, -10)

        # Go through these parts and crop the subimages based on the neighborhood_size
        # value
        for dy, dx in slices:
            x_center = (dx.start + dx.stop - 1) / 2
            y_center = (dy.start + dy.stop - 1) / 2

            # Make sure we don't detect spots on the top of each other
            tab = tuple(
                map(operator.sub, (x_center_last, y_center_last),
                    (x_center, y_center)))

            subimage = image[int(dy.start - 2.5):int(dy.stop + 2.5),
                             int(dx.start - 2.5):int(dx.stop + 2.5)]

            if subimage.shape[0] == 0 or subimage.shape[1] == 0:
                continue

            if (subimage > spot_factor * avg_intensity).sum() < 6:
                continue

            # if spots detected too close keep the brightest one
            if (len(subimages) > 0) and (math.hypot(tab[0], tab[1]) <
                                         (scale / 2)):
                if numpy.sum(subimage) > numpy.sum(
                        subimages[len(subimages) - 1]):
                    subimages.pop()
                    subimage_coordinates.pop()
                    subimage_coordinates.append((x_center, y_center))
                    subimages.append(subimage)
            else:
                subimage_coordinates.append((x_center, y_center))
                subimages.append(subimage)

            (x_center_last, y_center_last) = (x_center, y_center)

        # Take care of outliers
        expected_spots = numpy.prod(number_of_spots)
        clean_subimages, clean_subimage_coordinates = FilterOutliers(
            image, subimages, subimage_coordinates, expected_spots)
        if len(clean_subimages) >= numpy.prod(number_of_spots):
            break

        if sensitivity > 4:
            step = 4
        sensitivity += step

    return clean_subimages, clean_subimage_coordinates
Пример #49
0
def join_bins(bin_edges, probabilities, min_prob=0.05):
    """Join bins until at least the minimum probability is contained.

    By joining adjacent bins, find the configuration with the maximum
    number of bins that each contain at least a certain probability.

    Parameters
    ----------
    bin_edges : iterable of 2-tuple
        Upper and lower bounds associated with each bin.
    probabilities : array-like
        Probabilities in each bin. The contiguous ranges where bin joining
        must be attempted will automatically be determined.
    min_prob : float
        The minimum probability (inclusive) per (final) bin.
        
    Returns
    -------
    bin_edges : list of 2-tuple
        List containing the new bin edges.
    probabilities : array
        Probabilities corresponding to the above bins.               

    Raises
    ------
    ValueError : If the number of bin edges does not match the number 
        of probabilities.
    ValueError : If the sum of all `probabilities` does not exceed `min_prob`.

    """
    if len(bin_edges) != len(probabilities):
        raise ValueError("Length of bin_edges and probabilities must match.")

    probabilities = np.asarray(probabilities)

    if np.sum(probabilities) <= min_prob:
        raise ValueError("Sum of probabilities must exceed min_prob.")

    max_i = probabilities.shape[0] - 1

    def _join(start_i, end_i):
        """Return new bin edges and probabilities after a join.
        
        Parameters
        ----------
        start_i : int
            Beginning of the join.
        end_i : int
            End of the join.
            
        Returns
        -------
        bin_edges : list of 2-tuple
            List containing the new bin edges.
        probabilities : array
            Probabilities corresponding to the above bins.             
            
        """
        new_bin_edges = []
        new_probabilities = []

        # Remove all but the first index within the join window.
        for i in filterfalse(
            lambda x: x in range(start_i + 1, end_i + 1), range(max_i + 1),
        ):
            if i == start_i:
                new_bin_edges.append((bin_edges[start_i][0], bin_edges[end_i][1],))
                new_probabilities.append(np.sum(probabilities[start_i : end_i + 1]))
            else:
                new_bin_edges.append(bin_edges[i])
                new_probabilities.append(probabilities[i])

        return join_bins(
            bin_edges=new_bin_edges, probabilities=new_probabilities, min_prob=min_prob,
        )

    # Identify regions with low probabilities.
    join_mask = probabilities < min_prob

    if not np.any(join_mask):
        # Joining is complete.
        return (bin_edges, probabilities)

    # Find the contiguous clusters.
    labelled, n_clusters = label(join_mask)

    variations = []

    # Carry out contiguous bin joining around all clusters.

    for cluster_i in range(1, n_clusters + 1):
        cluster_indices = np.where(labelled == cluster_i)[0]
        cluster_bounds = (cluster_indices[0], cluster_indices[-1])
        # Also consider the adjacent bins, since this may be needed
        # in some cases.
        join_bounds = tuple(
            np.clip(np.array([cluster_bounds[0] - 1, cluster_bounds[1] + 1]), 0, max_i)
        )
        for start_i in range(*join_bounds):
            # Optimisation: prevent 'orphan' bins on the left.
            if join_bounds[0] == 0 and start_i != 0:
                continue
            for end_i in range(start_i + 1, join_bounds[1] + 1):
                # Optimisation: prevent 'orphan' bins on the right.
                if join_bounds[1] == max_i and end_i != max_i:
                    continue

                # If the sum of probabilities between `start_i` and `end_i`
                # exceeds the minimum threshold, join the bins.
                if np.sum(probabilities[start_i : end_i + 1]) >= min_prob:
                    variations.append(_join(start_i, end_i))

    # Return the 'best' variation - the set of bins with the lowest variability,
    # measured using the standard deviation of the probabilities. Only sets with
    # the largest number of bins will be considered here.
    lengths = [len(variation[0]) for variation in variations]
    max_length = max(lengths)
    long_variations = [
        variation for variation in variations if len(variation[0]) == max_length
    ]
    variation_stds = [np.std(variation[1]) for variation in long_variations]
    min_index = np.argsort(variation_stds)[0]
    return long_variations[min_index]
Пример #50
0
def _detect_sources(data, thresholds, npixels, filter_kernel=None,
                    connectivity=8, mask=None, deblend_skip=False):
    """
    Detect sources above a specified threshold value in an image and
    return a `~photutils.segmentation.SegmentationImage` object.

    Detected sources must have ``npixels`` connected pixels that are
    each greater than the ``threshold`` value.  If the filtering option
    is used, then the ``threshold`` is applied to the filtered image.
    The input ``mask`` can be used to mask pixels in the input data.
    Masked pixels will not be included in any source.

    This function does not deblend overlapping sources.  First use this
    function to detect sources followed by
    :func:`~photutils.segmentation.deblend_sources` to deblend sources.

    Parameters
    ----------
    data : array_like
        The 2D array of the image.

    thresholds : array-like of floats or arrays
        The data value or pixel-wise data values to
        be used for the detection thresholds. A 2D
        ``threshold`` must have the same shape as ``data``. See
        `~photutils.segmentation.detect_threshold` for one way to create
        a ``threshold`` image.

    npixels : int
        The number of connected pixels, each greater than ``threshold``,
        that an object must have to be detected.  ``npixels`` must be a
        positive integer.

    filter_kernel : array-like (2D) or `~astropy.convolution.Kernel2D`, optional
        The 2D array of the kernel used to filter the image before
        thresholding.  Filtering the image will smooth the noise and
        maximize detectability of objects with a shape similar to the
        kernel.

    connectivity : {4, 8}, optional
        The type of pixel connectivity used in determining how pixels
        are grouped into a detected source. The options are 4 or
        8 (default). 4-connected pixels touch along their edges.
        8-connected pixels touch along their edges or corners. For
        reference, SourceExtractor uses 8-connected pixels.

    mask : array_like of bool, optional
        A boolean mask, with the same shape as the input ``data``, where
        `True` values indicate masked pixels.  Masked pixels will not be
        included in any source.

    deblend_skip : bool, optional
        If `True` do not include the segmentation image in the output
        list for any threshold level where the number of detected
        sources is less than 2.  This is useful for source deblending
        and improves its performance.

    Returns
    -------
    segment_image : list of `~photutils.segmentation.SegmentationImage`
        A list of 2D segmentation images, with the same shape as
        ``data``, where sources are marked by different positive integer
        values.  A value of zero is reserved for the background.  If no
        sources are found for a given threshold, then the output list
        will contain `None` for that threshold.  Also see the
        ``deblend_skip`` keyword.
    """
    from scipy import ndimage

    if (npixels <= 0) or (int(npixels) != npixels):
        raise ValueError('npixels must be a positive integer, got '
                         f'"{npixels}"')

    if mask is not None:
        if mask.shape != data.shape:
            raise ValueError('mask must have the same shape as the input '
                             'image.')

    if filter_kernel is not None:
        data = _filter_data(data, filter_kernel, mode='constant',
                            fill_value=0.0, check_normalization=True)

    selem = _make_binary_structure(data.ndim, connectivity)

    segms = []
    for threshold in thresholds:
        # ignore RuntimeWarning caused by > comparison when data contains NaNs
        with warnings.catch_warnings():
            warnings.simplefilter('ignore', category=RuntimeWarning)
            data2 = data > threshold

        if mask is not None:
            data2 &= ~mask

        # return if threshold was too high to detect any sources
        if np.count_nonzero(data2) == 0:
            warnings.warn('No sources were found.', NoDetectionsWarning)
            if deblend_skip:
                continue
            else:
                segms.append(None)
                continue

        segm_img, _ = ndimage.label(data2, structure=selem)

        # remove objects with less than npixels
        # NOTE:  for typical data, making the cutout images is ~10x faster
        # than using segm_img directly
        segm_slices = ndimage.find_objects(segm_img)
        for i, slices in enumerate(segm_slices):
            cutout = segm_img[slices]
            segment_mask = (cutout == (i + 1))
            if np.count_nonzero(segment_mask) < npixels:
                cutout[segment_mask] = 0

        if np.count_nonzero(segm_img) == 0:
            warnings.warn('No sources were found.', NoDetectionsWarning)
            if deblend_skip:
                continue
            else:
                segms.append(None)
                continue

        segm = object.__new__(SegmentationImage)
        segm._data = segm_img

        if deblend_skip and segm.nlabels == 1:
            continue
        else:
            segm.relabel_consecutive()
            segms.append(segm)

    return segms
def segment_glomeruli3d(input_dir, output_dir, slice_names):
    """
    Original implementation from Anna's script
    :param input_dir:
    :param output_dir:
    :param slice_names:
    :param voxel_xy:
    :param voxel_z:
    :return:
    """

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    num = 0
    mask = io.imread(input_dir + "/" + slice_names[0])
    l0 = np.zeros_like(mask)

    labels = []
    limsize = int(float(glomeruli_maxrad))
    nfiles = [output_dir + "/" + x for x in slice_names]

    # label
    for i in range(len(slice_names)):
        mask = io.imread(input_dir + "/" + slice_names[i])
        l, n = ndimage.label(mask)

        labels.append(np.zeros_like(l))
        for j in range(n):  # FOR EACH label
            ind = np.where(l == j + 1)  # Indices Of the current label
            ls = np.unique(l0[ind])
            ls = ls[np.where(
                ls > 0
            )]  # Get the connections current_label -> last_layer_label
            if len(ls) == 0:
                num += 1
                labels[-1][ind] = num

            if len(ls) == 1:
                labels[-1][ind] = ls[0]

            if len(ls) > 1:
                labels[-1][ind] = ls[0]  # Assign to target (first encountered)
                for k in range(1, len(ls)):  # FOREACH all other connections
                    for s in range(len(
                            labels)):  # Go through all layers and remove them
                        labels[s] = np.where(labels[s] == ls[k], ls[0],
                                             labels[s])
        l0 = labels[-1]

        # if number of layers exceeds limit, save the first layer
        if len(labels) > limsize:
            mask = labels.pop(0)
            fname = nfiles.pop(0)
            tifffile.imsave(fname, img_as_int(mask), compress=5)

    # save remaining layers
    for i in range(len(labels)):
        mask = labels.pop(0)
        fname = nfiles.pop(0)
        tifffile.imsave(fname, img_as_int(mask), compress=5)
Пример #52
0
async def setup_learner():
    await download_file(export_file_url, path / export_file_name)
    try:
        img_new = cv2.imread(str(path), cv2.IMREAD_COLOR)
        img_new = cv2.fastNlMeansDenoisingColored(img_new, None, 10, 10, 7, 21)
        img_sv = img_new
        img_test = img_sv
        img = img_new
        r = img.copy()
        r[:, :, 0] = 0
        r[:, :, 1] = 0
        img = r
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        test_r = img
        im_gray = cv2.cvtColor(r, cv2.COLOR_BGR2GRAY)
        im_blur = cv2.GaussianBlur(im_gray, (5, 5), 0)
        kernel_sharpening = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
        im_sharp = cv2.filter2D(im_blur, -1, kernel_sharpening)
        img = im_sharp
        th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                    cv2.THRESH_BINARY, 11, 2)
        img = im_sharp
        ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
        kernel = np.ones((3, 3), np.uint8)
        opening = cv2.morphologyEx(thresh3,
                                   cv2.MORPH_OPEN,
                                   kernel,
                                   iterations=2)
        ret, th = cv2.threshold(thresh3, 0, 255,
                                cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        kernel = np.ones((3, 3), np.uint8)
        opening = cv2.morphologyEx(th, cv2.MORPH_OPEN, kernel, iterations=2)
        sure_bg = cv2.dilate(th, kernel, iterations=3)
        dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
        ret, sure_fg = cv2.threshold(dist_transform,
                                     0.005 * dist_transform.max(), 255, 0)
        sure_fg = np.uint8(sure_fg)
        unknown = cv2.subtract(sure_bg, sure_fg)
        ret, markers = cv2.connectedComponents(sure_fg)
        markers = markers + 1
        markers[unknown == 255] = 0
        markers = cv2.watershed(img_sv, markers)
        img_sv[markers == -1] = [0, 255, 0]
        img_sv[markers == 1] = [0, 0, 0]
        from skimage.filters import threshold_otsu
        thresh_val = threshold_otsu(opening)
        mask = np.where(opening > thresh_val, 1, 0)
        if np.sum(mask == 0) < np.sum(mask == 1):
            mask = np.where(mask, 0, 1)
        from scipy import ndimage
        labels, nlabels = ndimage.label(mask)
        all_cords = {}
        for label_ind, label_coords in enumerate(ndimage.find_objects(labels)):
            cell = im_gray[label_coords]
            all_cords[label_ind] = label_coords
            if np.product(cell.shape) < 10:
                mask = np.where(labels == label_ind + 1, 0, mask)
        labels, nlabels = ndimage.label(mask)
        i = 0
        res = {}
        for ii, obj_indices in enumerate(
                ndimage.find_objects(labels)[0:nlabels]):
            cell = img_sv[obj_indices]
            res[i] = cell
            i = i + 1
        i = 0
        features = {}
        for i in res:
            gcolor = res[i]
            h, w, _ = gcolor.shape
            ggray = np.array([[gcolor[i, j, 2] for j in range(w)]
                              for i in range(h)],
                             dtype=np.uint8)
            area = np.sum(
                np.sum([[1.0 for j in range(w) if ggray[i, j]]
                        for i in range(h)]))
            mean_area = area / (h * w)
            r, b, g = np.sum(
                [gcolor[i, j] for j in range(w)
                 for i in range(h)], axis=0) / (area * 256)
            _, _, eigen_value = pca(ggray)
            eccentricity = eigen_value[0] / eigen_value[1]
            l = [
                mean_area, r, b, g, eigen_value[0], eigen_value[1],
                eccentricity
            ]
            features[i] = np.array(l)
            i = i + 1
        out = {}
        #learn = load_learner(path, export_file_name)
        #Change Working directory of pkl file
        model = keras.models.load_model('../input/weight/weights.pkl')
        out = {}
        for i in features:
            out[i] = model.predict(np.array([features[i]]))
        good = not_good = 0
        for i in out:
            s = res[i]
            if np.argmax(out[i][0]) == 0:
                good += 1
                x1 = all_cords[i][0].start
                y1 = all_cords[i][1].start
                x2 = all_cords[i][1].stop
                y2 = all_cords[i][0].stop
                cv2.rectangle(img_test, (x2, x1), (y1, y2), (255, 0, 0), 8)
            else:
                x1 = all_cords[i][0].start
                y1 = all_cords[i][1].start
                x2 = all_cords[i][1].stop
                y2 = all_cords[i][0].stop
                not_good += 1
                cv2.rectangle(img_test, (x2, x1), (y1, y2), (0, 0, 255), 3)
        p = (good / (good + not_good) * 100)
        print("Number of good grain :", good)
        print("Number of impure grains or impurity:", not_good)
        print("Percentage Purity is:", p)
        return p
    except RuntimeError as e:
        if len(e.args) > 0 and 'CPU-only machine' in e.args[0]:
            print(e)
            message = "\n\nThis model was trained with an old version of fastai and will not work in a CPU environment.\n\nPlease update the fastai library in your training environment and export your model again.\n\nSee instructions for 'Returning to work' at https://course.fast.ai."
            raise RuntimeError(message)
        else:
            raise
Пример #53
0
 def test_bundle_of_tubes(self):
     im = ps.generators.bundle_of_tubes(shape=[101, 101, 1], spacing=10)
     labels, N = spim.label(input=im)
     assert N == 100
Пример #54
0
 def test_lattice_spheres_triangular(self):
     im = ps.generators.lattice_spheres(shape=[101, 101],
                                        radius=5,
                                        lattice='triangular')
     labels, N = spim.label(input=~im)
     assert N == 85
Пример #55
0
def regionprops(label_image,
                properties=['Area', 'Centroid'],
                intensity_image=None):
    """Measure properties of labelled image regions.

    Parameters
    ----------
    label_image : (N, M) ndarray
        Labelled input image.
    properties : {'all', list}
        Shape measurements to be determined for each labelled image region.
        Default is `['Area', 'Centroid']`. The following properties can be
        determined:

        * Area : int
           Number of pixels of region.

        * BoundingBox : tuple
           Bounding box `(min_row, min_col, max_row, max_col)`

        * CentralMoments : (3, 3) ndarray
            Central moments (translation invariant) up to 3rd order.

                mu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i }

            where the sum is over the `x`, `y` coordinates of the region,
            and `x_c` and `y_c` are the coordinates of the region's centroid.

        * Centroid : array
            Centroid coordinate tuple `(row, col)`.

        * ConvexArea : int
            Number of pixels of convex hull image.

        * ConvexImage : (H, J) ndarray
            Binary convex hull image which has the same size as bounding box.

        * Coordinates : (N, 2) ndarray
            Coordinate list `(row, col)` of the region.

        * Eccentricity : float
            Eccentricity of the ellipse that has the same second-moments as the
            region. The eccentricity is the ratio of the distance between its
            minor and major axis length. The value is between 0 and 1.

        * EquivDiameter : float
            The diameter of a circle with the same area as the region.

        * EulerNumber : int
            Euler number of region. Computed as number of objects (= 1)
            subtracted by number of holes (8-connectivity).

        * Extent : float
            Ratio of pixels in the region to pixels in the total bounding box.
            Computed as `Area / (rows*cols)`

        * FilledArea : int
            Number of pixels of filled region.

        * FilledImage : (H, J) ndarray
            Binary region image with filled holes which has the same size as
            bounding box.

        * HuMoments : tuple
            Hu moments (translation, scale and rotation invariant).

        * Image : (H, J) ndarray
            Sliced binary region image which has the same size as bounding box.

        * MajorAxisLength : float
            The length of the major axis of the ellipse that has the same
            normalized second central moments as the region.

        * MaxIntensity: float
            Value with the greatest intensity in the region.

        * MeanIntensity: float
            Value with the mean intensity in the region.

        * MinIntensity: float
            Value with the least intensity in the region.

        * MinorAxisLength : float
            The length of the minor axis of the ellipse that has the same
            normalized second central moments as the region.

        * Moments : (3, 3) ndarray
            Spatial moments up to 3rd order.

                m_ji = sum{ array(x, y) * x^j * y^i }

            where the sum is over the `x`, `y` coordinates of the region.

        * NormalizedMoments : (3, 3) ndarray
            Normalized moments (translation and scale invariant) up to 3rd
            order.

                nu_ji = mu_ji / m_00^[(i+j)/2 + 1]

            where `m_00` is the zeroth spatial moment.

        * Orientation : float
            Angle between the X-axis and the major axis of the ellipse that has
            the same second-moments as the region. Ranging from `-pi/2` to
            `pi/2` in counter-clockwise direction.

        * Perimeter : float
            Perimeter of object which approximates the contour as a line
            through the centers of border pixels using a 4-connectivity.

        * Solidity : float
            Ratio of pixels in the region to pixels of the convex hull image.

        * WeightedCentralMoments : (3, 3) ndarray
            Central moments (translation invariant) of intensity image up to
            3rd order.

                wmu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i }

            where the sum is over the `x`, `y` coordinates of the region,
            and `x_c` and `y_c` are the coordinates of the region's centroid.

        * WeightedCentroid : array
            Centroid coordinate tuple `(row, col)` weighted with intensity
            image.

        * WeightedHuMoments : tuple
            Hu moments (translation, scale and rotation invariant) of intensity
            image.

        * WeightedMoments : (3, 3) ndarray
            Spatial moments of intensity image up to 3rd order.

                wm_ji = sum{ array(x, y) * x^j * y^i }

            where the sum is over the `x`, `y` coordinates of the region.

        * WeightedNormalizedMoments : (3, 3) ndarray
            Normalized moments (translation and scale invariant) of intensity
            image up to 3rd order.

                wnu_ji = wmu_ji / wm_00^[(i+j)/2 + 1]

            where `wm_00` is the zeroth spatial moment (intensity-weighted
            area).

    intensity_image : (N, M) ndarray, optional
        Intensity image with same size as labelled image. Default is None.

    Returns
    -------
    properties : list of dicts
        List containing a property dict for each region. The property dicts
        contain all the specified properties plus a 'Label' field.

    References
    ----------
    .. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing:
           Core Algorithms. Springer-Verlag, London, 2009.
    .. [2] B. Jähne. Digital Image Processing. Springer-Verlag,
           Berlin-Heidelberg, 6. edition, 2005.
    .. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image
           Features, from Lecture notes in computer science, p. 676. Springer,
           Berlin, 1993.
    .. [4] http://en.wikipedia.org/wiki/Image_moment

    Examples
    --------
    >>> from skimage.data import coins
    >>> from skimage.morphology import label
    >>> img = coins() > 110
    >>> label_img = label(img)
    >>> props = regionprops(label_img)
    >>> props[0]['Centroid'] # centroid of first labelled object
    """
    if not np.issubdtype(label_image.dtype, 'int'):
        raise TypeError('labelled image must be of integer dtype')

    # determine all properties if nothing specified
    if properties == 'all':
        properties = PROPS

    props = []

    objects = ndimage.find_objects(label_image)
    for i, sl in enumerate(objects):
        label = i + 1

        # create property dict for current label
        obj_props = {}
        props.append(obj_props)

        obj_props['Label'] = label

        array = (label_image[sl] == label).astype('double')

        # upper left corner of object bbox
        r0 = sl[0].start
        c0 = sl[1].start

        m = _moments.central_moments(array, 0, 0, 3)
        # centroid
        cr = m[0, 1] / m[0, 0]
        cc = m[1, 0] / m[0, 0]
        mu = _moments.central_moments(array, cr, cc, 3)

        # elements of the inertia tensor [a b; b c]
        a = mu[2, 0] / mu[0, 0]
        b = mu[1, 1] / mu[0, 0]
        c = mu[0, 2] / mu[0, 0]
        # eigen values of inertia tensor
        l1 = (a + c) / 2 + sqrt(4 * b**2 + (a - c)**2) / 2
        l2 = (a + c) / 2 - sqrt(4 * b**2 + (a - c)**2) / 2

        # cached results which are used by several properties
        _filled_image = None
        _convex_image = None
        _nu = None

        if 'Area' in properties:
            obj_props['Area'] = m[0, 0]

        if 'BoundingBox' in properties:
            obj_props['BoundingBox'] = (r0, c0, sl[0].stop, sl[1].stop)

        if 'Centroid' in properties:
            obj_props['Centroid'] = cr + r0, cc + c0

        if 'CentralMoments' in properties:
            obj_props['CentralMoments'] = mu

        if 'ConvexArea' in properties:
            if _convex_image is None:
                _convex_image = convex_hull_image(array)
            obj_props['ConvexArea'] = np.sum(_convex_image)

        if 'ConvexImage' in properties:
            if _convex_image is None:
                _convex_image = convex_hull_image(array)
            obj_props['ConvexImage'] = _convex_image

        if 'Coordinates' in properties:
            rr, cc = np.nonzero(array)
            obj_props['Coordinates'] = np.vstack((rr + r0, cc + c0)).T

        if 'Eccentricity' in properties:
            if l1 == 0:
                obj_props['Eccentricity'] = 0
            else:
                obj_props['Eccentricity'] = sqrt(1 - l2 / l1)

        if 'EquivDiameter' in properties:
            obj_props['EquivDiameter'] = sqrt(4 * m[0, 0] / PI)

        if 'EulerNumber' in properties:
            if _filled_image is None:
                _filled_image = ndimage.binary_fill_holes(array, STREL_8)
            euler_array = _filled_image != array
            _, num = ndimage.label(euler_array, STREL_8)
            obj_props['EulerNumber'] = -num

        if 'Extent' in properties:
            obj_props['Extent'] = m[0, 0] / (array.shape[0] * array.shape[1])

        if 'HuMoments' in properties:
            if _nu is None:
                _nu = _moments.normalized_moments(mu, 3)
            obj_props['HuMoments'] = _moments.hu_moments(_nu)

        if 'Image' in properties:
            obj_props['Image'] = array

        if 'FilledArea' in properties:
            if _filled_image is None:
                _filled_image = ndimage.binary_fill_holes(array, STREL_8)
            obj_props['FilledArea'] = np.sum(_filled_image)

        if 'FilledImage' in properties:
            if _filled_image is None:
                _filled_image = ndimage.binary_fill_holes(array, STREL_8)
            obj_props['FilledImage'] = _filled_image

        if 'MajorAxisLength' in properties:
            obj_props['MajorAxisLength'] = 4 * sqrt(l1)

        if 'MinorAxisLength' in properties:
            obj_props['MinorAxisLength'] = 4 * sqrt(l2)

        if 'Moments' in properties:
            obj_props['Moments'] = m

        if 'NormalizedMoments' in properties:
            if _nu is None:
                _nu = _moments.normalized_moments(mu, 3)
            obj_props['NormalizedMoments'] = _nu

        if 'Orientation' in properties:
            if a - c == 0:
                if b > 0:
                    obj_props['Orientation'] = -PI / 4.
                else:
                    obj_props['Orientation'] = PI / 4.
            else:
                obj_props['Orientation'] = -0.5 * atan2(2 * b, (a - c))

        if 'Perimeter' in properties:
            obj_props['Perimeter'] = perimeter(array, 4)

        if 'Solidity' in properties:
            if _convex_image is None:
                _convex_image = convex_hull_image(array)
            obj_props['Solidity'] = m[0, 0] / np.sum(_convex_image)

        if intensity_image is not None:
            weighted_array = array * intensity_image[sl]

            wm = _moments.central_moments(weighted_array, 0, 0, 3)
            # weighted centroid
            wcr = wm[0, 1] / wm[0, 0]
            wcc = wm[1, 0] / wm[0, 0]
            wmu = _moments.central_moments(weighted_array, wcr, wcc, 3)

            # cached results which are used by several properties
            _wnu = None
            _vals = None

            if 'MaxIntensity' in properties:
                if _vals is None:
                    _vals = weighted_array[array.astype('bool')]
                obj_props['MaxIntensity'] = np.max(_vals)

            if 'MeanIntensity' in properties:
                if _vals is None:
                    _vals = weighted_array[array.astype('bool')]
                obj_props['MeanIntensity'] = np.mean(_vals)

            if 'MinIntensity' in properties:
                if _vals is None:
                    _vals = weighted_array[array.astype('bool')]
                obj_props['MinIntensity'] = np.min(_vals)

            if 'WeightedCentralMoments' in properties:
                obj_props['WeightedCentralMoments'] = wmu

            if 'WeightedCentroid' in properties:
                obj_props['WeightedCentroid'] = wcr + r0, wcc + c0

            if 'WeightedHuMoments' in properties:
                if _wnu is None:
                    _wnu = _moments.normalized_moments(wmu, 3)
                obj_props['WeightedHuMoments'] = _moments.hu_moments(_wnu)

            if 'WeightedMoments' in properties:
                obj_props['WeightedMoments'] = wm

            if 'WeightedNormalizedMoments' in properties:
                if _wnu is None:
                    _wnu = _moments.normalized_moments(wmu, 3)
                obj_props['WeightedNormalizedMoments'] = _wnu

    return props
Пример #56
0
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.copyMakeBorder(thresh, 1, 1, 1, 1, cv2.BORDER_CONSTANT, 0)
#cv2.imshow("Thresh", thresh)

# compute the exact Euclidean distance from every binary
# pixel to the nearest zero pixel, then find peaks in this
# distance map
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=20, labels=thresh)

# perform a connected component analysis on the local peaks,
# using 8-connectivity, then appy the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))

circles = np.empty((0, 3), int)

# loop over the unique labels returned by the Watershed
# algorithm
for label in np.unique(labels):
    # if the label is zero, we are examining the 'background'
    # so simply ignore it
    if label == 0:
        continue

    # otherwise, allocate memory for the label region and draw
    # it on the mask
Пример #57
0
    def extract_particles(self, segmentation):
        """
        Saves particle centers into output .star file, after dismissing regions
        that are too big to contain a particle.

        Args:
            segmentation: Segmentation of the micrograph into noise and particle projections.
        """
        segmentation = segmentation[self.query_size // 2 - 1:-self.query_size // 2,
                                    self.query_size // 2 - 1:-self.query_size // 2]
        labeled_segments, _ = ndimage.label(segmentation, np.ones((3, 3)))
        values, repeats = np.unique(labeled_segments, return_counts=True)

        values_to_remove = np.where(repeats > self.max_size ** 2)
        values = np.take(values, values_to_remove)
        values = np.reshape(values, (1, 1, np.prod(values.shape)), 'F')

        labeled_segments = np.reshape(labeled_segments, (labeled_segments.shape[0],
                                                         labeled_segments.shape[1], 1), 'F')
        matrix1 = np.repeat(labeled_segments, values.shape[2], 2)
        matrix2 = np.repeat(values, matrix1.shape[0], 0)
        matrix2 = np.repeat(matrix2, matrix1.shape[1], 1)

        matrix3 = np.equal(matrix1, matrix2)
        matrix4 = np.sum(matrix3, 2)

        segmentation[np.where(matrix4 == 1)] = 0
        labeled_segments, _ = ndimage.label(segmentation, np.ones((3, 3)))

        max_val = np.amax(np.reshape(labeled_segments, (np.prod(labeled_segments.shape))))
        center = center_of_mass(segmentation, labeled_segments, np.arange(1, max_val))
        center = np.rint(center)

        img = np.zeros((segmentation.shape[0], segmentation.shape[1]))
        img[center[:, 0].astype(int), center[:, 1].astype(int)] = 1
        y, x = np.ogrid[-self.moa:self.moa+1, -self.moa:self.moa+1]
        element = x*x+y*y <= self.moa * self.moa
        img = binary_dilation(img, structure=element)
        labeled_img, _ = ndimage.label(img, np.ones((3, 3)))
        values, repeats = np.unique(labeled_img, return_counts=True)
        y = np.where(repeats == np.count_nonzero(element))
        y = np.array(y)
        y = y.astype(int)
        y = np.reshape(y, (np.prod(y.shape)), 'F')
        y -= 1
        center = center[y, :]

        center = center + (self.query_size // 2 - 1) * np.ones(center.shape)
        center = center + (self.query_size // 2 - 1) * np.ones(center.shape)
        center = center + np.ones(center.shape)

        center = config.apple.mrc_shrink_factor * center

        # swap columns to align with Relion
        center = center[:, [1, 0]]

        # first column is x; second column is y - offset by margins that were discarded from the image
        center[:, 0] += config.apple.mrc_margin_left
        center[:, 1] += config.apple.mrc_margin_top

        if self.output_directory is not None:
            basename = os.path.basename(self.filename)
            name_str, ext = os.path.splitext(basename)

            applepick_path = os.path.join(self.output_directory, "{}_applepick.star".format(name_str))
            with open(applepick_path, "w") as f:
                np.savetxt(f, ["data_root\n\nloop_\n_rlnCoordinateX #1\n_rlnCoordinateY #2"], fmt='%s')
                np.savetxt(f, center, fmt='%d %d')

        return center
Пример #58
0
    def pull_spots(self,
                   plane_data,
                   grain_params,
                   imgser_dict,
                   tth_tol=0.25,
                   eta_tol=1.,
                   ome_tol=1.,
                   npdiv=2,
                   threshold=10,
                   eta_ranges=[
                       (-np.pi, np.pi),
                   ],
                   ome_period=(-np.pi, np.pi),
                   dirname='results',
                   filename=None,
                   output_format='text',
                   save_spot_list=False,
                   quiet=True,
                   check_only=False,
                   interp='nearest'):
        """
        Exctract reflection info from a rotation series encoded as an
        OmegaImageseries object
        """

        # grain parameters
        rMat_c = makeRotMatOfExpMap(grain_params[:3])
        tVec_c = grain_params[3:6]

        # grab omega ranges from first imageseries
        #
        # WARNING: all imageseries AND all wedges within are assumed to have
        # the same omega values; put in a check that they are all the same???
        oims0 = imgser_dict[imgser_dict.keys()[0]]
        ome_ranges = [
            np.radians([i['ostart'], i['ostop']])
            for i in oims0.omegawedges.wedges
        ]

        # delta omega in DEGREES grabbed from first imageseries in the dict
        delta_ome = oims0.omega[0, 1] - oims0.omega[0, 0]

        # make omega grid for frame expansion around reference frame
        # in DEGREES
        ndiv_ome, ome_del = make_tolerance_grid(
            delta_ome,
            ome_tol,
            1,
            adjust_window=True,
        )

        # generate structuring element for connected component labeling
        if ndiv_ome == 1:
            label_struct = ndimage.generate_binary_structure(2, 2)
        else:
            label_struct = ndimage.generate_binary_structure(3, 3)

        # simulate rotation series
        sim_results = self.simulate_rotation_series(plane_data, [
            grain_params,
        ],
                                                    eta_ranges=eta_ranges,
                                                    ome_ranges=ome_ranges,
                                                    ome_period=ome_period)

        # patch vertex generator (global for instrument)
        tol_vec = 0.5 * np.radians([
            -tth_tol, -eta_tol, -tth_tol, eta_tol, tth_tol, eta_tol, tth_tol,
            -eta_tol
        ])

        # prepare output if requested
        if filename is not None and output_format.lower() == 'hdf5':
            this_filename = os.path.join(dirname, filename)
            writer = io.GrainDataWriter_h5(os.path.join(dirname, filename),
                                           self.write_config(), grain_params)

        # =====================================================================
        # LOOP OVER PANELS
        # =====================================================================
        iRefl = 0
        compl = []
        output = dict.fromkeys(self.detectors)
        for detector_id in self.detectors:
            # initialize text-based output writer
            if filename is not None and output_format.lower() == 'text':
                output_dir = os.path.join(dirname, detector_id)
                if not os.path.exists(output_dir):
                    os.makedirs(output_dir)
                this_filename = os.path.join(output_dir, filename)
                writer = io.PatchDataWriter(this_filename)

            # grab panel
            panel = self.detectors[detector_id]
            instr_cfg = panel.config_dict(self.chi, self.tvec)
            native_area = panel.pixel_area  # pixel ref area

            # pull out the OmegaImageSeries for this panel from input dict
            ome_imgser = imgser_dict[detector_id]

            # extract simulation results
            sim_results_p = sim_results[detector_id]
            hkl_ids = sim_results_p[0][0]
            hkls_p = sim_results_p[1][0]
            ang_centers = sim_results_p[2][0]
            xy_centers = sim_results_p[3][0]
            ang_pixel_size = sim_results_p[4][0]

            # now verify that full patch falls on detector...
            # ???: strictly necessary?
            #
            # patch vertex array from sim
            nangs = len(ang_centers)
            patch_vertices = (np.tile(ang_centers[:, :2],
                                      (1, 4)) + np.tile(tol_vec,
                                                        (nangs, 1))).reshape(
                                                            4 * nangs, 2)
            ome_dupl = np.tile(ang_centers[:, 2],
                               (4, 1)).T.reshape(len(patch_vertices), 1)

            # find vertices that all fall on the panel
            det_xy, _ = xrdutil._project_on_detector_plane(
                np.hstack([patch_vertices, ome_dupl]), panel.rmat, rMat_c,
                self.chi, panel.tvec, tVec_c, self.tvec, panel.distortion)
            _, on_panel = panel.clip_to_panel(det_xy, buffer_edges=True)

            # all vertices must be on...
            patch_is_on = np.all(on_panel.reshape(nangs, 4), axis=1)
            patch_xys = det_xy.reshape(nangs, 4, 2)[patch_is_on]

            # re-filter...
            hkl_ids = hkl_ids[patch_is_on]
            hkls_p = hkls_p[patch_is_on, :]
            ang_centers = ang_centers[patch_is_on, :]
            xy_centers = xy_centers[patch_is_on, :]
            ang_pixel_size = ang_pixel_size[patch_is_on, :]

            # TODO: add polygon testing right here!
            # done <JVB 06/21/16>
            if check_only:
                patch_output = []
                for i_pt, angs in enumerate(ang_centers):
                    # the evaluation omegas;
                    # expand about the central value using tol vector
                    ome_eval = np.degrees(angs[2]) + ome_del

                    # ...vectorize the omega_to_frame function to avoid loop?
                    frame_indices = [
                        ome_imgser.omega_to_frame(ome)[0] for ome in ome_eval
                    ]
                    if -1 in frame_indices:
                        if not quiet:
                            msg = """
                            window for (%d%d%d) falls outside omega range
                            """ % tuple(hkls_p[i_pt, :])
                            print(msg)
                        continue
                    else:
                        these_vertices = patch_xys[i_pt]
                        ijs = panel.cartToPixel(these_vertices)
                        ii, jj = polygon(ijs[:, 0], ijs[:, 1])
                        contains_signal = False
                        for i_frame in frame_indices:
                            contains_signal = contains_signal or np.any(
                                ome_imgser[i_frame][ii, jj] > threshold)
                        compl.append(contains_signal)
                        patch_output.append((ii, jj, frame_indices))
            else:
                # make the tth,eta patches for interpolation
                patches = xrdutil.make_reflection_patches(
                    instr_cfg,
                    ang_centers[:, :2],
                    ang_pixel_size,
                    omega=ang_centers[:, 2],
                    tth_tol=tth_tol,
                    eta_tol=eta_tol,
                    rMat_c=rMat_c,
                    tVec_c=tVec_c,
                    distortion=panel.distortion,
                    npdiv=npdiv,
                    quiet=True,
                    beamVec=self.beam_vector)

                # GRAND LOOP over reflections for this panel
                patch_output = []
                for i_pt, patch in enumerate(patches):

                    # strip relevant objects out of current patch
                    vtx_angs, vtx_xy, conn, areas, xy_eval, ijs = patch

                    prows, pcols = areas.shape
                    nrm_fac = areas / float(native_area)
                    nrm_fac = nrm_fac / np.min(nrm_fac)

                    # grab hkl info
                    hkl = hkls_p[i_pt, :]
                    hkl_id = hkl_ids[i_pt]

                    # edge arrays
                    tth_edges = vtx_angs[0][0, :]
                    delta_tth = tth_edges[1] - tth_edges[0]
                    eta_edges = vtx_angs[1][:, 0]
                    delta_eta = eta_edges[1] - eta_edges[0]

                    # need to reshape eval pts for interpolation
                    xy_eval = np.vstack(
                        [xy_eval[0].flatten(), xy_eval[1].flatten()]).T

                    # the evaluation omegas;
                    # expand about the central value using tol vector
                    ome_eval = np.degrees(ang_centers[i_pt, 2]) + ome_del

                    # ???: vectorize the omega_to_frame function to avoid loop?
                    frame_indices = [
                        ome_imgser.omega_to_frame(ome)[0] for ome in ome_eval
                    ]

                    if -1 in frame_indices:
                        if not quiet:
                            msg = """
                            window for (%d%d%d) falls outside omega range
                            """ % tuple(hkl)
                            print(msg)
                        continue
                    else:
                        # initialize spot data parameters
                        # !!! maybe change these to nan to not f**k up writer
                        peak_id = -999
                        sum_int = None
                        max_int = None
                        meas_angs = None
                        meas_xy = None

                        # quick check for intensity
                        contains_signal = False
                        patch_data_raw = []
                        for i_frame in frame_indices:
                            tmp = ome_imgser[i_frame][ijs[0], ijs[1]]
                            contains_signal = contains_signal or np.any(
                                tmp > threshold)
                            patch_data_raw.append(tmp)
                            pass
                        patch_data_raw = np.stack(patch_data_raw, axis=0)
                        compl.append(contains_signal)

                        if contains_signal:
                            # initialize patch data array for intensities
                            if interp.lower() == 'bilinear':
                                patch_data = np.zeros(
                                    (len(frame_indices), prows, pcols))
                                for i, i_frame in enumerate(frame_indices):
                                    patch_data[i] = \
                                        panel.interpolate_bilinear(
                                            xy_eval,
                                            ome_imgser[i_frame],
                                            pad_with_nans=False
                                        ).reshape(prows, pcols)  # * nrm_fac
                            elif interp.lower() == 'nearest':
                                patch_data = patch_data_raw  # * nrm_fac
                            else:
                                msg = "interpolation option " + \
                                    "'%s' not understood"
                                raise (RuntimeError, msg % interp)

                            # now have interpolated patch data...
                            labels, num_peaks = ndimage.label(
                                patch_data > threshold, structure=label_struct)
                            slabels = np.arange(1, num_peaks + 1)

                            if num_peaks > 0:
                                peak_id = iRefl
                                coms = np.array(
                                    ndimage.center_of_mass(patch_data,
                                                           labels=labels,
                                                           index=slabels))
                                if num_peaks > 1:
                                    center = np.r_[patch_data.shape] * 0.5
                                    center_t = np.tile(center, (num_peaks, 1))
                                    com_diff = coms - center_t
                                    closest_peak_idx = np.argmin(
                                        np.sum(com_diff**2, axis=1))
                                else:
                                    closest_peak_idx = 0
                                    pass  # end multipeak conditional
                                coms = coms[closest_peak_idx]
                                # meas_omes = \
                                #     ome_edges[0] + (0.5 + coms[0])*delta_ome
                                meas_omes = \
                                    ome_eval[0] + coms[0]*delta_ome
                                meas_angs = np.hstack([
                                    tth_edges[0] + (0.5 + coms[2]) * delta_tth,
                                    eta_edges[0] + (0.5 + coms[1]) * delta_eta,
                                    mapAngle(np.radians(meas_omes), ome_period)
                                ])

                                # intensities
                                #   - summed is 'integrated' over interpolated
                                #     data
                                #   - max is max of raw input data
                                sum_int = np.sum(patch_data[
                                    labels == slabels[closest_peak_idx]])
                                max_int = np.max(patch_data_raw[
                                    labels == slabels[closest_peak_idx]])
                                # ???: Should this only use labeled pixels?
                                # Those are segmented from interpolated data,
                                # not raw; likely ok in most cases.

                                # need MEASURED xy coords
                                gvec_c = anglesToGVec(meas_angs,
                                                      chi=self.chi,
                                                      rMat_c=rMat_c,
                                                      bHat_l=self.beam_vector)
                                rMat_s = makeOscillRotMat(
                                    [self.chi, meas_angs[2]])
                                meas_xy = gvecToDetectorXY(
                                    gvec_c,
                                    panel.rmat,
                                    rMat_s,
                                    rMat_c,
                                    panel.tvec,
                                    self.tvec,
                                    tVec_c,
                                    beamVec=self.beam_vector)
                                if panel.distortion is not None:
                                    # FIXME: distortion handling
                                    meas_xy = panel.distortion[0](
                                        np.atleast_2d(meas_xy),
                                        panel.distortion[1],
                                        invert=True).flatten()
                                    pass
                                # FIXME: why is this suddenly necessary???
                                meas_xy = meas_xy.squeeze()
                                pass  # end num_peaks > 0
                        else:
                            patch_data = patch_data_raw
                            pass  # end contains_signal
                        # write output
                        if filename is not None:
                            if output_format.lower() == 'text':
                                writer.dump_patch(peak_id, hkl_id, hkl,
                                                  sum_int, max_int,
                                                  ang_centers[i_pt], meas_angs,
                                                  xy_centers[i_pt], meas_xy)
                            elif output_format.lower() == 'hdf5':
                                xyc_arr = xy_eval.reshape(prows, pcols,
                                                          2).transpose(
                                                              2, 0, 1)
                                writer.dump_patch(
                                    detector_id, iRefl, peak_id, hkl_id,
                                    hkl, tth_edges, eta_edges,
                                    np.radians(ome_eval), xyc_arr, ijs,
                                    frame_indices, patch_data,
                                    ang_centers[i_pt], xy_centers[i_pt],
                                    meas_angs, meas_xy)
                            pass  # end conditional on write output
                        pass  # end conditional on check only
                        patch_output.append([
                            peak_id,
                            hkl_id,
                            hkl,
                            sum_int,
                            max_int,
                            ang_centers[i_pt],
                            meas_angs,
                            meas_xy,
                        ])
                        iRefl += 1
                    pass  # end patch conditional
                pass  # end patch loop
            output[detector_id] = patch_output
            if filename is not None and output_format.lower() == 'text':
                writer.close()
            pass  # end detector loop
        if filename is not None and output_format.lower() == 'hdf5':
            writer.close()
        return compl, output
Пример #59
0
    def peak_finding(self,
                     im,
                     transformed,
                     roi=False,
                     roi_pos=None,
                     background_correction=None):
        start = time.time()
        img = np.copy(im)
        if background_correction is None and self.background_correction:
            img = self.subtract_background(img)

        self.log(self.threshold)
        self.log(self.pixel_upper_threshold)
        self.log(self.pixel_lower_threshold)
        self.log(self.flood_steps)
        self.log(img.shape)
        self.log(img.max())
        img[img < self.threshold] = 0

        labels, num_objects = ndi.label(img)
        label_size = np.bincount(labels.ravel())

        # single photons and no noise
        mask_sp = np.where((label_size >= self.pixel_lower_threshold) &
                           (label_size < self.pixel_upper_threshold), True,
                           False)
        if sum(mask_sp) == 0:
            coor_sp = []
        else:
            label_mask_sp = mask_sp[labels.ravel()].reshape(labels.shape)
            labels_sp = label_mask_sp * labels
            labels_sp, n_s = ndi.label(labels_sp)
            coor_sp = ndi.center_of_mass(img, labels_sp,
                                         range(1,
                                               labels_sp.max() + 1))

        # multiple photons
        mask_mp = np.where((label_size >= self.pixel_upper_threshold) &
                           (label_size < np.max(label_size)), True, False)
        if sum(mask_mp) > 0:
            label_mask_mp = mask_mp[labels.ravel()].reshape(labels.shape)
            labels_mp = label_mask_mp * labels
            labels_mp, n_m = ndi.label(labels_mp)
            for i in range(1, sum(mask_mp) + 1):
                objects = ndi.find_objects(labels_mp == i)
                if len(objects) == 0:
                    self.print('No beads found!')
                    return None
                slice_x, slice_y = objects[0]
                roi_i = np.copy(img[slice_x, slice_y])
                max_i = np.max(roi_i)
                step = (0.95 * max_i - self.threshold) / self.flood_steps
                multiple = False
                coor_tmp = np.array(
                    ndi.center_of_mass(roi_i,
                                       ndi.label(roi_i)[0]))
                for k in range(1, self.flood_steps + 1):
                    new_threshold = self.threshold + k * step
                    roi_i[roi_i < new_threshold] = 0
                    labels_roi, n_i = ndi.label(roi_i)
                    if n_i > 1:
                        roi_label_size = np.bincount(labels_roi.ravel())
                        if np.max(roi_label_size[1:]
                                  ) <= self.pixel_upper_threshold:
                            if len(roi_label_size) == 3 and roi_label_size.min(
                            ) < self.roi_min_size:
                                break
                            else:
                                multiple = True
                                coordinates_roi = np.array(
                                    ndi.center_of_mass(roi_i, labels_roi,
                                                       range(1, n_i + 1)))
                                [
                                    coor_sp.append(coordinates_roi[j] +
                                                   np.array((slice_x.start,
                                                             slice_y.start)))
                                    for j in range(len(coordinates_roi))
                                ]
                                break
                if not multiple:
                    coor_sp.append(coor_tmp +
                                   np.array((slice_x.start, slice_y.start)))

        coor = np.array(coor_sp)
        if len(coor) == 0:
            return None
        if roi:
            try:
                return np.round(coor)[0]
            except IndexError:
                return None
        else:
            #peaks_2d = np.round(coor)
            peaks_2d = coor
            if roi_pos is not None and peaks_2d is not None:
                peaks_2d += roi_pos
            if self.aligning:
                if transformed:
                    self.tf_peaks_align_ref = np.copy(peaks_2d)
                else:
                    self.peaks_align_ref = np.copy(peaks_2d)
            else:
                if transformed:
                    self.tf_peaks = peaks_2d
                    if self.orig_tf_peaks is None:
                        self.orig_tf_peaks = np.copy(self.tf_peaks)
                else:
                    self.peaks = np.copy(peaks_2d)
        end = time.time()
        self.log('duration: ', end - start)
        self.print('Number of peaks found: ', peaks_2d.shape[0])
Пример #60
0
def extract_background_pid(img,
                           P_id,
                           slit_height=25,
                           return_mask=False,
                           exclude_top_and_bottom=True,
                           timit=False):
    """
    This function marks all relevant pixels for extraction. Extracts the background (ie the inter-order regions = everything outside the order stripes)
    from the original 2D spectrum to a sparse matrix containing only relevant pixels.
    
    INPUT:
    'img'                     : 2D echelle spectrum [np.array]
    'P_id'                    : dictionary of the form of {order: np.poly1d} (as returned by make_P_id / identify_stripes)
    'slit_height'             : half the total slit height in pixels
    'return_mask'             : boolean - do you want to return the mask of the background locations as well?
    'exclude_top_and_bottom'  : boolean - do you want to exclude the top and bottom bits (where there are usually incomplete orders)
    'timit'                   : for timing tests...
    
    OUTPUT:
    'mat.tocsc()'  : scipy.sparse_matrix containing the locations and values of the inter-order regions    
    'bg_mask'      : boolean array containing the location of what is considered background (ie the inter-order space)
    """

    if timit:
        start_time = time.time()


#     logging.info('Extracting background...')
    print('Extracting background...')

    ny, nx = img.shape
    xx = np.arange(nx, dtype='f8')
    yy = np.arange(ny, dtype='f8')
    x_grid, y_grid = np.meshgrid(xx, yy, copy=False)
    bg_mask = np.ones((ny, nx), dtype=bool)

    for o, p in sorted(P_id.items()):

        # order trace
        y = np.poly1d(p)(xx)

        # distance from order trace
        distance = y_grid - y.repeat(ny).reshape((nx, ny)).T
        indices = abs(distance) > slit_height

        # include in global mask
        bg_mask *= indices

    final_bg_mask = bg_mask.copy()
    # in case we want to exclude the top and bottom parts where incomplete orders are located
    if exclude_top_and_bottom:
        print(
            'WARNING: this fix works for the current Veloce CCD layout only!!!'
        )
        labelled_mask, nobj = label(bg_mask)
        # WARNING: this fix works for the current Veloce CCD layout only!!!
        topleftnumber = labelled_mask[ny - 1, 0]
        toprightnumber = labelled_mask[ny - 1, nx - 1]
        #         bottomleftnumber = labelled_mask[0,0]
        bottomrightnumber = labelled_mask[0, nx - 1]
        final_bg_mask[labelled_mask == topleftnumber] = False
        final_bg_mask[labelled_mask == toprightnumber] = False
        final_bg_mask[labelled_mask == bottomrightnumber] = False

    mat = sparse.coo_matrix((np.squeeze(np.array(img[final_bg_mask])),
                             (y_grid[final_bg_mask], x_grid[final_bg_mask])),
                            shape=(ny, nx))
    #     return mat.tocsr()

    if timit:
        print('Elapsed time: ', time.time() - start_time, ' seconds')

    if not return_mask:
        return mat.tocsc()
    else:
        return mat.tocsc(), final_bg_mask