def _calculateSingleId(self): """ Calculates statistics (see method calculate) when ids is a single (int) id. Does not calculate statistics on the mean. """ # do calculations for all segments self.mean = ndimage.mean(input=self.data, labels=self.labels, index=self._ids) self.std = ndimage.standard_deviation(input=self.data, labels=self.labels, index=self._ids) # maximum bug fix extr = ndimage.extrema(input=self.data, labels=self.labels, index=self._ids) extr_bug = ndimage.extrema(input=-self.data, labels=self.labels, index=self._ids) # put extrema results in data arrays (self.min, self.max) = (extr[0], extr[1]) self.max = -extr_bug[0] self.minPos = extr[2][0] #self.maxPos = extr[3][0] self.maxPos = extr_bug[2][0]
def fit_gauss(ph): for i in range(4): # bepaal de counts en de bingrootte in een range van 0 t/m 1000 ADC y, bins = histogram(ph[i], bins=500, range=[0, 1000]) # loop for elke plaat x = (bins[:-1] + bins[1:])/2. #let op neem bins om het midden te vinden van de bin if y[np.random.random_integers(200, 300)] != 0 : # ter controle of de data van de detector betrouwbaar is, aangezien plaat 4 503 geen goede data bevatte 3-01-2013 # vanwege bartels (2012) kiezen we waar de ADC waarde tussen 150 en 410 zit voor de gauss fit, schat geeft de elementen waar tussen gefit moet worden. schat = np.where((x > 150) & (x < 600)) # geeft een tweeledig array terug x1 = x[schat[0]] # geeft de waarde van de elementen gevonden met de determinatie hierboven in het eerste element #bovenstaande kan ook met x1 = fit_xa[np.where(x>150) & (x< 420)] y1 = y[schat] # bepaling van de count in de meting max_min = ndimage.extrema(y1) max_y = ndimage.extrema(y1)[1] #maximale count y waarde piek van de gauss!) min_x = max_min[0] # de laagste waarde van de count max_x = max_min[1] # hoogste waarde van de count -> a waarde in de gauss fit b_temp = max_min[3] b_place = b_temp[0] # b waarde b = x1[b_place] # de b-waarde van de gauss curve bound1 = max_x - (max_x - min_x)*0.75 if (max_x- min_x) <= 50: bound2 = max_x + (max_x - min_x)*1.5 else: bound2 = max_x + (max_x - min_x) x2 = x1.compress((bound1 <= x1) & (x1 < bound2)) y2 = y1.compress((bound1 <= x1) & (x1 < bound2)) #popt, pcov = curve_fit(func1, x1, y1, [200, 250, 50] ) # werkende fit met een handmatige guess kleine verschillen. orde van 0.2 popt, pcov = curve_fit(func1, x1, y1, [max_x, b, 20] ) # fit met guess gebruikt werkt ook pylab.plot(func1(range(0,600), *popt), '--') peak = popt[1] if i == 0: MIP1 = peak MPV1.append(MIP1) #bij herhalen van de loop oor ander station append deze regel op de juiste manier? elif i == 1: MIP2 = peak MPV2.append(MIP2) elif i == 2: MIP3 = peak MPV3.append(MIP3) elif i == 3: MIP4 = peak MPV4.append(MIP4) print 'The MPV of detector',i + 1, 'lies at', peak, 'ADC' else: print 'The data of the detector ',i + 1, 'could not be fitted to a gauss curve'
def bounding_boxes(seg): lbl, nlbl = ndimage.label(seg) class_label, _, minxy, maxxy = ndimage.extrema(seg, lbl, index=np.arange( 1, nlbl + 1)) return class_label, minxy, maxxy
def test_extrema(shape, chunks, has_lbls, ind): a = np.random.random(shape) d = da.from_array(a, chunks=chunks) lbls = None d_lbls = None if has_lbls: lbls = np.zeros(a.shape, dtype=np.int64) lbls += ((a < 0.5).astype(lbls.dtype) + (a < 0.25).astype(lbls.dtype) + (a < 0.125).astype(lbls.dtype) + (a < 0.0625).astype(lbls.dtype)) d_lbls = da.from_array(lbls, chunks=d.chunks) a_r = spnd.extrema(a, lbls, ind) d_r = dask_image.ndmeasure.extrema(d, d_lbls, ind) assert len(a_r) == len(d_r) for i in irange(len(a_r)): a_r_i = np.array(a_r[i]) if a_r_i.dtype != d_r[i].dtype: wrn.warn( "Encountered a type mismatch." " Expected type, %s, but got type, %s." "" % (str(a_r_i.dtype), str(d_r[i].dtype)), RuntimeWarning) assert a_r_i.shape == d_r[i].shape assert np.allclose(a_r_i, np.array(d_r[i]), equal_nan=True)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] leny = 400 maxy = data.max() logging.info("Plot data max = %s", maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): h = leny - int((v * leny) / maxy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def normalized_per_object(image, labels): """Normalize the intensities of each object to the [0, 1] range.""" nobjects = labels.max() objects = np.arange(nobjects + 1) lmin, lmax = scind.extrema(image, labels, objects)[:2] # Divisor is the object's max - min, or 1 if they are the same. divisor = np.ones((nobjects + 1,)) divisor[lmax > lmin] = (lmax - lmin)[lmax > lmin] return (image - lmin[labels]) / divisor[labels]
def test_extrema02(): labels = np.array([1, 2]) for type in types: input = np.array([[1, 2], [3, 4]], type) output1 = ndimage.extrema(input, labels=labels, index=2) output2 = ndimage.minimum(input, labels=labels, index=2) output3 = ndimage.maximum(input, labels=labels, index=2) output4 = ndimage.minimum_position(input, labels=labels, index=2) output5 = ndimage.maximum_position(input, labels=labels, index=2) assert_equal(output1, (output2, output3, output4, output5))
def test_extrema01(): "extrema 1" labels = np.array([1, 0], bool) for type in types: input = np.array([[1, 2], [3, 4]], type) output1 = ndimage.extrema(input, labels=labels) output2 = ndimage.minimum(input, labels=labels) output3 = ndimage.maximum(input, labels=labels) output4 = ndimage.minimum_position(input, labels=labels) output5 = ndimage.maximum_position(input, labels=labels) assert_equal(output1, (output2, output3, output4, output5))
def lut(im, table, limits=None): "Look up each pixel of an image in a table" if limits is None: limits = extrema(im) lo, hi = limits ny, nx, nc = im.shape #sizes(im) bins = len(table) for y in range(0, ny): for x in range(0, nx): for c in range(0, nc): v = (im[y, x, c] - lo) / (hi - lo) * (bins - 1) im[y, x, c] = table[int(v)]
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def f(array, il): i = il[0] # This function returns (mini, maxi), the indexes of the max # and min of the array. They return the *lowest* possible # such indexes, thus the max(0, ...) below. min_, max_, mini, maxi = extrema(array) #print array, (min_, max_, mini, maxi), mini[0]+i-halfwidth, maxi[0]+i-halfwidth minima[max(0, mini[0]+i-halfwidth)] += 1 maxima[ maxi[0]+i-halfwidth ] += 1 il[0] += 1 return 0
def test_extrema01(): labels = np.array([1, 0], bool) for type in types: input = np.array([[1, 2], [3, 4]], type) output1 = ndimage.extrema(input, labels=labels) output2 = ndimage.minimum(input, labels=labels) output3 = ndimage.maximum(input, labels=labels) output4 = ndimage.minimum_position(input, labels=labels) output5 = ndimage.maximum_position(input, labels=labels) assert_equal(output1, (output2, output3, output4, output5))
def scipy_features(image): histo = ndimage.measurements.histogram(image, 0, 255, 10) mini, maxi, minpos, maxpos = ndimage.extrema(image) return numpy.concatenate(( histo, minpos, maxpos, ndimage.measurements.center_of_mass(image), [ mini, maxi, ] ))
def test_extrema04(): labels = [1, 2, 0, 4] for type in types: input = np.array([[5, 4, 2, 5], [3, 7, 8, 2], [1, 5, 1, 1]], type) output1 = ndimage.extrema(input, labels, [1, 2]) output2 = ndimage.minimum(input, labels, [1, 2]) output3 = ndimage.maximum(input, labels, [1, 2]) output4 = ndimage.minimum_position(input, labels, [1, 2]) output5 = ndimage.maximum_position(input, labels, [1, 2]) assert_array_almost_equal(output1[0], output2) assert_array_almost_equal(output1[1], output3) assert_array_almost_equal(output1[2], output4) assert_array_almost_equal(output1[3], output5)
def grad_graph(img, interactive=True): """ gradient graph: use gradient to define different objects and then segment the image to those objects :param img: image to process :return: fragmentation """ blur_radius = 2 imgf = ndimage.gaussian_filter(img, blur_radius) scharr2 = np.array([[ -3, 0, 3], [-10, 0, 10], [ -3, 0, 3]]) grad = [convolve2d(imgf[:, :, i], scharr2, boundary='symm', mode='same') for i in np.arange(3)] grad = np.sum(np.abs(grad), 0, dtype=np.uint8) imgf[ndimage.gaussian_filter(grad/np.mean(grad), 3) < 1] = 0 threshold = np.mean(imgf) mask = np.any(imgf > threshold, -1) labeled, nr_objects = ndimage.label(mask) # labeled: a width X height matrix, in which each pixel of object i is given index i sizes = ndimage.sum(mask, labeled, range(nr_objects + 1)) #plt.title('objects are colored') #plt.imshow(labeled) #plt.show() labeled[(sizes < 1000)[labeled]] = 0 # filter noise label_im = np.searchsorted(np.unique(labeled), labeled) # TODO: can we do better with widths and heights (Eran: I think it is the way to calc width/height) widths_heights = np.abs(np.diff((np.array(ndimage.extrema(mask, label_im, range(np.max(label_im) + 1))[2:])), axis=0)[0, :, :]) label_im[(widths_heights[:, 0] < 5) | (widths_heights[:, 0] > 800) | (widths_heights[:, 1] > 300)] = 0 label_im = np.searchsorted(np.unique(label_im), label_im) #plt.hist(widths_heights[:, 0],100) width histogram #plt.show() # now given the objects return their positions (frags) frags = ndimage.find_objects(label_im, max_label=np.max(label_im)) if interactive: # show example of one of the words img2 = np.array(img, copy=True) img2[label_im == 0] = 0 plt.imshow(img2) plt.show() # fragment_to_show = len(frags)//2 plt.imshow(img[frags[fragment_to_show]]) plt.show() return frags
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def test_extrema02(): "extrema 2" labels = np.array([1, 2]) for type in types: input = np.array([[1, 2], [3, 4]], type) output1 = ndimage.extrema(input, labels=labels, index=2) output2 = ndimage.minimum(input, labels=labels, index=2) output3 = ndimage.maximum(input, labels=labels, index=2) output4 = ndimage.minimum_position(input, labels=labels, index=2) output5 = ndimage.maximum_position(input, labels=labels, index=2) assert_equal(output1, (output2, output3, output4, output5))
def test_extrema03(): labels = np.array([[1, 2], [2, 3]]) for type in types: input = np.array([[1, 2], [3, 4]], type) output1 = ndimage.extrema(input, labels=labels, index=[2, 3, 8]) output2 = ndimage.minimum(input, labels=labels, index=[2, 3, 8]) output3 = ndimage.maximum(input, labels=labels, index=[2, 3, 8]) output4 = ndimage.minimum_position(input, labels=labels, index=[2, 3, 8]) output5 = ndimage.maximum_position(input, labels=labels, index=[2, 3, 8]) assert_array_almost_equal(output1[0], output2) assert_array_almost_equal(output1[1], output3) assert_array_almost_equal(output1[2], output4) assert_array_almost_equal(output1[3], output5)
def mark_peaks_of_trace(self, absolute=None, relative=None): '''Absolute means that the peak-finding is based on the raw value. Relative is a fraction of the maximum. ''' # Calculate the cutoff # The logic is inflated for sanity check if (absolute is not None) and (relative is None): ekg_cutoff = absolute elif (relative is not None) and (absolute is None): ekg_cutoff = self.global_ekg_max * relative else: # Probably not necessary, as ekg_cutoff would be undefined raise RuntimeError("Must sepcify ekg cutoff in one way!") # Stuff to store internally. self.spike_times = [] # The times in EKG ms offset self.spike_number = [] # The number of spikes self.spike_heights = [] # The amplitudes # For each EKG trace for n, tr in enumerate(self.traces): # Find the area above the cutoff screen = (tr > ekg_cutoff) # Label each and record the number of labels labels, spike_count = ndimage.label(screen) # Find the extrema; locations and amplitudes indexs_of_spikes = range(1, spike_count + 1) # This conditional should not be necessary. # TODO: scipy bug-tracker is down . . . report this one if indexs_of_spikes != []: ext = ndimage.extrema(tr, labels=labels, index=indexs_of_spikes) else: ext = ([],[],[],[]) # Break out the results of the extrema, ignore min-related values min_vals, max_vals, min_locs, max_locs = ext # Store the values on a per-experiment basis # The arrays appended _could_ be empty, but will be an object . . . # so the offsets will still be correct. self.spike_times.append( array(max_locs).flatten() ) self.spike_number.append( spike_count ) self.spike_heights.append( array(max_vals).flatten() )
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.spots, self.app.translation, self.app.scaling, self.app.rotation = FindGridSpots( data, self.gridsize) self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.spots, self.app.translation, self.app.scaling, self.app.rotation = FindGridSpots(data, self.gridsize) self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) assert isinstance(objects, cpo.Objects) has_pixels = objects.areas > 0 labels = objects.small_removed_segmented kept_labels = objects.segmented neighbor_objects = workspace.object_set.get_objects(self.neighbors_name.value) assert isinstance(neighbor_objects, cpo.Objects) neighbor_labels = neighbor_objects.small_removed_segmented # # Need to add in labels touching border. # unedited_segmented = neighbor_objects.unedited_segmented touching_border = np.zeros(np.max(unedited_segmented) + 1, bool) touching_border[unedited_segmented[0, :]] = True touching_border[unedited_segmented[-1, :]] = True touching_border[unedited_segmented[:, 0]] = True touching_border[unedited_segmented[:, -1]] = True touching_border[0] = False touching_border_mask = touching_border[unedited_segmented] if np.any(touching_border) and \ np.all(~ touching_border_mask[neighbor_labels]): # Add the border labels if any were excluded touching_border_object_number = np.cumsum(touching_border) + \ np.max(neighbor_labels) touching_border_mask = touching_border_mask & neighbor_labels == 0 neighbor_labels[touching_border_mask] = touching_border_object_number[ unedited_segmented[touching_border_mask]] nobjects = np.max(labels) nneighbors = np.max(neighbor_labels) nkept_objects = objects.count _, object_numbers = objects.relate_labels(labels, kept_labels) if self.neighbors_are_objects: neighbor_numbers = object_numbers else: _, neighbor_numbers = neighbor_objects.relate_labels( neighbor_labels, neighbor_objects.segmented) neighbor_count = np.zeros((nobjects,)) pixel_count = np.zeros((nobjects,)) first_object_number = np.zeros((nobjects,),int) second_object_number = np.zeros((nobjects,),int) first_x_vector = np.zeros((nobjects,)) second_x_vector = np.zeros((nobjects,)) first_y_vector = np.zeros((nobjects,)) second_y_vector = np.zeros((nobjects,)) angle = np.zeros((nobjects,)) percent_touching = np.zeros((nobjects,)) expanded_labels = None if self.distance_method == D_EXPAND: # Find the i,j coordinates of the nearest foreground point # to every background point i,j = scind.distance_transform_edt(labels==0, return_distances=False, return_indices=True) # Assign each background pixel to the label of its nearest # foreground pixel. Assign label to label for foreground. labels = labels[i,j] expanded_labels = labels # for display distance = 1 # dilate once to make touching edges overlap scale = S_EXPANDED if self.neighbors_are_objects: neighbor_labels = labels.copy() elif self.distance_method == D_WITHIN: distance = self.distance.value scale = str(distance) elif self.distance_method == D_ADJACENT: distance = 1 scale = S_ADJACENT else: raise ValueError("Unknown distance method: %s" % self.distance_method.value) if nneighbors > (1 if self.neighbors_are_objects else 0): first_objects = [] second_objects = [] object_indexes = np.arange(nobjects, dtype=np.int32)+1 # # First, compute the first and second nearest neighbors, # and the angles between self and the first and second # nearest neighbors # ocenters = centers_of_labels( objects.small_removed_segmented).transpose() ncenters = centers_of_labels( neighbor_objects.small_removed_segmented).transpose() areas = fix(scind.sum(np.ones(labels.shape),labels, object_indexes)) perimeter_outlines = outline(labels) perimeters = fix(scind.sum( np.ones(labels.shape), perimeter_outlines, object_indexes)) i,j = np.mgrid[0:nobjects,0:nneighbors] distance_matrix = np.sqrt((ocenters[i,0] - ncenters[j,0])**2 + (ocenters[i,1] - ncenters[j,1])**2) # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # if distance_matrix.shape[1] == 1: # a little buggy, lexsort assumes that a 2-d array of # second dimension = 1 is a 1-d array order = np.zeros(distance_matrix.shape, int) else: order = np.lexsort([distance_matrix]) first_neighbor = 1 if self.neighbors_are_objects else 0 first_object_index = order[:, first_neighbor] first_x_vector = ncenters[first_object_index,1] - ocenters[:,1] first_y_vector = ncenters[first_object_index,0] - ocenters[:,0] if nneighbors > first_neighbor+1: second_object_index = order[:, first_neighbor + 1] second_x_vector = ncenters[second_object_index,1] - ocenters[:,1] second_y_vector = ncenters[second_object_index,0] - ocenters[:,0] v1 = np.array((first_x_vector,first_y_vector)) v2 = np.array((second_x_vector,second_y_vector)) # # Project the unit vector v1 against the unit vector v2 # dot = (np.sum(v1*v2,0) / np.sqrt(np.sum(v1**2,0)*np.sum(v2**2,0))) angle = np.arccos(dot) * 180. / np.pi # Make the structuring element for dilation strel = strel_disk(distance) # # A little bigger one to enter into the border with a structure # that mimics the one used to create the outline # strel_touching = strel_disk(distance + .5) # # Get the extents for each object and calculate the patch # that excises the part of the image that is "distance" # away i,j = np.mgrid[0:labels.shape[0],0:labels.shape[1]] min_i, max_i, min_i_pos, max_i_pos =\ scind.extrema(i,labels,object_indexes) min_j, max_j, min_j_pos, max_j_pos =\ scind.extrema(j,labels,object_indexes) min_i = np.maximum(fix(min_i)-distance,0).astype(int) max_i = np.minimum(fix(max_i)+distance+1,labels.shape[0]).astype(int) min_j = np.maximum(fix(min_j)-distance,0).astype(int) max_j = np.minimum(fix(max_j)+distance+1,labels.shape[1]).astype(int) # # Loop over all objects # Calculate which ones overlap "index" # Calculate how much overlap there is of others to "index" # for object_number in object_numbers: if object_number == 0: # # No corresponding object in small-removed. This means # that the object has no pixels, e.g. not renumbered. # continue index = object_number - 1 patch = labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] npatch = neighbor_labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] # # Find the neighbors # patch_mask = patch==(index+1) extended = scind.binary_dilation(patch_mask,strel) neighbors = np.unique(npatch[extended]) neighbors = neighbors[neighbors != 0] if self.neighbors_are_objects: neighbors = neighbors[neighbors != object_number] nc = len(neighbors) neighbor_count[index] = nc if nc > 0: first_objects.append(np.ones(nc,int) * object_number) second_objects.append(neighbors) if self.neighbors_are_objects: # # Find the # of overlapping pixels. Dilate the neighbors # and see how many pixels overlap our image. Use a 3x3 # structuring element to expand the overlapping edge # into the perimeter. # outline_patch = perimeter_outlines[ min_i[index]:max_i[index], min_j[index]:max_j[index]] == object_number extended = scind.binary_dilation( (patch != 0) & (patch != object_number), strel_touching) overlap = np.sum(outline_patch & extended) pixel_count[index] = overlap if sum([len(x) for x in first_objects]) > 0: first_objects = np.hstack(first_objects) reverse_object_numbers = np.zeros( max(np.max(object_numbers), np.max(first_objects)) + 1, int) reverse_object_numbers[object_numbers] = np.arange(len(object_numbers)) + 1 first_objects = reverse_object_numbers[first_objects] second_objects = np.hstack(second_objects) reverse_neighbor_numbers = np.zeros( max(np.max(neighbor_numbers), np.max(second_objects)) + 1, int) reverse_neighbor_numbers[neighbor_numbers] = np.arange(len(neighbor_numbers)) + 1 second_objects= reverse_neighbor_numbers[second_objects] to_keep = (first_objects > 0) & (second_objects > 0) first_objects = first_objects[to_keep] second_objects = second_objects[to_keep] else: first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) if self.neighbors_are_objects: percent_touching = pixel_count * 100 / perimeters else: percent_touching = pixel_count * 100.0 / areas object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 # # Have to recompute nearest # first_object_number = np.zeros(nkept_objects, int) second_object_number = np.zeros(nkept_objects, int) if nkept_objects > (1 if self.neighbors_are_objects else 0): di = (ocenters[object_indexes[:, np.newaxis], 0] - ncenters[neighbor_indexes[np.newaxis, :], 0]) dj = (ocenters[object_indexes[:, np.newaxis], 1] - ncenters[neighbor_indexes[np.newaxis, :], 1]) distance_matrix = np.sqrt(di*di + dj*dj) distance_matrix[~ has_pixels, :] = np.inf distance_matrix[:, ~has_pixels] = np.inf # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # order = np.lexsort([distance_matrix]).astype( first_object_number.dtype) if self.neighbors_are_objects: first_object_number[has_pixels] = order[has_pixels,1] + 1 if nkept_objects > 2: second_object_number[has_pixels] = order[has_pixels,2] + 1 else: first_object_number[has_pixels] = order[has_pixels,0] + 1 if nneighbors > 1: second_object_number[has_pixels] = order[has_pixels,1] + 1 else: object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) # # Now convert all measurements from the small-removed to # the final number set. # neighbor_count = neighbor_count[object_indexes] neighbor_count[~ has_pixels] = 0 percent_touching = percent_touching[object_indexes] percent_touching[~ has_pixels] = 0 first_x_vector = first_x_vector[object_indexes] second_x_vector = second_x_vector[object_indexes] first_y_vector = first_y_vector[object_indexes] second_y_vector = second_y_vector[object_indexes] angle = angle[object_indexes] # # Record the measurements # assert(isinstance(workspace, cpw.Workspace)) m = workspace.measurements assert(isinstance(m, cpmeas.Measurements)) image_set = workspace.image_set features_and_data = [ (M_NUMBER_OF_NEIGHBORS, neighbor_count), (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number), (M_FIRST_CLOSEST_DISTANCE, np.sqrt(first_x_vector**2+first_y_vector**2)), (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number), (M_SECOND_CLOSEST_DISTANCE, np.sqrt(second_x_vector**2+second_y_vector**2)), (M_ANGLE_BETWEEN_NEIGHBORS, angle)] if self.neighbors_are_objects: features_and_data.append((M_PERCENT_TOUCHING, percent_touching)) for feature_name, data in features_and_data: m.add_measurement(self.object_name.value, self.get_measurement_name(feature_name), data) if len(first_objects) > 0: m.add_relate_measurement( self.module_num, cpmeas.NEIGHBORS, self.object_name.value, self.object_name.value if self.neighbors_are_objects else self.neighbors_name.value, m.image_set_number * np.ones(first_objects.shape, int), first_objects, m.image_set_number * np.ones(second_objects.shape, int), second_objects) labels = kept_labels neighbor_count_image = np.zeros(labels.shape,int) object_mask = objects.segmented != 0 object_indexes = objects.segmented[object_mask]-1 neighbor_count_image[object_mask] = neighbor_count[object_indexes] workspace.display_data.neighbor_count_image = neighbor_count_image if self.neighbors_are_objects: percent_touching_image = np.zeros(labels.shape) percent_touching_image[object_mask] = percent_touching[object_indexes] workspace.display_data.percent_touching_image = percent_touching_image image_set = workspace.image_set if self.wants_count_image.value: neighbor_cm_name = self.count_colormap.value neighbor_cm = get_colormap(neighbor_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = neighbor_cm) img = sm.to_rgba(neighbor_count_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 count_image = cpi.Image(img, masking_objects = objects) image_set.add(self.count_image_name.value, count_image) else: neighbor_cm_name = cpprefs.get_default_colormap() neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name) if self.neighbors_are_objects and self.wants_percent_touching_image: percent_touching_cm_name = self.touching_colormap.value percent_touching_cm = get_colormap(percent_touching_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = percent_touching_cm) img = sm.to_rgba(percent_touching_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 touching_image = cpi.Image(img, masking_objects = objects) image_set.add(self.touching_image_name.value, touching_image) else: percent_touching_cm_name = cpprefs.get_default_colormap() percent_touching_cm = matplotlib.cm.get_cmap(percent_touching_cm_name) if self.show_window: workspace.display_data.neighbor_cm_name = neighbor_cm_name workspace.display_data.percent_touching_cm_name = percent_touching_cm_name workspace.display_data.orig_labels = objects.segmented workspace.display_data.expanded_labels = expanded_labels workspace.display_data.object_mask = object_mask
def _extrema_x(self): # npg aggregate min/max is very slow, use scipy.ndimage instead. mi, ma, _, _ = ndi.extrema(self._xs, self._flat, self._group_idx) return mi, ma
def find_MPV(fit, conv=1): """Determine the ADC value of the MPV for each detector For pulseheights use conv = 1 For pulseintegral values use conv = 10 Returns a tuple of MPV values """ MPV1, MPV2, MPV3, MPV4 = [], [], [], [] for i in range(4): ##4 DETECTOREN try: y, bins, patches = plt.hist(fit[i], bins=linspace(0, conv * 2000 / 0.57, STEPSIZE), label="Data") x = bins[:-1] + .5 * (bins[1] - bins[0]) # A first approximation of the position of the MPV and the minimum to the left is made. Used for fit bounds and initial guess of the parameters. guess_max_x = ndimage.extrema(y.compress((conv * 150 <= x) & (x < conv * 410)))[3][0] + len(y.compress(x < conv * 150)) guess_max_x = x[guess_max_x] guess_min_x = ndimage.extrema(y.compress((conv * 53 <= x) & (x < guess_max_x)))[2][0] + len(y.compress(x < conv * 53)) guess_min_x = max([conv * 120, x[guess_min_x]]) guess_max_y = ndimage.extrema(y.compress((conv * 150 <= x) & (x < conv * 410)))[1] guess_min_y = ndimage.extrema(y.compress((conv * 53 <= x) & (x < guess_max_x)))[0] g0 = guess_max_y g1 = guess_max_x # The fit range. Since the right side of the ph histogram is most similar to a Gauss function, we do not want to set bound 2 too small. bound1 = guess_min_x + (guess_max_x - guess_min_x) / 4 if (guess_max_x - guess_min_x) <= conv * 50: bound2 = guess_max_x + (guess_max_x - guess_min_x) * 1.5 else: bound2 = guess_max_x + (guess_max_x - guess_min_x) # Fit a Gaussian to the peak. f = lambda x, a, b, c: a * exp(-((x - b) ** 2) / c) x2 = x.compress((bound1 <= x) & (x < bound2)) y2 = y.compress((bound1 <= x) & (x < bound2)) popt, pcov = optimize.curve_fit(f, x2, y2, (g0, g1, (guess_max_x - guess_min_x) / 2), sigma=sqrt(y2)) # Find the x value of the peak: peak = popt[1] print ('The MPV of the pulseheight of detector %d lies at %d ADC' % (i + 1, peak)) # Safety nets: prevent the code from terminating if an error occurs except IndexError: peak = nan print 'Apparently there is no data' except RuntimeError: peak = nan print 'Unable to make a good fit' except TypeError: peak = nan print 'Not enough data to make a proper fit' # When it uses less than three bins to make the fit you get this error except ValueError: peak = nan print 'Value Error Occured' if i == 0: MIP1 = peak elif i == 1: MIP2 = peak elif i == 2: MIP3 = peak elif i == 3: MIP4 = peak mpv = (MIP1, MIP2, MIP3, MIP4) return mpv
def measure_worms(self, workspace, labels, nworms, width): m = workspace.measurements assert isinstance(m, cpmeas.Measurements) object_name = self.straightened_objects_name.value nbins_vertical = self.number_of_segments.value nbins_horizontal = self.number_of_stripes.value params = self.read_params(workspace) if nworms == 0: # # # # # # # # # # # # # # # # # # # # # # # # Record measurements if no worms # # # # # # # # # # # # # # # # # # # # # # # for ftr in (FTR_MEAN_INTENSITY, FTR_STD_INTENSITY): for group in self.images: image_name = group.straightened_image_name.value if nbins_vertical > 1: for b in range(nbins_vertical): measurement = "_".join( (C_WORM, ftr, image_name, self.get_scale_name(None, b))) m.add_measurement(object_name, measurement, np.zeros((0))) if nbins_horizontal > 1: for b in range(nbins_horizontal): measurement = "_".join( (C_WORM, ftr, image_name, self.get_scale_name(b, None))) m.add_measurement(object_name, measurement, np.zeros((0))) if nbins_vertical > 1: for v in range(nbins_vertical): for h in range(nbins_horizontal): measurement = "_".join( (C_WORM, ftr, image_name, self.get_scale_name(h, v))) m.add_measurement(object_name, measurement, np.zeros((0))) else: # # Find the minimum and maximum i coordinate of each worm # object_set = workspace.object_set assert isinstance(object_set, cpo.ObjectSet) orig_objects = object_set.get_objects(self.objects_name.value) i,j = np.mgrid[0:labels.shape[0], 0:labels.shape[1]] min_i, max_i, _, _ = extrema(i, labels, orig_objects.indices) min_i = np.hstack(([0], min_i)) max_i = np.hstack(([labels.shape[0]], max_i)) + 1 heights = max_i - min_i # # # # # # # # # # # # # # # # # # # Create up to 3 spaces which represent the gridding # of the worm and create a coordinate mapping into # this gridding for each straightened worm # # # # # # # # # # # # # # # # # # griddings = [] if nbins_vertical > 1: scales = np.array([self.get_scale_name(None, b) for b in range(nbins_vertical)]) scales.shape = (nbins_vertical, 1) griddings += [(nbins_vertical, 1, scales)] if nbins_horizontal > 1: scales = np.array([self.get_scale_name(b, None) for b in range(nbins_horizontal)]) scales.shape = (1, nbins_horizontal) griddings += [(1, nbins_horizontal, scales)] if nbins_vertical > 1: scales = np.array([ [self.get_scale_name(h,v) for h in range(nbins_horizontal)] for v in range(nbins_vertical)]) griddings += [(nbins_vertical, nbins_horizontal, scales)] for i_dim, j_dim, scales in griddings: # # # # # # # # # # # # # # # # # # # # # # # # Start out mapping every point to a 1x1 space # # # # # # # # # # # # # # # # # # # # # # # labels1 = labels.copy() i,j = np.mgrid[0:labels.shape[0], 0:labels.shape[1]] i_frac = (i - min_i[labels]).astype(float) / heights[labels] i_frac_end = i_frac + 1.0 / heights[labels].astype(float) i_radius_frac = (i - min_i[labels]).astype(float) / (heights[labels] - 1) labels1[(i_frac >= 1) | (i_frac_end <= 0)] = 0 # # # # # # # # # # # # # # # # # # # # # # # # Map the horizontal onto the grid. # # # # # # # # # # # # # # # # # # # # # # # radii = np.array(params.radii_from_training) # # For each pixel in the image, find the center of its worm # in the j direction (the width) # j_center = int(width / 2) + width * (labels-1) # # Find which segment (from the training set) per pixel in # a fractional form # i_index = i_radius_frac * (len(radii) - 1) # # Interpolate # i_index_frac = i_index - np.floor(i_index) i_index_frac[i_index >= len(radii) - 1] = 1 i_index = np.minimum(i_index.astype(int), len(radii) - 2) r = np.ceil((radii[i_index] * (1 - i_index_frac) + radii[i_index+1] * i_index_frac)) # # Map the worm width into the space 0-1 # j_frac = (j - j_center + r) / (r * 2 + 1) j_frac_end = j_frac + 1.0 / (r * 2 + 1) labels1[(j_frac >= 1) | (j_frac_end <= 0)] = 0 # # Map the worms onto the gridding. # i_mapping = np.maximum(i_frac * i_dim, 0) i_mapping_end = np.minimum(i_frac_end * i_dim, i_dim) j_mapping = np.maximum(j_frac * j_dim, 0) j_mapping_end = np.minimum(j_frac_end * j_dim, j_dim) i_mapping = i_mapping[labels1 > 0] i_mapping_end = i_mapping_end[labels1 > 0] j_mapping = j_mapping[labels1 > 0] j_mapping_end = j_mapping_end[labels1 > 0] labels_1d = labels1[labels1 > 0] i = i[labels1 > 0] j = j[labels1 > 0] # # There are easy cases and hard cases. The easy cases are # when a pixel in the input space wholly falls in the # output space. # easy = ((i_mapping.astype(int) == i_mapping_end.astype(int)) & (j_mapping.astype(int) == j_mapping_end.astype(int))) i_src = i[easy] j_src = j[easy] i_dest = i_mapping[easy].astype(int) j_dest = j_mapping[easy].astype(int) weight = np.ones(i_src.shape) labels_src = labels_1d[easy] # # The hard cases start in one pixel in the binning space, # possibly continue through one or more intermediate pixels # in horribly degenerate cases and end in a final # partial pixel. # # More horribly, a pixel in the straightened space # might span two or more in the binning space in the I # direction, the J direction or both. # if not np.all(easy): i = i[~ easy] j = j[~ easy] i_mapping = i_mapping[~ easy] j_mapping = j_mapping[~ easy] i_mapping_end = i_mapping_end[~ easy] j_mapping_end = j_mapping_end[~ easy] labels_1d = labels_1d[~ easy] # # A pixel in the straightened space can be wholly within # a pixel in the bin space, it can straddle two pixels # or straddle two and span one or more. It can do different # things in the I and J direction. # # --- The number of pixels wholly spanned --- # i_span = np.maximum(np.floor(i_mapping_end) - np.ceil(i_mapping), 0) j_span = np.maximum(np.floor(j_mapping_end) - np.ceil(j_mapping), 0) # # --- The fraction of a pixel covered by the lower straddle # i_low_straddle = i_mapping.astype(int) + 1 - i_mapping j_low_straddle = j_mapping.astype(int) + 1 - j_mapping # # Segments that start at exact pixel boundaries and span # whole pixels have low fractions that are 1. The span # length needs to have these subtracted from it. # i_span[i_low_straddle == 1] -= 1 j_span[j_low_straddle == 1] -= 1 # # --- the fraction covered by the upper straddle # i_high_straddle = i_mapping_end - i_mapping_end.astype(int) j_high_straddle = j_mapping_end - j_mapping_end.astype(int) # # --- the total distance across the binning space # i_total = i_low_straddle + i_span + i_high_straddle j_total = j_low_straddle + j_span + j_high_straddle # # --- The fraction in the lower straddle # i_low_frac = i_low_straddle / i_total j_low_frac = j_low_straddle / j_total # # --- The fraction in the upper straddle # i_high_frac = i_high_straddle / i_total j_high_frac = j_high_straddle / j_total # # later on, the high fraction will overwrite the low fraction # for i and j hitting on a single pixel in the bin space # i_high_frac[(i_mapping.astype(int) == i_mapping_end.astype(int))] = 1 j_high_frac[(j_mapping.astype(int) == j_mapping_end.astype(int))] = 1 # # --- The fraction in spans # i_span_frac = i_span / i_total j_span_frac = j_span / j_total # # --- The number of bins touched by each pixel # i_count = (np.ceil(i_mapping_end) - np.floor(i_mapping)).astype(int) j_count = (np.ceil(j_mapping_end) - np.floor(j_mapping)).astype(int) # # --- For I and J, calculate the weights for each pixel # along each axis. # i_idx = INDEX.Indexes([i_count]) j_idx = INDEX.Indexes([j_count]) i_weights = i_span_frac[i_idx.rev_idx] j_weights = j_span_frac[j_idx.rev_idx] i_weights[i_idx.fwd_idx] = i_low_frac j_weights[j_idx.fwd_idx] = j_low_frac mask = i_high_frac > 0 i_weights[i_idx.fwd_idx[mask]+ i_count[mask] - 1] = \ i_high_frac[mask] mask = j_high_frac > 0 j_weights[j_idx.fwd_idx[mask] + j_count[mask] - 1] = \ j_high_frac[mask] # # Get indexes for the 2-d array, i_count x j_count # idx = INDEX.Indexes([i_count, j_count]) # # The coordinates in the straightened space # i_src_hard = i[idx.rev_idx] j_src_hard = j[idx.rev_idx] # # The coordinates in the bin space # i_dest_hard = i_mapping[idx.rev_idx].astype(int) + idx.idx[0] j_dest_hard = j_mapping[idx.rev_idx].astype(int) + idx.idx[1] # # The weights are the i-weight times the j-weight # # The i-weight can be found at the nth index of # i_weights relative to the start of the i_weights # for the pixel in the straightened space. # # The start is found at i_idx.fwd_idx[idx.rev_idx] # the I offset is found at idx.idx[0] # # Similarly for J. # weight_hard = (i_weights[i_idx.fwd_idx[idx.rev_idx] + idx.idx[0]] * j_weights[j_idx.fwd_idx[idx.rev_idx] + idx.idx[1]]) i_src = np.hstack((i_src, i_src_hard)) j_src = np.hstack((j_src, j_src_hard)) i_dest = np.hstack((i_dest, i_dest_hard)) j_dest = np.hstack((j_dest, j_dest_hard)) weight = np.hstack((weight, weight_hard)) labels_src = np.hstack((labels_src, labels_1d[idx.rev_idx])) self.measure_bins(workspace, i_src, j_src, i_dest, j_dest, weight, labels_src, scales, nworms)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == 1: # single point => show text text = "%g" % (data.flat[0], ) logging.info("Data value is: %s", text) # Create a big enough white space (30x200 px) of BGRA format rgb = numpy.empty((30, 200, 4), dtype=numpy.uint8) rgb.fill(255) # Get a Cairo context for that image surface = cairo.ImageSurface.create_for_data( rgb, cairo.FORMAT_ARGB32, rgb.shape[1], rgb.shape[0]) ctx = cairo.Context(surface) # Draw a black text of 20 px high ctx.set_source_rgb(0, 0, 0) ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL) ctx.set_font_size(20) ctx.move_to(5, 20) ctx.show_text(text) del ctx # ensure the context is flushed elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) disp_size = wx.Display(0).GetGeometry().GetSize() if disp_size[0] < rgb.shape[1] or disp_size[1] < rgb.shape[0]: asp_ratio = rgb.shape[1] / rgb.shape[0] if disp_size[0] / disp_size[1] < asp_ratio: self.app.magn = disp_size[0] / rgb.shape[1] else: self.app.magn = disp_size[1] / rgb.shape[0] self.app.img.Rescale(rgb.shape[1] * self.app.magn, rgb.shape[0] * self.app.magn, rgb.shape[2]) else: self.app.magn = 1 wx.CallAfter(self.app.update_view)
def _calculateArrayId(self): """ Calculates statistics (see methods calculate) when ids are array, even if ids have one element only. """ # make sure the result data structures are ok self._prepareArrays(arrays=('mean', 'std', 'min', 'max', 'minPos', 'maxPos'), widths=(1, 1, 1, 1, self.ndim, self.ndim), dtypes=(float, float, float, float, int, int)) # do calculations for each segment separately self.mean[self._ids] = ndimage.mean(input=self.data, labels=self.labels, index=self._ids) self.std[self._ids] = ndimage.standard_deviation(input=self.data, labels=self.labels, index=self._ids) extr = ndimage.extrema(input=self.data, labels=self.labels, index=self._ids) # figure out if 0 is the only id zero_id = False if isinstance(self._ids, (numpy.ndarray, list)): zero_id = (self._ids[0] == 0) else: zero_id = (self._ids == 0) # do calculations for all segments together if not zero_id: from .segment import Segment seg = Segment() locLabels = seg.keep(ids=self._ids, data=self.labels.copy()) self.mean[0] = ndimage.mean(input=self.data, labels=locLabels, index=None) self.std[0] = ndimage.standard_deviation(input=self.data, labels=locLabels, index=None) extr0 = ndimage.extrema(input=self.data, labels=locLabels, index=None) # put extrema for individual labels in data arrays (self.min[self._ids], self.max[self._ids]) = (extr[0], extr[1]) #self.max[self._ids] = -numpy.array(extr_bug[0]) if (self._ids.size == 1) and not isinstance(extr[2], list): self.minPos[self._ids] = [extr[2]] self.maxPos[self._ids] = [extr[3]] #self.maxPos[self._ids] = [extr_bug[2]] else: self.minPos[self._ids] = extr[2] self.maxPos[self._ids] = extr[3] #self.maxPos[self._ids] = extr_bug[3] # put total extrema in data arrays at index 0 if not zero_id: (self.min[0], self.max[0]) = (extr0[0], extr0[1]) #self.max[0] = -extr0_bug[0] if self.ndim == 1: self.minPos[0] = extr0[2][0] self.maxPos[0] = extr0[3][0] #self.maxPos[0] = extr0_bug[2][0] else: self.minPos[0] = extr0[2] self.maxPos[0] = extr0[3]
import scipy.misc as misc import scipy.ndimage as ndi img = misc.ascent() print(ndi.minimum(img)) print(ndi.minimum_position(img)) print(ndi.maximum(img)) print(ndi.maximum_position(img)) print(ndi.extrema(img))
""" Find at what time the temperature suddenly took off """ import sys, glob import pyfits from scipy.ndimage import extrema runid = sys.argv[1] pattern = "%s-te????.fits" % (runid) filelist = glob.glob(pattern) for file in filelist: Tarray = pyfits.open(file)[0].data Tmin, Tmax, Tminloc, Tmaxloc = extrema(Tarray) # switch to fortran array indexing Tmaxloc = [ i+1 for i in Tmaxloc[::-1] ] print "%s: max T = %.2e at %s" % (file, Tmax, Tmaxloc)
def get_mask_period_info(hours_since_beginning, lon, mask, lat=None, verbose=False): ## Get Pandas data frame of east propagation periods. ## If lat is set to None, don't calculate latitude related stuff. label_im, nE = ndimage.label(mask) if verbose: print(f'Found {str(nE)} propagation periods.') props = {} begin_hours, end_hours, indx1, indx2 = ndimage.extrema( hours_since_beginning, label_im, range(1, nE + 1)) props['duration'] = (np.array(end_hours) - np.array(begin_hours)) props['begin_indx'] = np.array(indx1)[:, 0].astype(int) props['end_indx'] = np.array(indx2)[:, 0].astype(int) props['begin_lon'] = lon[props['begin_indx']] props['end_lon'] = lon[props['end_indx']] props['lon_propagation'] = lon[props['end_indx']] - lon[ props['begin_indx']] props['total_zonal_spd'] = linregress(hours_since_beginning, lon)[0] * (111000 / 3600.0) min_lon, max_lon, indx1, indx2 = ndimage.extrema(lon, label_im, range(1, nE + 1)) props['min_lon'] = min_lon props['max_lon'] = max_lon props['segment_zonal_spd'] = 0.0 * np.arange(nE) for iii in range(nE): ii1 = props['begin_indx'][iii] ii2 = props['end_indx'][iii] + 1 props['segment_zonal_spd'][iii] = linregress( hours_since_beginning[ii1:ii2], lon[ii1:ii2])[0] * (111000 / 3600.0) if not lat is None: props['begin_lat'] = lat[props['begin_indx']] props['end_lat'] = lat[props['end_indx']] props['lat_propagation'] = lat[props['end_indx']] - lat[ props['begin_indx']] min_lat, max_lat, indx1, indx2 = ndimage.extrema( lat, label_im, range(1, nE + 1)) props['min_lat'] = min_lat props['max_lat'] = max_lat props['total_meridional_spd'] = linregress(hours_since_beginning, lat)[0] * (111000 / 3600.0) props['segment_meridional_spd'] = 0.0 * np.arange(nE) for iii in range(nE): ii1 = props['begin_indx'][iii] ii2 = props['end_indx'][iii] + 1 props['segment_meridional_spd'][iii] = linregress( hours_since_beginning[ii1:ii2], lat[ii1:ii2])[0] * (111000 / 3600.0) ## Put in to Pandas DataFrame F = pd.DataFrame.from_dict(props) return F
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) assert isinstance(objects, cpo.Objects) has_pixels = objects.areas > 0 labels = objects.small_removed_segmented kept_labels = objects.segmented neighbor_objects = workspace.object_set.get_objects( self.neighbors_name.value) assert isinstance(neighbor_objects, cpo.Objects) neighbor_labels = neighbor_objects.small_removed_segmented # # Need to add in labels touching border. # unedited_segmented = neighbor_objects.unedited_segmented touching_border = np.zeros(np.max(unedited_segmented) + 1, bool) touching_border[unedited_segmented[0, :]] = True touching_border[unedited_segmented[-1, :]] = True touching_border[unedited_segmented[:, 0]] = True touching_border[unedited_segmented[:, -1]] = True touching_border[0] = False touching_border_mask = touching_border[unedited_segmented] nobjects = np.max(labels) nkept_objects = objects.count nneighbors = np.max(neighbor_labels) if np.any(touching_border) and \ np.all(~ touching_border_mask[neighbor_labels != 0]): # Add the border labels if any were excluded touching_border_object_number = np.cumsum(touching_border) + \ np.max(neighbor_labels) touching_border_mask = touching_border_mask & (neighbor_labels == 0) neighbor_labels = neighbor_labels.copy().astype(np.int32) neighbor_labels[ touching_border_mask] = touching_border_object_number[ unedited_segmented[touching_border_mask]] _, object_numbers = objects.relate_labels(labels, kept_labels) if self.neighbors_are_objects: neighbor_numbers = object_numbers neighbor_has_pixels = has_pixels else: _, neighbor_numbers = neighbor_objects.relate_labels( neighbor_labels, neighbor_objects.segmented) neighbor_has_pixels = np.bincount(neighbor_labels.ravel())[1:] > 0 neighbor_count = np.zeros((nobjects, )) pixel_count = np.zeros((nobjects, )) first_object_number = np.zeros((nobjects, ), int) second_object_number = np.zeros((nobjects, ), int) first_x_vector = np.zeros((nobjects, )) second_x_vector = np.zeros((nobjects, )) first_y_vector = np.zeros((nobjects, )) second_y_vector = np.zeros((nobjects, )) angle = np.zeros((nobjects, )) percent_touching = np.zeros((nobjects, )) expanded_labels = None if self.distance_method == D_EXPAND: # Find the i,j coordinates of the nearest foreground point # to every background point i, j = scind.distance_transform_edt(labels == 0, return_distances=False, return_indices=True) # Assign each background pixel to the label of its nearest # foreground pixel. Assign label to label for foreground. labels = labels[i, j] expanded_labels = labels # for display distance = 1 # dilate once to make touching edges overlap scale = S_EXPANDED if self.neighbors_are_objects: neighbor_labels = labels.copy() elif self.distance_method == D_WITHIN: distance = self.distance.value scale = str(distance) elif self.distance_method == D_ADJACENT: distance = 1 scale = S_ADJACENT else: raise ValueError("Unknown distance method: %s" % self.distance_method.value) if nneighbors > (1 if self.neighbors_are_objects else 0): first_objects = [] second_objects = [] object_indexes = np.arange(nobjects, dtype=np.int32) + 1 # # First, compute the first and second nearest neighbors, # and the angles between self and the first and second # nearest neighbors # ocenters = centers_of_labels( objects.small_removed_segmented).transpose() ncenters = centers_of_labels( neighbor_objects.small_removed_segmented).transpose() areas = fix( scind.sum(np.ones(labels.shape), labels, object_indexes)) perimeter_outlines = outline(labels) perimeters = fix( scind.sum(np.ones(labels.shape), perimeter_outlines, object_indexes)) i, j = np.mgrid[0:nobjects, 0:nneighbors] distance_matrix = np.sqrt((ocenters[i, 0] - ncenters[j, 0])**2 + (ocenters[i, 1] - ncenters[j, 1])**2) # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # if distance_matrix.shape[1] == 1: # a little buggy, lexsort assumes that a 2-d array of # second dimension = 1 is a 1-d array order = np.zeros(distance_matrix.shape, int) else: order = np.lexsort([distance_matrix]) first_neighbor = 1 if self.neighbors_are_objects else 0 first_object_index = order[:, first_neighbor] first_x_vector = ncenters[first_object_index, 1] - ocenters[:, 1] first_y_vector = ncenters[first_object_index, 0] - ocenters[:, 0] if nneighbors > first_neighbor + 1: second_object_index = order[:, first_neighbor + 1] second_x_vector = ncenters[second_object_index, 1] - ocenters[:, 1] second_y_vector = ncenters[second_object_index, 0] - ocenters[:, 0] v1 = np.array((first_x_vector, first_y_vector)) v2 = np.array((second_x_vector, second_y_vector)) # # Project the unit vector v1 against the unit vector v2 # dot = (np.sum(v1 * v2, 0) / np.sqrt(np.sum(v1**2, 0) * np.sum(v2**2, 0))) angle = np.arccos(dot) * 180. / np.pi # Make the structuring element for dilation strel = strel_disk(distance) # # A little bigger one to enter into the border with a structure # that mimics the one used to create the outline # strel_touching = strel_disk(distance + .5) # # Get the extents for each object and calculate the patch # that excises the part of the image that is "distance" # away i, j = np.mgrid[0:labels.shape[0], 0:labels.shape[1]] min_i, max_i, min_i_pos, max_i_pos = \ scind.extrema(i, labels, object_indexes) min_j, max_j, min_j_pos, max_j_pos = \ scind.extrema(j, labels, object_indexes) min_i = np.maximum(fix(min_i) - distance, 0).astype(int) max_i = np.minimum(fix(max_i) + distance + 1, labels.shape[0]).astype(int) min_j = np.maximum(fix(min_j) - distance, 0).astype(int) max_j = np.minimum(fix(max_j) + distance + 1, labels.shape[1]).astype(int) # # Loop over all objects # Calculate which ones overlap "index" # Calculate how much overlap there is of others to "index" # for object_number in object_numbers: if object_number == 0: # # No corresponding object in small-removed. This means # that the object has no pixels, e.g. not renumbered. # continue index = object_number - 1 patch = labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] npatch = neighbor_labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] # # Find the neighbors # patch_mask = patch == (index + 1) extended = scind.binary_dilation(patch_mask, strel) neighbors = np.unique(npatch[extended]) neighbors = neighbors[neighbors != 0] if self.neighbors_are_objects: neighbors = neighbors[neighbors != object_number] nc = len(neighbors) neighbor_count[index] = nc if nc > 0: first_objects.append(np.ones(nc, int) * object_number) second_objects.append(neighbors) if self.neighbors_are_objects: # # Find the # of overlapping pixels. Dilate the neighbors # and see how many pixels overlap our image. Use a 3x3 # structuring element to expand the overlapping edge # into the perimeter. # outline_patch = perimeter_outlines[ min_i[index]:max_i[index], min_j[index]:max_j[index]] == object_number extended = scind.binary_dilation( (patch != 0) & (patch != object_number), strel_touching) overlap = np.sum(outline_patch & extended) pixel_count[index] = overlap if sum([len(x) for x in first_objects]) > 0: first_objects = np.hstack(first_objects) reverse_object_numbers = np.zeros( max(np.max(object_numbers), np.max(first_objects)) + 1, int) reverse_object_numbers[object_numbers] = np.arange( len(object_numbers)) + 1 first_objects = reverse_object_numbers[first_objects] second_objects = np.hstack(second_objects) reverse_neighbor_numbers = np.zeros( max(np.max(neighbor_numbers), np.max(second_objects)) + 1, int) reverse_neighbor_numbers[neighbor_numbers] = np.arange( len(neighbor_numbers)) + 1 second_objects = reverse_neighbor_numbers[second_objects] to_keep = (first_objects > 0) & (second_objects > 0) first_objects = first_objects[to_keep] second_objects = second_objects[to_keep] else: first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) if self.neighbors_are_objects: percent_touching = pixel_count * 100 / perimeters else: percent_touching = pixel_count * 100.0 / areas object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 # # Have to recompute nearest # first_object_number = np.zeros(nkept_objects, int) second_object_number = np.zeros(nkept_objects, int) if nkept_objects > (1 if self.neighbors_are_objects else 0): di = (ocenters[object_indexes[:, np.newaxis], 0] - ncenters[neighbor_indexes[np.newaxis, :], 0]) dj = (ocenters[object_indexes[:, np.newaxis], 1] - ncenters[neighbor_indexes[np.newaxis, :], 1]) distance_matrix = np.sqrt(di * di + dj * dj) distance_matrix[~has_pixels, :] = np.inf distance_matrix[:, ~neighbor_has_pixels] = np.inf # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # order = np.lexsort([distance_matrix ]).astype(first_object_number.dtype) if self.neighbors_are_objects: first_object_number[has_pixels] = order[has_pixels, 1] + 1 if nkept_objects > 2: second_object_number[has_pixels] = order[has_pixels, 2] + 1 else: first_object_number[has_pixels] = order[has_pixels, 0] + 1 if order.shape[1] > 1: second_object_number[has_pixels] = order[has_pixels, 1] + 1 else: object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) # # Now convert all measurements from the small-removed to # the final number set. # neighbor_count = neighbor_count[object_indexes] neighbor_count[~has_pixels] = 0 percent_touching = percent_touching[object_indexes] percent_touching[~has_pixels] = 0 first_x_vector = first_x_vector[object_indexes] second_x_vector = second_x_vector[object_indexes] first_y_vector = first_y_vector[object_indexes] second_y_vector = second_y_vector[object_indexes] angle = angle[object_indexes] # # Record the measurements # assert (isinstance(workspace, cpw.Workspace)) m = workspace.measurements assert (isinstance(m, cpmeas.Measurements)) image_set = workspace.image_set features_and_data = [ (M_NUMBER_OF_NEIGHBORS, neighbor_count), (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number), (M_FIRST_CLOSEST_DISTANCE, np.sqrt(first_x_vector**2 + first_y_vector**2)), (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number), (M_SECOND_CLOSEST_DISTANCE, np.sqrt(second_x_vector**2 + second_y_vector**2)), (M_ANGLE_BETWEEN_NEIGHBORS, angle) ] if self.neighbors_are_objects: features_and_data.append((M_PERCENT_TOUCHING, percent_touching)) for feature_name, data in features_and_data: m.add_measurement(self.object_name.value, self.get_measurement_name(feature_name), data) if len(first_objects) > 0: m.add_relate_measurement( self.module_num, cpmeas.NEIGHBORS, self.object_name.value, self.object_name.value if self.neighbors_are_objects else self.neighbors_name.value, m.image_set_number * np.ones(first_objects.shape, int), first_objects, m.image_set_number * np.ones(second_objects.shape, int), second_objects) labels = kept_labels neighbor_count_image = np.zeros(labels.shape, int) object_mask = objects.segmented != 0 object_indexes = objects.segmented[object_mask] - 1 neighbor_count_image[object_mask] = neighbor_count[object_indexes] workspace.display_data.neighbor_count_image = neighbor_count_image if self.neighbors_are_objects: percent_touching_image = np.zeros(labels.shape) percent_touching_image[object_mask] = percent_touching[ object_indexes] workspace.display_data.percent_touching_image = percent_touching_image image_set = workspace.image_set if self.wants_count_image.value: neighbor_cm_name = self.count_colormap.value neighbor_cm = get_colormap(neighbor_cm_name) sm = matplotlib.cm.ScalarMappable(cmap=neighbor_cm) img = sm.to_rgba(neighbor_count_image)[:, :, :3] img[:, :, 0][~object_mask] = 0 img[:, :, 1][~object_mask] = 0 img[:, :, 2][~object_mask] = 0 count_image = cpi.Image(img, masking_objects=objects) image_set.add(self.count_image_name.value, count_image) else: neighbor_cm_name = cpprefs.get_default_colormap() neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name) if self.neighbors_are_objects and self.wants_percent_touching_image: percent_touching_cm_name = self.touching_colormap.value percent_touching_cm = get_colormap(percent_touching_cm_name) sm = matplotlib.cm.ScalarMappable(cmap=percent_touching_cm) img = sm.to_rgba(percent_touching_image)[:, :, :3] img[:, :, 0][~object_mask] = 0 img[:, :, 1][~object_mask] = 0 img[:, :, 2][~object_mask] = 0 touching_image = cpi.Image(img, masking_objects=objects) image_set.add(self.touching_image_name.value, touching_image) else: percent_touching_cm_name = cpprefs.get_default_colormap() percent_touching_cm = matplotlib.cm.get_cmap( percent_touching_cm_name) if self.show_window: workspace.display_data.neighbor_cm_name = neighbor_cm_name workspace.display_data.percent_touching_cm_name = percent_touching_cm_name workspace.display_data.orig_labels = objects.segmented workspace.display_data.expanded_labels = expanded_labels workspace.display_data.object_mask = object_mask