def outChannelMask(im, chAngle=0): """Creates a mask that excludes the channel Parameters ---------- im: 2d array The image chAngle: number The angle of the channel in radians Returns ------- mask: 2d array the mask excluding the channel Notes ----- The channel should be clear(ish) on the image. The angle should be aligned with the channel """ im=np.array(im,dtype='float32') #Remove clear dust mask=rmbg.backgroundMask(im, nstd=6) im[~mask]=np.nan #get edge scharr=cr.Scharr_edge(im) #Orientate image along x if not done if chAngle !=0: scharr= ir.rotate_scale(scharr, -chAngle,1,np.nan) #get profile prof=np.nanmean(scharr,1) #get threshold threshold=np.nanmean(prof)+3*np.nanstd(prof) mprof=prof>threshold edgeargs=np.flatnonzero(mprof) if edgeargs.size > 2: mask=np.zeros(im.shape) mask[edgeargs[0]-5:edgeargs[-1]+5,:]=2 if chAngle !=0: mask= ir.rotate_scale(mask, chAngle,1,np.nan) mask=np.logical_and(mask<1, np.isfinite(im)) else: mask= None return mask
def channels_edges(bg, approxwidth, angle=None, std=10, Nwalls=8): """ Get the position of the edges Parameters ---------- bg: 2d array image containning the 4 channels approxwidth: integer the approximate width angle: float if given, angle at which the edges are std: integer Tolerence on wall position in pixels Returns ------- edges: 1d integer array Position in the rotated image of the edges in pixels """ bg = bg / rmbg.polyfit2d(bg) if angle is not None: bg = ir.rotate_scale(bg, -angle, 1, borderValue=np.nan) prof = gfilter(np.nanmean(bg, 0), 3) edges = np.abs(np.diff(prof)) edges[np.isnan(edges)] = 0 #create approximate walls x = np.arange(len(edges)) gwalls = np.zeros(len(edges), dtype=float) for center in (1 + np.arange(Nwalls)) * approxwidth: gwalls += edges.max() * np.exp(-(x - center)**2 / (2 * std**2)) #Get best fit for approximate walls c = int( np.correlate(edges, gwalls, mode='same').argmax() - len(gwalls) / 2) ''' from matplotlib.pyplot import plot, figure, imshow figure() imshow(bg) figure() plot(edges) plot(gwalls) figure() plot(np.correlate(edges,gwalls,mode='same')) #''' #Roll gwalls = np.roll(gwalls, c) if c < 0: gwalls[c:] = 0 else: gwalls[:c] = 0 #label wall position label, n = msr.label(gwalls > .1 * gwalls.max()) #Get the positions edges = np.squeeze(msr.maximum_position(edges, label, range(1, n + 1))) assert len(edges) == 8, 'Did not detect 8 edges' return edges
def remove_bg(im, bg, edgesOut=None): """ Flatten and background subtract images Parameters ---------- im: 2d array list of images containning the 4 channels bg: 2d array Background corresponding to the list edgesOut: 1d array output for the edges Returns ------- flatIm: 2d array Flattened image """ #Get bg angle (the other images are the same) infoDict = {} angle = bg_angle(im, bg, infoDict) approxwidth = infoDict['BrightInfos']['width'] #Get the mask maskbg = channels_mask(bg, approxwidth, angle, edgesOut) #rotate and flatten the bg bg = ir.rotate_scale(bg, -angle, 1, borderValue=np.nan) im = ir.rotate_scale(im, -angle, 1, borderValue=np.nan) maskim = ir.rotate_scale_shift(maskbg, infoDict['diffAngle'], infoDict['diffScale'], infoDict['offset'], borderValue=np.nan) > .5 maskim = binary_erosion(maskim, iterations=15) #Get Intensity ret = rmbg.remove_curve_background(im, bg, maskbg=maskbg, maskim=maskim, bgCoord=True, reflatten=True) return ret
def flat_image(im, pixsize, chanWidth=300e-6): """ Flatten the image Parameters ---------- im: 2d array image pixsize: float pixel size in [m] chanWidth: float, defaults 300e-6 channel width in [m] Returns ------- im: 2d array The flattened image """ im=np.asarray(im,dtype=float) #remove peaks im[rmbg.getPeaks(im, maxsize=20*20)]=np.nan #straighten angle=dp.image_angle(im-np.nanmedian(im)) im=ir.rotate_scale(im,-angle,1,borderValue=np.nan) #Get center prof=np.nanmean(im,0) flatprof=prof-np.nanmedian(prof) flatprof[np.isnan(flatprof)]=0 x=np.arange(len(prof))-dp.center(flatprof) x=x*pixsize #Create mask channel=np.abs(x)<chanWidth/2 mask=np.ones(np.shape(im)) mask[:,channel]=0 #Flatten im=im/rmbg.polyfit2d(im,mask=mask)-1 """ from matplotlib.pyplot import figure, imshow,plot figure() imshow(im) imshow(mask,alpha=.5,cmap='Reds') # plot(x,flatprof) # plot(x,np.correlate(flatprof,flatprof[::-1],mode='same')) #""" return im
def flat_image(im, frac=.7, infosOut=None, subtract=False): """ Flatten input images Parameters ---------- im: 2d array The image frac: float fraction of the profile taken by fluorescence from channels infosOut: dict, defaults None dictionnary containing the return value of straight_image_infos subtract: Bool Should the shape be subtracted instead of divided Returns ------- im: 2d array The flattened image """ #Detect Angle angle = dp.image_angle(im - np.median(im)) im = ir.rotate_scale(im, -angle, 1, borderValue=np.nan) #Get channels infos w, a, origin = straight_image_infos(im) #get mask mask = np.ones(np.shape(im)[1]) for i in range(4): amin = origin + 2 * i * w - frac * w amax = origin + 2 * i * w + frac * w mask[int(amin):int(amax)] = 0 mask = mask > 0 mask = np.tile(mask[None, :], (np.shape(im)[0], 1)) #Flatten if not subtract: im = im / rmbg.polyfit2d(im, mask=mask) - 1 else: im = im - rmbg.polyfit2d(im, mask=mask) # import matplotlib.pyplot as plt # plt.figure() # plt.imshow(rmbg.polyfit2d(im,mask=mask)) # plt.colorbar() # plt.figure() # plt.imshow(im) # plt.imshow(mask,alpha=.5) if infosOut is not None: infosOut['infos'] = (w, a, origin) return im
def extract_profiles(im, imSlice=None, flatten=False): ''' Extract profiles from image Parameters ---------- im: 2d array The flat image imSlice: slice Slice of the image to consider flatten: Bool, Defaults False Should the image be flatten Returns ------- profiles: 2d array The four profiles ''' im = np.asarray(im) if imSlice is not None: im = im[imSlice] infos = {} if flatten: im = flat_image(im, infosOut=infos) angle = dp.image_angle(im) im = ir.rotate_scale(im, -angle, 1, borderValue=np.nan) if not flatten: infos['infos'] = straight_image_infos(im) """ profiles0=extract_profiles_flatim(im[:100],infos['infos']) for p in profiles0: p/=np.mean(p) profiles1=extract_profiles_flatim(im[-100:],infos['infos']) for p in profiles1: p/=np.mean(p) from matplotlib.pyplot import plot, figure, imshow figure() plot(np.ravel(profiles0)) plot(np.ravel(profiles1)) #""" profiles = extract_profiles_flatim(im, infos['infos']) return profiles
def image_infos(im): """ Get the image angle, channel width, proteind offset, and origin Parameters ---------- im: 2d array The image Returns ------- dict: dictionnary dictionnary containing infos """ imflat = im #Detect Angle angle = dp.image_angle(imflat) im = ir.rotate_scale(im, -angle, 1, borderValue=np.nan) #Get channels infos w, a, origin = straight_image_infos(im) retdict = {'angle': angle, 'origin': origin, 'width': w, 'offset': a} return retdict
def outGaussianBeamMask(data, chAngle=0): """ get the outside of the channel from a gaussian fit Parameters ---------- data: 2d array The image chAngle: number The angle of the channel in radians Returns ------- mask: 2d array the mask excluding the channel """ data=np.asarray(data) #Filter to be used gfilter=scipy.ndimage.filters.gaussian_filter1d #get profile if chAngle!=0: data=ir.rotate_scale(data, -chAngle,1,np.nan) profile=np.nanmean(data,1) #guess position of max amax= profile.size//2 #get X and Y X0=np.arange(profile.size)-amax Y0=profile #The cutting values are when the profiles goes below zero rlim=np.flatnonzero(np.logical_and(Y0<0,X0>0))[0] llim=np.flatnonzero(np.logical_and(Y0<0,X0<0))[-1] #We can now detect the true center fil=gfilter(profile,21) X0=X0-X0[np.nanargmax(fil[llim:rlim])]-llim #restrict to the correct limits X=X0[llim:rlim] Y=Y0[llim:rlim]-np.nanmin(Y0) #Fit the log, which should be a parabola c=np.polyfit(X,np.log(Y),2) #Deduce the variance var=-1/(2*c[0]) #compute the limits (3std, restricted to half the image) mean=np.nanargmax(fil[llim:rlim])+llim dist=int(3*np.sqrt(var)) if dist > profile.size//4: dist = profile.size//4 llim=mean-dist if llim < 0: return None rlim=mean+dist if rlim>profile.size: return None #get mask mask=np.ones(data.shape) if chAngle!=0: idx=np.indices(mask.shape) idx[1]-=mask.shape[1]//2 idx[0]-=mask.shape[0]//2 X=np.cos(chAngle)*idx[1]+np.sin(chAngle)*idx[0] Y=np.cos(chAngle)*idx[0]-np.sin(chAngle)*idx[1] mask[np.abs(Y-mean+mask.shape[0]//2)<dist]=0 else: mask[llim:rlim,:]=0 #mask=np.logical_and(mask>.5, np.isfinite(data)) mask=mask>.5 return mask """
def extract_profile(flatim, pixsize, chanWidth=300e-6,*,reflatten=True,ignore=10): """ Get profile from a flat image Parameters ---------- flatim: 2d array flat image pixsize: float pixel size in [m] chanWidth: float, defaults 300e-6 channel width in [m] reflatten: Bool, defaults True Should we reflatten the profile? ignore: int, defaults 10 The number of pixels to ignore if reflattening Returns ------- im: 2d array The flattened image """ #Orientate flatim=ir.rotate_scale(flatim,-dp.image_angle(flatim) ,1, borderValue=np.nan) #get profile prof=np.nanmean(flatim,0) #Center X X=np.arange(len(prof))*pixsize center=dp.center(prof)*pixsize inchannel=np.abs(X-center)<.45*chanWidth X=X-(dp.center(prof[inchannel])+np.argmax(inchannel))*pixsize #get what is out out=np.logical_and(np.abs(X)>.55*chanWidth,np.isfinite(prof)) if reflatten: #fit ignoring extreme 10 pix fit=np.polyfit(X[out][ignore:-ignore],prof[out][ignore:-ignore],2) bgfit=fit[0]*X**2+fit[1]*X+fit[2] #Flatten the profile prof=(prof+1)/(bgfit+1)-1 #We restrict the profile to channel width - widthcut Npix=int(chanWidth//pixsize)+1 Xc=np.arange(Npix)-(Npix-1)/2 Xc*=pixsize finterp=interpolate.interp1d(X, prof,bounds_error=False,fill_value=0) """ from matplotlib.pyplot import figure, imshow,plot figure() plot(X,prof) #""" return finterp(Xc) """