Пример #1
0
    def reverbUniformity(self,cs):
        """
        Analysis uniformity of reverb pattern
        Workflow:
        1. Define ROI of reverb (dependend on vertical profile)
        2. Average ROI horizontally and calculate COV
        3. Normalize profile as deviation wrt mean
        4. Find dips in profile
        """
        error = True
        
        ## 1. Define ROI of reverb (dependend on vertical profile)
        yran = []
        if self.fastmode:
            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]
            print yran
        if len(yran) == 0:
            yran = [self.offsetVER,cs.sens_ylim] if cs.sens_ylim>0 else [self.offsetVER]

        crop = cropImage(cs.rect_image, [self.offsetHOR], yran)

        uniformity = np.mean(crop,axis=1)
        uniformitysmoothed = mymath.movingaverage(uniformity,self.smooth_uniformity)
        
        ## line uniformity
        intemin = np.min(uniformity)
        intemax = np.max(uniformity)
        inteavg = np.mean(uniformity)
        cs.unif_line = np.max([intemax-inteavg,inteavg-intemin])/inteavg

        # Output of COV 
        meanvalue = np.mean(uniformity) 
        stdvalue = np.std(uniformity)

        # normalized uniformity 
        if self.modeLocalNorm:
            frac = .1
            print "Uniformity, using Local Normalization",frac
            normuniformity = mymath.localnormalization(uniformity, sigma=len(uniformity)*frac)
        else:
            normuniformity = ((uniformitysmoothed-meanvalue)/meanvalue)
            
        if cs.testing:
            try:
                import QCUS_testing as mytest
                mytest._exportProfile(normuniformity,fname='xprofile.tsv')
                mytest._exportNDArray(cs.rect_image)
            except:
                pass
            
        return self._uniformityAnalysis(cs, normuniformity)
Пример #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
Пример #3
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