def __init__(self, img, src, dst): nrows, ncols = img.shape cols = np.tile(np.arange(ncols), (nrows, 1)) rows = np.tile(np.arange(nrows), (ncols, 1)).T i_values = np.array(profile_line(rows, src, dst, mode='constant'), dtype=int) j_values = np.array(profile_line(cols, src, dst, mode='constant'), dtype=int) self.i_values, self.j_values = i_values, j_values self.src = src self.dst = dst
def draw_traj(all_grids ,n_grid, par_trajs, arr_size=200, field_size_cm = 100, dur_ms=5000, speed_cm=20): "Activation profile of cells out of trajectories walked by a mouse" all_grids = all_grids size2cm = int(arr_size/field_size_cm) dur_s = dur_ms/1000 traj_len_cm = int(dur_s*speed_cm) traj_len_dp = traj_len_cm*size2cm dt_s = (dur_s)/traj_len_cm #for parallel one par_idc_cm = par_trajs par_idc = par_idc_cm*size2cm-1 n_traj = par_idc.shape[0] #empty arrays traj = np.empty((n_grid,traj_len_dp)) par_traj = np.empty((n_grid,traj_len_dp,n_traj)) #draw the trajectories for j in range(n_traj): idc = par_idc[j] for i in range(n_grid): traj[i,:] = profile_line(all_grids[:,:,i], (idc,0), (idc,traj_len_dp-1)) par_traj[:,:,j] = traj # cum_par = np.sum(par_traj, axis=1)*(dt_s) return par_traj, dt_s
def __init__(self, fig, ax, profileax, plotData, startPoint=(0, 0), endPoint=(1, 1), pixelScale=1, setupOptions=None, centerCoord=(0, 0)): assert setupOptions is not None, "You must supply a SetupOptions object" self.ax = ax self.fig = fig self.profileax = profileax self.pixelScale = pixelScale self.useCenteredLine = setupOptions.useCenteredLine self.centerCoord = centerCoord self.fileName = setupOptions.imageFilePath self.plotData = plotData self.useLogData = setupOptions.useLogData if self.useCenteredLine: _, endPoint = convertLinePointsToCenteredLinePoints(startPoint, self.centerCoord) self.xy = [startPoint, endPoint] self.line = Line2D(list(zip(*self.xy))[0], list(zip(*self.xy))[1], marker='o', markerfacecolor='r', animated=True) self.ax.add_line(self.line) self.profileLineWidth = setupOptions.profileLineWidth self.profileLineData = profile_line(self.plotData, (self.xy[0][1], self.xy[0][0]), (self.xy[1][1], self.xy[1][0]), linewidth=self.profileLineWidth) if self.useCenteredLine: self.xData = self.pixelScale * (np.arange(self.profileLineData.size) - self.profileLineData.size/2) else: self.xData = self.pixelScale * np.arange(self.profileLineData.size) self.profileLine = profileax.plot(self.xData, self.profileLineData)[0] self.profileax.autoscale(enable=True, axis='x', tight=True) self.profileax.autoscale(enable=True, axis='y', tight=True) self._ind = None # the active vertex self.ax.figure.canvas.mpl_connect('draw_event', self.draw_callback) self.ax.figure.canvas.mpl_connect('button_press_event', self.button_press_callback) self.ax.figure.canvas.mpl_connect('button_release_event', self.button_release_callback) self.ax.figure.canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
def motion_notify_callback(self, event): """on mouse movement""" if self._ind is None: return if event.inaxes is None: return if event.button != 1: return x, y = event.xdata, event.ydata # print(x, y) self.xy[self._ind] = x, y if self.useCenteredLine: _, otherPoint = convertLinePointsToCenteredLinePoints((x, y), self.centerCoord) if self._ind == 0: self.xy[1] = otherPoint else: self.xy[0] = otherPoint self.line.set_data(zip(*self.xy)) self.profileLineData = profile_line(self.plotData, (self.xy[0][1], self.xy[0][0]), (self.xy[1][1], self.xy[1][0]), linewidth=self.profileLineWidth) if self.useCenteredLine: xDataLims = (-self.pixelScale*self.profileLineData.size/2, self.pixelScale*self.profileLineData.size/2) self.xData = self.pixelScale * (np.arange(self.profileLineData.size) - self.profileLineData.size/2) else: xDataLims = (0, self.pixelScale*self.profileLineData.size) self.xData = self.pixelScale * np.arange(self.profileLineData.size) self.profileLine.set_xdata(self.xData) self.profileLine.set_ydata(self.profileLineData) self.profileax.set_xlim(xDataLims) # noinspection PyTypeChecker self.profileax.set_ylim(np.min(self.profileLineData), np.max(self.profileLineData)) self.fig.canvas.draw() self.fig.canvas.flush_events()
def get_line_profiles(self, lw=0.7, force=False): """ """ if force or not hasattr(self, 'line_profiles'): # Get image tf = self.get_tif() im = tf.asarray() tf.close() md = self.metadata # Z projection id_z = md['DimensionOrder'].index('Z') im = im.max(axis=id_z) # Get GFP channel id_c = im.shape.index(2) try: id_ndc80 = md['Channels'].index('GFP') except: id_ndc80 = 0 gfp_im = im.take(id_ndc80, axis=id_c) gfp_im = gfp_im / np.median(gfp_im) del im gc.collect() gfp_im = (gfp_im - gfp_im.min()) / (gfp_im.max() - gfp_im.min()) lw_pixel = lw / md['PhysicalSizeX'] line_profiles = {} line_size = {} for t_stamp, p in self.poles.groupby(level='t_stamp'): a = gfp_im[t_stamp] scaled_p = p.copy() scaled_p.loc[:, ['x', 'y', 'w']] /= md['PhysicalSizeX'] p1 = scaled_p.iloc[0][['y', 'x']] p2 = scaled_p.iloc[1][['y', 'x']] lp = measure.profile_line(a, p1, p2, linewidth=lw_pixel) line_profiles[t_stamp] = lp line_size[t_stamp] = scipy.spatial.distance.cdist( np.atleast_2d(p1.values), np.atleast_2d(p2.values))[0, 0] line_size[t_stamp] *= self.metadata['PhysicalSizeX'] del gfp_im del tf gc.collect() line_profiles = pd.DataFrame.from_dict(line_profiles, orient='index') line_size = pd.Series(line_size) self.save(line_profiles, 'line_profiles') self.save(line_size, 'line_size')
def calculate_profiles(self): """ Loops over all start/end points held by the handler and calculates the x- and y-axis of each line profile. Currently enforces that each line in the handler must have the same width. Returns ------- """ for lp in self._rois: # skip if already calculated, or if profile was extracted from different image if (np.any(lp._profile) and lp._width == self._width) or ( lp.get_image_name() != self.image_name): continue lp.set_profile( profile_line(self.image.data.getSlice(lp._slice), (lp._r1, lp._c1), (lp._r2, lp._c2), order=self.interpolation_order, linewidth=self._width)) lp.set_width(self._width) dist = np.sqrt( (self.image.voxelsize.x * (lp._r2 - lp._r1))**2 + (self.image.voxelsize.y * (lp._c2 - lp._c1))**2) # [nm] lp.set_distance(np.linspace(0, dist, lp.get_data().shape[0]))
def cut_channel(self, channel_data): self.line_profile = profile_line(channel_data.T, self.px_i, self.px_f, linewidth=self.px_width, mode="nearest")
def proLine(image,theta,length,center=None): cr, cc = np.indices(image.shape) if not center: center = np.array([(cr.max()-cr.min())/2.0, (cc.max()-cc.min())/2.0]) (endrow,endcol) = (length*np.sin(theta)+center[0],length*np.cos(theta)+center[1]) line = profile_line(image, center,(endrow,endcol)) return line
def LineProfile(dataArray, startPoint, endPoint, lineWidth): #startPoint = (y1, x1) i.e. columns, rows #endPoint = (x2, y2) #LineWidth, number of pixels normal to the profile #Example #profile = profile_line(csvData, (240, 0), (240,640), 5) profile = profile_line(dataArray, startPoint, endPoint, 5) return profile
def profile_lines(image, shape_layer): profile_data = [] for line in shape_layer.data: profile_data.append( measure.profile_line(image, line[0], line[1]).mean()) msg = ('profile means: [' + ', '.join([f'{d:.2f}' for d in profile_data]) + ']') shape_layer.status = msg
def test_reduce_func_sqrt_linewidth_3(): prof = profile_line(pyth_image, (1, 2), (4, 2), linewidth=3, order=0, reduce_func=lambda x: x**0.5) expected_prof = np.array([[1.34164079, 0.77459667, 0.77459667], [0.77459667, 1.34164079, 1.34164079], [0., 0.77459667, 1.34164079], [0., 0., 0.77459667]]) assert_almost_equal(prof, expected_prof)
def test_reduce_func_None_linewidth_3(): prof = profile_line(pyth_image, (1, 2), (4, 2), linewidth=3, order=0, reduce_func=None) expected_prof = np.array([[1.8, 0.6, 0.6], [0.6, 1.8, 1.8], [0., 0.6, 1.8], [0., 0., 0.6]]) assert_almost_equal(prof, expected_prof)
def return_line_profile(self, imdata, src, dst, lw, plotflag=False): """ Draw line profile across centre line of phantom Specify source (src) and destination (dst) coordinates This function produces plot of voxel values and image of sampled line on phantom. Linewidth = width of the line (mean taken over width) Return: = output. Which is the sampled voxel values. """ linewidth = lw output = profile_line(imdata, src, dst) # voxel values along specified line # plot profile line output vs. voxel sampled if plotflag: plt.figure() plt.plot(output) plt.xlabel('Voxels') plt.ylabel('Signal') plt.show() # display profile line on phantom: from source code of profile_line function src_row, src_col = src = np.asarray(src, dtype=float) dst_row, dst_col = dst = np.asarray(dst, dtype=float) d_row, d_col = dst - src theta = np.arctan2(d_row, d_col) length = int(np.ceil(np.hypot(d_row, d_col) + 1)) # add one above to include the last point in the profile # (in contrast to standard numpy indexing) line_col = np.linspace(src_col, dst_col, length) line_row = np.linspace(src_row, dst_row, length) # subtract 1 from linewidth to change from pixel-counting # (make this line 3 pixels wide) to point distances (the # distance between pixel centers) col_width = (linewidth - 1) * np.sin(-theta) / 2 row_width = (linewidth - 1) * np.cos(theta) / 2 perp_rows = np.array([ np.linspace(row_i - row_width, row_i + row_width, linewidth) for row_i in line_row ]) perp_cols = np.array([ np.linspace(col_i - col_width, col_i + col_width, linewidth) for col_i in line_col ]) improfile = np.copy(imdata) improfile[np.array(np.round(perp_rows), dtype=int), np.array(np.round(perp_cols), dtype=int)] = 0 # plot sampled line on phantom to visualise where output comes from if plotflag: plt.figure() plt.imshow(improfile, cmap='bone') plt.colorbar() plt.axis('off') plt.show() return output
def get_line_profiles(self, lw=0.7, force=False): """ """ if force or not hasattr(self, 'line_profiles'): # Get image tf = self.get_tif() im = tf.asarray() tf.close() md = self.metadata # Z projection id_z = md['DimensionOrder'].index('Z') im = im.max(axis=id_z) # Get GFP channel id_c = im.shape.index(2) try: id_ndc80 = md['Channels'].index('GFP') except: id_ndc80 = 0 gfp_im = im.take(id_ndc80, axis=id_c) gfp_im = gfp_im / np.median(gfp_im) del im gc.collect() gfp_im = (gfp_im - gfp_im.min()) / (gfp_im.max() - gfp_im.min()) lw_pixel = lw / md['PhysicalSizeX'] line_profiles = {} line_size = {} for t_stamp, p in self.poles.groupby(level='t_stamp'): a = gfp_im[t_stamp] scaled_p = p.copy() scaled_p.loc[:, ['x', 'y', 'w']] /= md['PhysicalSizeX'] p1 = scaled_p.iloc[0][['y', 'x']] p2 = scaled_p.iloc[1][['y', 'x']] lp = measure.profile_line(a, p1, p2, linewidth=lw_pixel) line_profiles[t_stamp] = lp line_size[t_stamp] = scipy.spatial.distance.cdist(np.atleast_2d(p1.values), np.atleast_2d(p2.values))[0, 0] line_size[t_stamp] *= self.metadata['PhysicalSizeX'] del gfp_im del tf gc.collect() line_profiles = pd.DataFrame.from_dict(line_profiles, orient='index') line_size = pd.Series(line_size) self.save(line_profiles, 'line_profiles') self.save(line_size, 'line_size')
def test_45deg_right_downward(): prof = profile_line(image, (2, 2), (8, 8), order=0) expected_prof = np.array([22, 33, 33, 44, 55, 55, 66, 77, 77, 88]) # repeats are due to aliasing using nearest neighbor interpolation. # to see this, imagine a diagonal line with markers every unit of # length traversing a checkerboard pattern of squares also of unit # length. Because the line is diagonal, sometimes more than one # marker will fall on the same checkerboard box. assert_almost_equal(prof, expected_prof)
def test_reduce_func_lambda_linewidth_3(): prof = profile_line(pyth_image, (1, 2), (4, 2), linewidth=3, order=0, reduce_func=lambda x: x + x**2) expected_prof = np.array([[5.04, 0.96, 0.96], [0.96, 5.04, 5.04], [0., 0.96, 5.04], [0., 0., 0.96]]) # The lambda function acts on each pixel value individually. assert_almost_equal(prof, expected_prof)
def profile_lines(image, shape_layer): profile_data = [] for line in shape_layer.data: profile_data.append( measure.profile_line(image, line[0], line[1], mode='reflect').mean()) msg = ('profile means: [' + ', '.join([f'{d:.2f}' for d in profile_data]) + ']') print(msg)
def sub_pixel_accuracy(image, binary, center, phi): """ 10312018: v7 """ length_max = int(2 * np.sqrt(binary.sum() / np.pi)) y_binary = profile_line(binary, center, (center[0] + length_max * np.cos(phi), center[1] + length_max * np.sin(phi)), order=0) rough_boundary = len(y_binary[y_binary > 0]) - 1 y = profile_line(image, center, (center[0] + length_max * np.cos(phi), center[1] + length_max * np.sin(phi)), order=2) dp = (y[rough_boundary]) / (y[rough_boundary] - y[rough_boundary + 1]) if dp < 2.0: return rough_boundary + dp else: return rough_boundary
def profile_line(img, src=None, dst=None, linewidth=1, order=1, mode="constant", cval=0.0, constrain=True, **kargs): """Wrapper for sckit-image method of the same name to get a line_profile. Parameters: img(ImageArray): Image data to take line section of src, dst (2-tuple of int or float): start and end of line profile. If the co-ordinates are given as intergers then they are assumed to be pxiel co-ordinates, floats are assumed to be real-space co-ordinates using the embedded metadata. linewidth (int): the wideth of the profile to be taken. order (int 1-3): Order of interpolation used to find image data when not aligned to a point mode (str): How to handle data outside of the image. cval (float): The constant value to assume for data outside of the image is mode is "constant" constrain (bool): Ensure the src and dst are within the image (default True). Returns: A :py:class:`Stoner.Data` object containing the line profile data and the metadata from the image. """ scale = img.get("MicronsPerPixel", 1.0) r, c = img.shape if src is None and dst is None: if "x" in kargs: src = (kargs["x"], 0) dst = (kargs["x"], r) if "y" in kargs: src = (0, kargs["y"]) dst = (c, kargs["y"]) if isinstance(src, float): src = (src, src) if isinstance(dst, float): dst = (dst, dst) dst = _scale(dst, scale) src = _scale(src, scale) if not istuple(src, int, int): raise ValueError("src co-ordinates are not a 2-tuple of ints.") if not istuple(dst, int, int): raise ValueError("dst co-ordinates are not a 2-tuple of ints.") if constrain: fix = lambda x, mx: int(round(sorted([0, x, mx])[1])) r, c = img.shape src = list(src) src = (fix(src[0], r), fix(src[1], c)) dst = (fix(dst[0], r), fix(dst[1], c)) result = measure.profile_line(img, src, dst, linewidth, order, mode, cval) points = measure.profile._line_profile_coordinates(src, dst, linewidth)[:, :, 0] ret = Data() ret.data = points.T ret.setas = "xy" ret &= np.sqrt(ret.x ** 2 + ret.y ** 2) * scale ret &= result ret.column_headers = ["X", "Y", "Distance", "Intensity"] ret.setas = "..xy" ret.metadata = img.metadata.copy() return ret
def trace_profile(image, sigma=5., width_factor=1., check_vertical=False): """Trace the intensity profile of a tubular structure in an image. Parameters ---------- image : array of int or float, shape (M, N[, P]) The input image. If 3D, the first dimension is flattened by summing along that axis. sigma : float, optional Convolve the intensity with this sigma to estimate the start and end of the scan lines. width_factor : float, optional The width of the line profile is determined automatically, then multiplied by this factor. check_vertical : bool, optional Check whether the tube is arranged top-to-bottom in the image. If `False`, it is assumed to be vertical, otherwise, the orientation is automatically determined from the image. Returns ------- profile : 1D array of float The intensity profile of the tube. Examples -------- >>> edges = np.array([8, 16, 22, 16, 8]) >>> middle = np.array([0, 0, 0, 0, 0]) >>> image = np.vstack([edges, middle, edges]) >>> trace_profile(image, sigma=0) array([ 18., 0., 18.]) >>> image3d = np.array([image, image, image]) >>> trace_profile(image3d, sigma=0) array([ 54., 0., 54.]) >>> trace_profile(image.T, sigma=0, check_vertical=True) array([ 18., 0., 18.]) """ if image.ndim > 2: image = image.sum(axis=0) if check_vertical: top_bottom_mean = np.mean(image[[0, image.shape[0] - 1], :]) left_right_mean = np.mean(image[:, [0, image.shape[1] - 1]]) if top_bottom_mean < left_right_mean: image = image.T top_distribution = nd.gaussian_filter1d(image[0], sigma) bottom_distribution = nd.gaussian_filter1d(image[-1], sigma) top_loc, top_whm = estimate_mode_width(top_distribution) bottom_loc, bottom_whm = estimate_mode_width(bottom_distribution) angle = np.arctan(np.abs(float(bottom_loc - top_loc)) / image.shape[0]) width = np.int(np.ceil(max(top_whm, bottom_whm) * np.cos(angle))) profile = profile_line(image, (0, top_loc), (image.shape[0] - 1, bottom_loc), linewidth=width, mode='nearest') return profile
def line_scanner(image): from skimage import measure yloc = 456 image = ndimage.gaussian_filter(image, sigma=(1, 1), order=0) line1 = measure.profile_line(image, (yloc, 0), (yloc, 1388)) fig, ax = plt.subplots(2, 1, figsize=(10, 5), sharex=True, sharey=False) ax[0].imshow(image, cmap="gray") ax[0].set_ylim(yloc - 100, yloc + 100) ax[0].axhline(y=yloc, xmin=0, xmax=1) ax[1].plot(line1)
def create_lineout(self, start=(0,0), end=(0,0), lineout_width=20): ''' start and end are in mm on the grid defined by the origin you just set ''' #find coordinates in pixels start_px=mm_to_px(start) end_px=mm_to_px(stop) #use scikit image to do a nice lineout on the cropped array self.lo=profile_line(self.neL_crop, start_px,end_px,linewidth=lineout_width) #set up a mm scale centred on 0 px_range=self.lo.size/2 self.mm=np.linspace(px_range, -px_range, 2*px_range)/self.scale #flip range to match images
def lineprofile(img, startpoint, endpoint, linewidth=1, pxsize=1): """Extracts a line profile from img, according to the parameters.""" # Make coordinates for the line x0, y0 = startpoint[0], startpoint[1] # pixel coordinates x1, y1 = endpoint[0], endpoint[1] # pixel coordinates # Extract the values along the line linelength = np.sqrt((x1 - x0)**2 + (y1 - y0)**2) * pxsize zi = measure.profile_line(img, (y0, x0), (y1, x1), linewidth=linewidth, mode='constant') ci = np.linspace(0, linelength, zi.size) # Return the intensity profile and the corresponding coordinate vector return zi, ci
def _update_data(self): scan = measure.profile_line(self.image_viewer.image, *self.line_tool.end_points[:, ::-1], linewidth=self.line_tool.linewidth) self.scan_data = scan if scan.ndim == 1: scan = scan[:, np.newaxis] if scan.shape[1] != len(self.profile): self.reset_axes(scan) for i in range(len(scan[0])): self.profile[i].set_xdata(np.arange(scan.shape[0])) self.profile[i].set_ydata(scan[:, i])
def create_lineout(self, start=(0,0), end=(0,0), lineout_width_mm=1, verbose=False): ''' start and end are in mm on the grid defined by the origin you just set ''' #find coordinates in pixels start_px=self.mm_to_px(start) end_px=self.mm_to_px(end) if verbose is True: print(start_px,end_px) #use scikit image to do a nice lineout on the cropped array self.lo=profile_line(self.data_c, start_px,end_px,linewidth=lineout_width_mm*self.scale) #set up a mm scale centred on 0 px_range=self.lo.size/2 self.mm=np.linspace(-px_range, px_range, 2*px_range)/self.scale #flip range to match images
def trace_profile(image, sigma=5., width_factor=1., check_vertical=False): """Trace the intensity profile of a tubular structure in an image. Parameters ---------- image : array of int or float, shape (M, N[, P]) The input image. If 3D, the first dimension is flattened by summing along that axis. sigma : float, optional Convolve the intensity with this sigma to estimate the start and end of the scan lines. width_factor : float, optional The width of the line profile is determined automatically, then multiplied by this factor. check_vertical : bool, optional Check whether the tube is arranged top-to-bottom in the image. If `False`, it is assumed to be vertical, otherwise, the orientation is automatically determined from the image. Returns ------- profile : 1D array of float The intensity profile of the tube. Examples -------- >>> edges = np.array([8, 16, 22, 16, 8]) >>> middle = np.array([0, 0, 0, 0, 0]) >>> image = np.vstack([edges, middle, edges]) >>> trace_profile(image, sigma=0) array([ 18., 0., 18.]) """ if image.ndim > 2: image = image.sum(axis=0) if check_vertical: top_bottom_mean = np.mean(image[[0, image.shape[0] - 1], :]) left_right_mean = np.mean(image[:, [0, image.shape[1] - 1]]) if top_bottom_mean < left_right_mean: image = image.T top_distribution = nd.gaussian_filter1d(image[0], sigma) bottom_distribution = nd.gaussian_filter1d(image[-1], sigma) top_loc, top_whm = estimate_mode_width(top_distribution) bottom_loc, bottom_whm = estimate_mode_width(bottom_distribution) angle = np.arctan(np.abs(float(bottom_loc - top_loc)) / image.shape[0]) width = np.int(np.ceil(max(top_whm, bottom_whm) * np.cos(angle))) profile = profile_line(image, (0, top_loc), (image.shape[0] - 1, bottom_loc), linewidth=width, mode='nearest') return profile
def update_width(self, *args): self.width = float(self.width_box.get()) self.profile = profile_line(sp.ma.filled( self.options.imshow.get_array().astype(float), fill_value=sp.nan), self.line[0], self.line[1], linewidth=self.width) self.mframe.ax.lines[0].set_data(self.xspace, self.profile) # Redraw the graph in lineout's window self.mframe.fig.canvas.draw() # Change the verices of the rectangle in the main window self.rect.set_xy(self.get_verts()) self.main_canvas_draw() # Give the focus to the graph self.mframe.canvas._tkcanvas.focus_set()
def MeanWaveSeriesSpectrum(image, direction, res, linewidth, paddingextrapower): #-------------------------------------------------------------------- # extract wave series from mean direction line and compute Spectrum #-------------------------------------------------------------------- # line segment (in selected direction) that passed by image center center = IP.ImageCenter(image) center = np.round(center) linecenter = DefineLine(image, direction, center, FlagOrtho=0) # Detect intersection of the line with the image edges edpt = DetectLineEdge(image, linecenter) # extract yline = profile_line(image, edpt.point1, edpt.point2, linewidth, order=2) xline = Distance4Line(yline, edpt, res) # perform zero padding (to increase spectrum resolution) padding = resolutionpadding(image, paddingextrapower) xline1, yline1 = zerospadding(xline, yline, padding) # spectrum of the wave series ks, Spectrum = Spectrum1D(xline1, yline1, 0) """ #figure fig, ax = plt.subplots(1) xl = [0, image.shape[0]]; yl = [image.shape[1], 0]; #image ax.imshow(image,cmap=plt.cm.gray, extent = [0,image.shape[0],image.shape[0],0]) # line in the mean direction passing by the center of the image ax.plot(linecenter.x,linecenter.y,'c'); # limit lines offset = np.int(np.rint(linewidth/2)) point1=np.zeros(2); point1[1]=center[1]; point1[0] = center[0]-offset; point2=np.zeros(2); point2[1]=center[1]; point2[0] = center[0]+offset; line1 = DefineLine(image, direction, point1, FlagOrtho = 0) line2 = DefineLine(image, direction, point2, FlagOrtho = 0) ax.fill_between(linecenter.x,linecenter.y, line1.y, where=linecenter.y>=line1.x, Facecolor=(0.1,0.1,0.6,0.5), interpolate=True) ax.fill_between(linecenter.x,linecenter.y, line2.y, where=linecenter.y<=line2.x, Facecolor=(0.1,0.1,0.6,0.5), interpolate=True) ax.fill_between(linecenter.x,line1.y, linecenter.y, where=linecenter.y<=line1.x, Facecolor=(0.1,0.1,0.6,0.5), interpolate=True) ax.fill_between(linecenter.x,line2.y, linecenter.y, where=linecenter.y>=line2.x, Facecolor=(0.1,0.1,0.6,0.5), interpolate=True) ax.plot(line1.x,line1.y,'c', line2.x, line2.y,'c'); ax.set_xlim(xl); ax.set_ylim(yl) plt.axis('off') plt.show() """ return xline, yline, ks, Spectrum
def assemble_profiles(phi_space, mask, banana_circle, linewidth=5): profiles = [] for phi in phi_space: profiles.append( measure.profile_line( mask.T, # For some reason gotta take the transpose banana_circle.center, circle(banana_circle.xc, banana_circle.yc, 3 * banana_circle.radius, phi), linewidth=linewidth, mode="constant", )[:2 * int(banana_circle.radius)]) profiles = np.vstack(profiles) return profiles
def create_lineout_angle(self, start=(-1,5), end=(1,5), lineout_width_mm=1, verbose=False): ''' start and end are in degrees ''' if start[1] is not end[1]: print('Ensure start and end are the same mm positions') return #find coordinates in pixels start_px=self.mm_to_px(start) end_px=self.mm_to_px(end) if verbose is True: print(start_px,end_px) #use scikit image to do a nice lineout on the cropped array self.lo=profile_line(self.data_c, start_px,end_px,linewidth=int(lineout_width_mm*self.scale_x)) #set up an angle scale centred on 0 self.angles=np.linspace(start[0], end[0], self.lo.size)
def calculate_scores_img(image, total_area): # Calculate scores around the circumference of image in the region of interest # Get size of image (ylen, xlen, dim) = image.shape # colored image NUM_INSPECTION_POINTS = ylen s = np.zeros((NUM_INSPECTION_POINTS)) # Run intensity lines across the length of the image for i in range(NUM_INSPECTION_POINTS): intensity_line = profile_line(image, (0, i), (xlen, i), 1) red_profile = intensity_line[:, 0] s[i] = sum(red_profile > par_dict['PAR_INTENSITY_THRESHOLD']) ppd_score = sum(s) / total_area return ppd_score
def create_lineout(self, start=(0, 0), end=(0, 0), lineout_width=20): ''' start and end are in mm on the grid defined by the origin you just set ''' #find coordinates in pixels start_px = mm_to_px(start) end_px = mm_to_px(stop) #use scikit image to do a nice lineout on the cropped array self.lo = profile_line(self.neL_crop, start_px, end_px, linewidth=lineout_width) #set up a mm scale centred on 0 px_range = self.lo.size / 2 self.mm = np.linspace( px_range, -px_range, 2 * px_range) / self.scale #flip range to match images
def extract_kymograth(path, x1, y1, x2, y2, pattern=None) -> np.array: """ Takes as input the path to a folder of consecutive images (a movie) of size (m, n) and coordinates for a segment on the image. Returns the evolution of this segment over time in a (p, k) array where p is the number of images and k is the lenght of the segment. 'pattern' is a parameter to only consider images matching a certain pattern. The output is a np.array of dimension (n, m) where n is the number of images and m is the length of the segment. WARNING: (x, y) coordinates are in the same system as matplotlib """ point1 = np.array([y1, x1]) # NB: we switch to (y, x) instead of (x, y) point2 = np.array([y2, x2]) # This is because of the profile_line function if pattern is None: def is_valid(name): return True else: model = re.compile(pattern) def is_valid(name): match = model.search(name) if match: return True else: return False listdir = [ file_name for file_name in os.listdir(path) if is_valid(file_name) ] l = [] for file_name in listdir: im = Image.open(os.path.join(path, file_name)) im_np = np.array(im) profile = profile_line(im_np, point1, point2, mode="constant") profile = profile.reshape((1, len(profile))) l.append(profile) logging.info(f"Number of images handled: {len(l)}") return np.concatenate(l, axis=0)
def calc_linescan_enrichment(channel_nobg, line_start, line_end, width=5): """Calculate the enrichment of signal at the highest peak along the scan line relative to the two next-highest peaks. Currently need the dev version of skimage for the profile_line method. Args: channel_nobg: background-subtracted channel. line_start: the starting point of the scan line. line_end: the ending point of the scan line. width: the width to scan. Returns: (enrichment, scan) """ linescan = measure.profile_line(channel_nobg, line_start, line_end, linewidth=width) mean_linescan = pd.rolling_mean(linescan, 3) peaks = signal.argrelmax(mean_linescan) peak_values = sorted(mean_linescan[peaks], reverse=True) scan_enrichment = peak_values[0] / (peak_values[1] + peak_values[2]) return scan_enrichment, mean_linescan
def line_changed(self, end_points): x, y = np.transpose(end_points) self.line_tool.end_points = end_points scan = measure.profile_line(self.image_viewer.original_image, *end_points[:, ::-1], linewidth=self.line_tool.linewidth) self.scan_data = scan if scan.ndim == 1: scan = scan[:, np.newaxis] if scan.shape[1] != len(self.profile): self.reset_axes(scan) for i in range(len(scan[0])): self.profile[i].set_xdata(np.arange(scan.shape[0])) self.profile[i].set_ydata(scan[:, i]) self.ax.relim() self._autoscale_view() self.redraw()
def line_profile(self, start, end, width=1, order=1): """Return a line trace of intensity averaging over width. Call through to skimage.measure.profile_line Parameters ---------- start: 2-tuple coords at start of line (numpy coordinates not x,y) end: 2-tuple coords at end of line (last pixel is included in result) width: int width of line to average over order: int order of the spline interpolation Returns ------- profile: array intensity profile """ return measure.profile_line(self,src=start,dst=end,linewidth=width, order=order,mode='nearest')
def find_mean_profile_line(image, annotation, center, theta_start, theta_end, length): lines = [] for theta in np.linspace(theta_start, theta_end, 200): line_start, line_end = find_line_through_point(center, theta, length) pline = profile_line(image, line_start, line_end) annotation_line = line(*(line_start + line_end)) try: annotation[annotation_line] = 0, 255, 255 except IndexError: pass lines.append(pline[:length-1]) lines_as_matrix = np.stack(lines) average_lines = np.mean(lines_as_matrix, axis=0) return average_lines
def attach(self, image_viewer): super(LineProfile, self).attach(image_viewer) image = image_viewer.original_image if self._limit_type == 'image': self.limits = (np.min(image), np.max(image)) elif self._limit_type == 'dtype': self.limits = dtype_range[image.dtype.type] elif self._limit_type is None or len(self._limit_type) == 2: self.limits = self._limit_type else: raise ValueError("Unrecognized `limits`: %s" % self._limit_type) if not self._limit_type is None: self.ax.set_ylim(self.limits) h, w = image.shape[0:2] x = [w / 3, 2 * w / 3] y = [h / 2] * 2 self.line_tool = ThickLineTool(self.image_viewer.ax, maxdist=self.maxdist, on_move=self.line_changed, on_change=self.line_changed) self.line_tool.end_points = np.transpose([x, y]) scan_data = measure.profile_line(image, *self.line_tool.end_points[:, ::-1]) self.scan_data = scan_data if scan_data.ndim == 1: scan_data = scan_data[:, np.newaxis] self.reset_axes(scan_data) self._autoscale_view()
def test_horizontal_rightward(): prof = profile_line(image, (0, 2), (0, 8), order=0) expected_prof = np.arange(2, 9) assert_equal(prof, expected_prof)
def test_vertical_upward(): prof = profile_line(image, (8, 5), (2, 5), order=0) expected_prof = np.arange(85, 15, -10) assert_equal(prof, expected_prof)
def test_3d_through_center_linewidth(): prof = profile_line(image3d, (1, 1, 0), (1, 1, 2), order=1, linewidth=3, multichannel=False) expected_prof = np.repeat(0.850761583277, 3) assert_almost_equal(prof, expected_prof)
def test_3d_vertical_downward(): prof = profile_line(image3d, (0, 0, 0), (0, 1, 0), order=0, multichannel=False) expected_prof = np.array([1, 1]) assert_equal(prof, expected_prof)
def test_3d_diagonal_interpolated(): prof = profile_line(image3d, (0, 0, 0), (2, 2, 2), order=1, multichannel=False) expected_prof = np.array([1, 0.75, 0, 0.75, 1]) assert_equal(prof, expected_prof)
def test_45deg_right_downward_interpolated(): prof = profile_line(image, (2, 2), (8, 8), order=1) expected_prof = np.linspace(22, 88, 10) assert_almost_equal(prof, expected_prof)
def test_45deg_left_downward(): prof = profile_line(image, (2, 8), (8, 2), order=1) expected_prof = np.arange(28, 83, 6) assert_almost_equal(prof, expected_prof)
def test_45deg_left_upward(): prof = profile_line(image, (8, 8), (2, 2), order=1) expected_prof = np.arange(88, 21, -22. / 3) assert_almost_equal(prof, expected_prof)
def test_45deg_right_upward(): prof = profile_line(image, (8, 2), (2, 8), order=1) expected_prof = np.arange(82, 27, -6) assert_almost_equal(prof, expected_prof)
rect = lpcoords((0, top_mode), (im.shape[1] - 1, bottom_mode), (top_width + bottom_width) / 2) rcorners = np.rint(rect[0][[0, 0, -1, -1], [0, -1, -1, 0]]).astype(int) ccorners = np.rint(rect[1][[0, 0, -1, -1], [0, -1, -1, 0]]).astype(int) rrect, crect = draw.polygon(rcorners, ccorners, overlay.shape) overlay[rrect, crect] = 0.5 overlay[rr, cc] = 0.0 fig, axes = plt.subplots(1, 3, figsize=(8, 3)) axes[0].imshow(img, interpolation='nearest') axes[0].set_xticks([]) axes[0].set_yticks([]) axes[0].set_title('original image') axes[1].imshow(1 - overlay, interpolation='nearest', cmap=cm.gray) prof = profile_line(im, (0, top_mode), (im.shape[1] - 1, bottom_mode), linewidth=(top_width + bottom_width) / 2, mode='reflect') axes[1].set_xticks([]) axes[1].set_yticks([]) axes[1].set_title('measured overlay') axes[2].plot(prof, lw=2, c='k') axes[2].set_ylabel('mean intensity') axes[2].set_xlabel('distance in pixels') axes[2].set_ylim(0, 2000) axes[2].set_xlim(0, 1100) axes[2].set_yticks(np.arange(200, 2000, 400)) axes[2].set_xticks(np.arange(200, 1100, 400)) axes[2].set_title('intensity profile') plt.tight_layout() plt.savefig('fig2.png', bbox_inches='tight', dpi=600)
def test_pythagorean_triangle_right_downward_interpolated(): prof = profile_line(image, (1, 1), (7, 9), order=1) expected_prof = np.linspace(11, 79, 11) assert_almost_equal(prof, expected_prof)
def profile(data, radius, posAngle, slitWidth): import numpy as np import w_subimg import copy from skimage import measure from skimage import feature ntrans = len(np.unique(data['lineID'])) nepoch = len(np.unique(data['JD'])) Phi = np.unique(data['Phi']) # http://www.python-course.eu/passing_arguments.php # https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/ dic = copy.deepcopy(data) # <- THIS IS VERY IMPORTANT! KEEP copy.deepcopy()! dic['profile'] = [] # new key: line radial profile dic['radPos'] = [] # new key: positions where the radial profile was measured raw_images = [ data['fileName'], data['image'], data['pixScale'] ] for j in range(ntrans): for i in range(nepoch): index = i + j * nepoch # print(j, i, index, raw_images[0][index], coords_row, coords_col) if raw_images[0][index] == 'zero.fits': raw_images[1][index] = raw_images[1][index] * 0 img = copy.deepcopy(raw_images[1][index]) rho = radius # length in arcsec # theta=0 @ 6:00; theta=90 @ 3:00; theta=180 @ 12:00 theta = (posAngle + 180. - 360.) if (posAngle >= 180.) else (posAngle + 180.) rho_x = rho * np.cos((theta) / 180. * np.pi) rho_y = rho * np.sin((theta) / 180. * np.pi) actual_image = img # transf.resize(raw_images[j][2], raw_images[0][2].shape) # center of image (same for X and Y) x0 = ((img.shape)[0] - 1) / 2 dx = rho_x / raw_images[2][index] dy = rho_y / raw_images[2][index] x1 = x0 + dx y1 = x0 + dy # slit width lineWidth = slitWidth / raw_images[2][index] xstart, ystart = x0, x0 xend, yend = x1, y1 if j == 0: xstart0, ystart0, xend0, yend0 = xstart, ystart, xend, yend # print(j,(xstart,ystart), (xend,yend)) profile = measure.profile_line(actual_image, (xstart,ystart), (xend,yend), linewidth=lineWidth) xvar = np.linspace(0,rho,profile.shape[0]) dic["profile"].append(profile) dic["radPos"].append(xvar) return dic
def test_pythagorean_triangle_right_upward_linewidth(): prof = profile_line(pyth_image[::-1, :], (4, 1), (1, 5), linewidth=3, order=0) expected_prof = np.ones(6) assert_almost_equal(prof, expected_prof)
def test_pythagorean_triangle_right_downward(): prof = profile_line(image, (1, 1), (7, 9), order=0) expected_prof = np.array([11, 22, 23, 33, 34, 45, 56, 57, 67, 68, 79]) assert_equal(prof, expected_prof)
def test_pythagorean_triangle_transpose_left_down_linewidth(): prof = profile_line(pyth_image.T[:, ::-1], (1, 4), (5, 1), linewidth=3, order=0) expected_prof = np.ones(6) assert_almost_equal(prof, expected_prof)