Exemplo n.º 1
0
    def fftAnalysis(self,cs,profile,mode='sensitivity'):
        """
        Fourier analysis: find main frequencies and power therein
        """
        if cs.verbose:
            try:
                import QCUS_testing as mytest
                if mode == 'sensitivity':
                    mytest._exportProfile( profile,fname='y2profile.tsv' )
                else:
                    mytest._exportProfile( profile,fname='x2profile.tsv' )
            except:
                pass

        fdelta = .1 # peak should differ by more than this fraction of max ps

        if mode == 'sensitivity':
            cs.sens_basewavelength = 0.
            cs.sens_ylim2 = -1

        # remove average component
        ywork = profile-np.average(profile)
        nx = len(ywork)
        x = np.array(range(nx))
        
        ffty = np.fft.rfft(ywork)
        ps = np.abs(ffty)**2
        integral = np.sum(ps[self.fft_skip:]) # calculate total content, but ignore zero component
        freqs = rfftfreq(nx)
            
        # find peaks
        xy_max,xy_min = wadwrapper_lib.peakdet(ps, delta=fdelta*np.max(ps[self.fft_skip:])) # returns indices for freqs

        # sort peaks from large to small
        xy_max = sorted(xy_max,key=operator.itemgetter(1))
        xy_max = xy_max[::-1]

        # find max component which is not zero-component and represents larger than given fraction of power
        base_ix = 0   # index of base-frequency
        start_ix = 0  # index of zero-peak
        for i,(xi,yi) in enumerate(xy_max):
            if xi<=self.fft_skip: # zero-peak must be located in skip
                start_ix = xi
            if xi>self.fft_skip and base_ix<1:
                base_ix = xi 
                if mode == 'sensitivity':
                    cs.sens_basewavelength = self.pixels2mm(cs, 1./freqs[xi])
                break

        # filter-out all non-background trend components to find extend of signal
        for i in range(len(ffty)):
            if i>(base_ix+start_ix)/2:
                ffty[i] = 0.

        # locate minimum (after zero-peak) of trend
        fy = np.fft.irfft(ffty)
        ix_max = np.argmax(fy)
        ix_min = ix_max+np.argmin(fy[ix_max:])
        if cs.verbose:
            print 'max @',ix_max
            print 'min @',ix_min

        if mode == 'sensitivity':
            cs.sens_ylim2 = ix_min
        
        if cs.verbose:
            plt.figure()
            plt.plot(ywork)
            plt.plot(fy)
            if mode == 'sensitivity':
                plt.title('sensitivity,filtered')
            else:
                plt.title('uniformity,filtered')
            plt.figure()
            plt.plot(ps)
            if mode == 'sensitivity':
                plt.title('sensitivity,powerspectrum')
            else:
                plt.title('uniformity,powerspectrum')
            cs.hasmadeplots = True
Exemplo n.º 2
0
    def sensitivityAnalysis(self,cs):
        """
        Workflow:
        1. Calculate profile (vertically)
        2. Determine noise level
        3. Exponential fit to peaks in profile
        4. total sensitivity = penetration depth (intercept fit and noise)
        5. Repeat for subsets
        """
        error = True
    
        ## 1. Calculate profile (vertically)
        wid,hei = np.shape(cs.rect_image)
        offsetHOR= wid/4 #10 ; adjusted to remove influence of annotations through reverb data (enhancement line)

        if offsetHOR == 0:
            offsetHOR = self.offsetHOR
        crop = cropImage(cs.rect_image, [offsetHOR], [self.offsetVER])
        wid,hei = np.shape(crop)
        
        sensitivity = np.mean(crop,axis=0)
        time0 = time.time()
        self.fftAnalysis(cs,sensitivity,mode='sensitivity')
        cs.report.append(('sens_fft',time.time()-time0))

        nx = len(sensitivity)
        sensitivitysmoothed = mymath.movingaverage(sensitivity,self.smooth_sensitivity)
        if cs.testing:
            try:
                import QCUS_testing as mytest
                mytest._exportProfile( [ (s,ss) for s,ss in zip(sensitivity,sensitivitysmoothed) ],fname='yprofile.tsv' )
            except:
                pass
        
        ##2. Determine noise level (mean of last n values of sensitivity)
        cs.sens_noiseM = -1
        noiseRange = 2
        noise_av = np.mean(sensitivitysmoothed[-noiseRange:])
        noise_sd = np.std(sensitivitysmoothed[-noiseRange:])
        noise_snr = noise_av/noise_sd if noise_sd >0. else 0.
        noise_inc = False # sometimes snr starts with a local max
        for nr in range(noiseRange+2,nx/3):
            av = np.mean(sensitivitysmoothed[-nr:])
            sd = np.std(sensitivitysmoothed[-nr:])
            snr = av/sd if sd >0. else 0.
            if snr>noise_snr or not noise_inc:
                if snr>noise_snr:
                    noise_inc = True 
                noise_av = av
                noise_sd = sd
                noise_snr = snr
            else:
                cs.sens_noiserange = nr
                break
        cs.sens_noiseM = noise_av

        top_val = np.max(sensitivitysmoothed)
        cut_val = cs.sens_noiseM+.1*(top_val-cs.sens_noiseM)
        for kk in reversed(range(nx)):
            if sensitivitysmoothed[kk]>cut_val:
                cs.sens_ylim = kk
                break
            
        # peak detection
        pmax = np.max(sensitivitysmoothed)
        pmin = np.min(sensitivitysmoothed)
        delta = (pmax-max(cs.sens_noiseM,pmin))*self.fdelta_sensitivity
        xy_max,xy_min = wadwrapper_lib.peakdet(sensitivitysmoothed, delta=delta,x=range(nx))
        
        # select only those peaks where max>noise; alternatively, select those peaks with min<noise
        if self.sens_hicut:
            xy_swap = []
            for xy in xy_max:
                if xy[1]>cs.sens_noiseM:
                    xy_swap.append(xy)
                else:
                    break
            xy_max = xy_swap
            if len(xy_max)>0:
                cs.sens_ylim = max(cs.sens_ylim,max(xy_max,key=operator.itemgetter(0))[0])

            xy_swap = []
            for xy in xy_min:
                if xy[0]<cs.sens_ylim:
                    xy_swap.append(xy)
                else:
                    xy_swap.append(xy) # last point
                    break
            xy_min = xy_swap
        else:
            xy_swap = []
            for xy in xy_min:
                if xy[1]<cs.sens_noiseM or len(xy_swap)<3:
                    xy_swap.append(xy)
                else:
                    break
            xy_min = xy_swap
            if len(xy_min)>1:
                cs.sens_ylim = max(xy_min,key=operator.itemgetter(0))[0]

            xy_swap = []
            for xy in xy_max:
                if xy[0]<cs.sens_ylim:
                    xy_swap.append(xy)
                else:
                    xy_swap.append(xy) # last point
                    break
            xy_max = xy_swap
        cs.sens_numtops = len(xy_max)
        cs.sens_numbots = len(xy_min)
        if cs.testing:
            try:
                import QCUS_testing as mytest
                mytest._exportProfile( xy_max, fname='xy_max.tsv' )
                mytest._exportProfile( xy_min, fname='xy_min.tsv' )
            except:
                pass
        
        if cs.verbose:
            x_max = np.array([xy[0] for xy in xy_max])
            y_max = np.array([xy[1] for xy in xy_max])
            x_min = np.array([xy[0] for xy in xy_min])
            y_min = np.array([xy[1] for xy in xy_min])

            x = np.array(range(nx))
            plt.figure()
            plt.plot(x,sensitivitysmoothed,'k-')
            plt.plot(x_min,y_min,'ro')
            plt.plot(x_max,y_max,'bo')
            cs.hasmadeplots = True


        error = False
        return error
Exemplo n.º 3
0
    def _uniformityAnalysis(self,cs,normuniformity):
        # Helper function for analysis of normalized uniformity profile:
        error = True
        nx = len(normuniformity)
        time0 = time.time()
        self.fftAnalysis(cs,normuniformity,mode='uniformity')
        cs.report.append(('unif_fft',time.time()-time0))

        # peak detection with ugly hack to also allow peaks at index 0 and last
        #xy_max,xy_min = wadwrapper_lib.peakdet(normuniformity, delta=self.delta_uniformity,x=range(nx))
        p0 = normuniformity[::-1]
        p2 = np.append(np.append(p0[:-1],normuniformity),p0[1:]) 
        x2 = np.array(range(-(nx-1),2*nx-1))
        xy_max,xy_min = wadwrapper_lib.peakdet(p2, delta=self.delta_uniformity,x=x2)
        xy_max = [xy for xy in xy_max if xy[0]>-1 and xy[0]<nx]
        xy_min = [xy for xy in xy_min if xy[0]>-1 and xy[0]<nx]

        ## peak analysis
        # sorted list of extrema positions:
        minmax_pos = [da[0] for da in xy_min]
        minmax_pos.extend( [da[0] for da in xy_max] )
        minmax_pos = sorted(minmax_pos)

        # generate an image of non-uniformity
        x_max = np.array([xy[0] for xy in xy_max])
        y_max = np.array([xy[1] for xy in xy_max])
        x_min = np.array([xy[0] for xy in xy_min])
        y_min = np.array([xy[1] for xy in xy_min])

        yran = []
        if self.fastmode: # use only first ring
            print 'Uniformity: FASTMODE',cs.sens_basewavelength
            if cs.sens_basewavelength >0:
                ylim = int(cs.sens_basewavelength/self.pixels2mm(cs,1.)+.5)
                yran = [self.offsetVER,ylim]

        if len(yran) == 0:
            yran = [self.offsetVER,cs.sens_ylim] if cs.sens_ylim>0 else [self.offsetVER]

        plt.figure()
        crop = cropImage(cs.rect_image, [self.offsetHOR], yran)
        plt.imshow(crop.transpose(),cmap=plt.gray())
        x = np.array(range(nx))
        plt.plot(x,-100*normuniformity,'y-',label='100*normalized')
        plt.plot(x_min,-100*y_min,'ro',label='accepted dips')
        plt.plot(x_max,-100*y_max,'bo',label='accepted peaks')
        plt.xlim([0,nx])
        if not self.guimode:
            fname = 'uniformity_'+self.imageID(cs,probeonly=True)+'.jpg'
            plt.savefig(fname)
            cs.image_fnames.append(fname)
        else:
            cs.hasmadeplots = True

        if cs.verbose:
            plt.figure()
            plt.plot(x,normuniformity,'k-')
            plt.plot(x_min,y_min,'ro')
            plt.plot(x_max,y_max,'bo')
            cs.hasmadeplots = True
            
        # possible clean-up of peaks detected
        cs.unif_bots = []
        for damin in xy_min:
            # find range around each dip and remove strongly asymetric dips
            if self.check_asym:
                peak_pos = damin[0]
                peak_val = damin[1]
                asym = True
                delta = self.delta_uniformity
                while asym:
                    pos_left = peak_pos
                    for ix in reversed(range(0,peak_pos)):
                        if normuniformity[ix]>peak_val+delta:
                            pos_left= ix
                            break
                    pos_right = peak_pos
                    for ix in range(peak_pos,nx):
                        if normuniformity[ix]>peak_val+delta:
                            pos_right= ix
                            break
                    if pos_left == peak_pos:
                        print 'ERROR! Could not find left point of peak',peak_ix,peak_pos,peak_val
                        return error
                    if pos_right == peak_pos:
                        print 'ERROR! Could not find left point of peak',peak_ix,peak_pos,peak_val
                        return error
                    # check if we are looking at a strongly symmetric peak
                    if (pos_right-pos_left)>4*min(peak_pos-pos_left,pos_right-peak_pos):
                        delta -= .1*self.delta_uniformity
                        if delta < .2*self.delta_uniformity:
                            break
                    else:
                        asym = False
                if asym:
                    print 'ERROR! Very asymmetric peak',peak_ix,peak_pos,peak_val,peak_pos-pos_left,pos_right-peak_pos
                    continue

            # acceptable
            cs.unif_bots.append(damin)

        # some figures of merit to store: non-unif in deepest dip and overal
        cs.unif_lowest = 1. if len(cs.unif_bots)==0 else min(cs.unif_bots,key=operator.itemgetter(1))[1]
        cs.unif_low = min(normuniformity[1:-1]) # exclude bounds
        error = False
        return error