Ejemplo n.º 1
0
    def calculateShiftsFFT(self, stack, reference, offsets=None, widths=None, crop=False):
        if DEBUG:
            print("Offsets = ", offsets)
            print("Widths = ", widths)
        data = stack.data
        if offsets is None:
            offsets = [0.0, 0.0]
        if widths is None:
            widths = [reference.shape[0], reference.shape[1]]
        fft2Function = numpy.fft.fft2
        if 1:
            DTYPE = numpy.float32
        else:
            DTYPE = numpy.float64
        image2 = numpy.zeros((widths[0], widths[1]), dtype=DTYPE)
        shape = image2.shape

        USE_APODIZATION_WINDOW = False
        apo = [10, 10]
        if USE_APODIZATION_WINDOW:
            # use apodization window
            window = numpy.outer(SpecfitFuns.slit([0.5, shape[0] * 0.5, shape[0] - 4 * apo[0], apo[0]],
                                          numpy.arange(float(shape[0]))),
                                 SpecfitFuns.slit([0.5, shape[1] * 0.5, shape[1] - 4 * apo[1], apo[1]],
                                          numpy.arange(float(shape[1])))).astype(DTYPE)
        else:
            window = numpy.zeros((shape[0], shape[1]), dtype=DTYPE)
            window[apo[0]:shape[0] - apo[0], apo[1]:shape[1] - apo[1]] = 1
        image2[:,:] = window * reference[offsets[0]:offsets[0]+widths[0],
                                         offsets[1]:offsets[1]+widths[1]]
        image2fft2 = fft2Function(image2)
        mcaIndex = stack.info.get('McaIndex')
        shifts = numpy.zeros((data.shape[mcaIndex], 2), numpy.float)
        image1 = numpy.zeros(image2.shape, dtype=DTYPE)
        total = float(data.shape[mcaIndex])
        if mcaIndex == 0:
            for i in range(data.shape[mcaIndex]):
                image1[:,:] = window * data[i][offsets[0]:offsets[0]+widths[0],
                                               offsets[1]:offsets[1]+widths[1]]

                image1fft2 = fft2Function(image1)
                shifts[i] = ImageRegistration.measure_offset_from_ffts(image2fft2,
                                                                       image1fft2)
                if DEBUG:
                    print("Index = %d shift = %.4f, %.4f" % (i, shifts[i][0], shifts[i][1]))
                self._progress = (100 * i) / total
        elif mcaIndex in [2, -1]:
            for i in range(data.shape[mcaIndex]):
                image1[:,:] = window * data[:,:,i][offsets[0]:offsets[0]+widths[0],
                                               offsets[1]:offsets[1]+widths[1]]

                image1fft2 = fft2Function(image1)
                shifts[i] = ImageRegistration.measure_offset_from_ffts(image2fft2,
                                                                       image1fft2)
                if DEBUG:
                    print("Index = %d shift = %.4f, %.4f" % (i, shifts[i][0], shifts[i][1]))
                self._progress = (100 * i) / total
        else:
            raise IndexError("Only stacks of images or spectra supported. 1D index should be 0 or 2")
        return shifts
Ejemplo n.º 2
0
    def guess_fwhm(self, **kw):
        if 'y' in kw:
            y=kw['y']
        else:
            return self.config['FwhmPoints']
        if 'x' in kw:
            x=kw['x']
        else:
            x=numpy.arange(len(y))*1.0

        #set at least a default value for the fwhm
        fwhm=4

        zz=SpecfitFuns.subac(y,1.000,1000)
        yfit=y-zz

        #now I should do some sort of peak search ...
        maximum = max(yfit)
        idx = numpy.nonzero(yfit == maximum)[0]
        pos = numpy.take(x,idx)[-1]
        posindex = idx[-1]
        height = yfit[posindex]
        imin = posindex
        while ((yfit[imin] > 0.5*height) & (imin >0)):
            imin=imin - 1
        imax=posindex
        while ((yfit[imax] > 0.5*height) & (imax <(len(yfit)-1))):
            imax=imax + 1
        fwhm=max(imax-imin-1,fwhm)

        return fwhm
Ejemplo n.º 3
0
def estimateXANESEdge(spectrum, energy=None, full=False):
    if energy is None:
        x = numpy.arange(len(spectrum)).astype(numpy.float)
    else:
        x = numpy.array(energy, dtype=numpy.float, copy=True)
    y = numpy.array(spectrum, dtype=numpy.float, copy=True)

    # make sure data are sorted
    idx = energy.argsort(kind='mergesort')
    x = numpy.take(energy, idx)
    y = numpy.take(spectrum, idx)

    # make sure data are strictly increasing
    delta = x[1:] - x[:-1]
    dmin = delta.min()
    dmax = delta.max()
    if delta.min() <= 1.0e-10:
        # force data are strictly increasing
        # although we do not consider last point
        idx = numpy.nonzero(delta>0)[0]
        x = numpy.take(x, idx)
        y = numpy.take(y, idx)
        delta = None

    sortedX = x
    sortedY = y

    # use a regularly spaced spectrum
    if dmax != dmin:
        # choose the number of points or deduce it from
        # the input data length?
        nchannels = 2 * len(spectrum)
        xi = numpy.linspace(x[1], x[-2], nchannels).reshape(-1, 1)
        x.shape = -1
        y.shape = -1
        y = SpecfitFuns.interpol([x], y, xi, y.min())
        x = xi
        x.shape = -1
        y.shape = -1

    # take the first derivative
    npoints = 7
    xPrime = x[npoints:-npoints]
    yPrime = SGModule.getSavitzkyGolay(y, npoints=npoints, degree=2, order=1)

    # get the index at maximum value
    iMax = numpy.argmax(yPrime)

    # get the center of mass
    w = 2 * npoints
    selection = yPrime[iMax-w:iMax+w+1]
    edge = (selection * xPrime[iMax-w:iMax+w+1]).sum(dtype=numpy.float)/\
           selection.sum(dtype=numpy.float)

    if full:
        # return intermediate information
        return edge, sortedX, sortedY, xPrime, yPrime
    else:
        # return the corresponding x value
        return edge
Ejemplo n.º 4
0
 def bkg_internal(self,pars,x):
    """
    Internal Background
    """
    #fast
    #return self.zz
    #slow: recalculate the background as function of the parameters
    #yy=SpecfitFuns.subac(self.ydata*self.fitconfig['Yscaling'],
    #                     pars[0],pars[1])
    yy=SpecfitFuns.subac(self.ydata*1.0,
                         pars[0],pars[1])
    nrx=shape(x)[0]
    nry=shape(yy)[0]
    if nrx == nry:
         return SpecfitFuns.subac(yy,pars[0],pars[1])
    else:
         return SpecfitFuns.subac(numpy.take(yy,numpy.arange(0,nry,2)),pars[0],pars[1])
Ejemplo n.º 5
0
def estimateXANESEdge(spectrum, energy=None, npoints=5, full=False,
                      sanitize=True):
    if sanitize:
        if energy is None:
            x = numpy.arange(len(spectrum)).astype(numpy.float)
        else:
            x = numpy.array(energy, dtype=numpy.float, copy=False)
        y = numpy.array(spectrum, dtype=numpy.float, copy=False)
        # make sure data are sorted
        idx = energy.argsort(kind='mergesort')
        x = numpy.take(energy, idx)
        y = numpy.take(spectrum, idx)

        # make sure data are strictly increasing
        delta = x[1:] - x[:-1]
        dmin = delta.min()
        dmax = delta.max()
        if delta.min() <= 1.0e-10:
            # force data are strictly increasing
            # although we do not consider last point
            idx = numpy.nonzero(delta>0)[0]
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)
            delta = None

        # use a regularly spaced spectrum
        if dmax != dmin:
            # choose the number of points or deduce it from
            # the input data length?
            nchannels = 10 * x.size
            xi = numpy.linspace(x[1], x[-2], nchannels).reshape(-1, 1)
            x.shape = -1
            y.shape = -1
            y = SpecfitFuns.interpol([x], y, xi, y.min())
            x = xi
    else:
        # take views
        x = energy[:]
        y = spectrum[:]

    x.shape = -1
    y.shape = -1

    # Sorted and regularly spaced values
    sortedX = x
    sortedY = y    

    ddict = getE0SavitzkyGolay(sortedX,
                               sortedY,
                               points=npoints,
                               full=full)
    if full:
        # return intermediate information
        return ddict["edge"], sortedX, sortedY, ddict["xPrime"], ddict["yPrime"]
    else:
        # return the corresponding x value
        return ddict
Ejemplo n.º 6
0
    def interpolate(self, factor=1.):
        """
        Input
        -----
        factor : float
            factor used to oversample existing data, use
            with caution.

        Interpolates all existing curves to an equidistant
        x-range using the either the active or the first
        curve do determine the number of data points.
        Use this method instead of self.getAllCurves() when
        performin FFT related tasks.

        Returns
        -------
        interpCurves : ndarray
            Array containing the interpolated curves shown
            in the plot window.
            Format: [(x0, y0, legend0, info0), ...]
        """
        curves = self.getAllCurves()
        if len(curves) < 1:
            if DEBUG == 1:
                print('interpolate -- no curves present')
            raise ValueError("At least 1 curve needed")
            return

        activeCurve = self.getActiveCurve()
        if not activeCurve:
            activeCurve = curves[0]
        else:
            activeLegend = activeCurve[2]
            idx = list.index([curve[2] for curve in curves],
                             activeLegend)
            activeCurve = curves[idx]
        activeX, activeY, activeLegend, activeInfo = activeCurve[0:4]

        # Determine average spaceing between Datapoints
        step = numpy.average(numpy.diff(activeX))
        xmin, xmax = self.getXLimits([x for (x,y,leg,info) in curves],
                                     overlap=False)
        num  = factor * numpy.ceil((xmax-xmin)/step)

        # Create equidistant x-range, exclude first and last point
        xeq = numpy.linspace(xmin, xmax, num, endpoint=False)[:-1]

        # Interpolate on sections of xeq
        interpCurves = []
        for (x,y,legend,info) in curves:
            idx = numpy.nonzero((x.min()<xeq) & (xeq<x.max()))[0]
            xi = numpy.take(xeq, idx)
            yi = SpecfitFuns.interpol([x], y, xi.reshape(-1,1), y.min())
            yi.shape = -1
            interpCurves += [(xi, yi, legend, info)]
        return interpCurves
Ejemplo n.º 7
0
 def periodic_gauss(self, pars, x):
     """
     Fit function periodic_gauss(pars, x)
     pars = [npeaks, delta, height, position, fwhm]
     """
     newpars = numpy.zeros((pars[0], 3), numpy.float)
     for i in range(int(pars[0])):
         newpars[i, 0] = pars[2]
         newpars[i, 1] = pars[3] + i * pars[1]
         newpars[:, 2] = pars[4]
     return SpecfitFuns.gauss(newpars,x)
Ejemplo n.º 8
0
 def _fitBkgSubtract(spectra, config=None, anchorslist=None, fitmodel=None):
     """Subtract brackground from data and add it to fit model
     """
     for k in range(spectra.shape[1]):
         # obtain the smoothed spectrum
         background = SpecfitFuns.SavitskyGolay(spectra[:, k],
                                 config['fit']['stripfilterwidth'])
         lastAnchor = 0
         for anchor in anchorslist:
             if (anchor > lastAnchor) and (anchor < background.size):
                 background[lastAnchor:anchor] =\
                         SpecfitFuns.snip1d(background[lastAnchor:anchor],
                                            config['fit']['snipwidth'],
                                            0)
                 lastAnchor = anchor
         if lastAnchor < background.size:
             background[lastAnchor:] =\
                     SpecfitFuns.snip1d(background[lastAnchor:],
                                        config['fit']['snipwidth'],
                                        0)
         spectra[:, k] -= background
         if fitmodel is not None:
             fitmodel[:, k] = background
Ejemplo n.º 9
0
    def estimate_linear(self, xx, yy, zzz, xscaling=1.0, yscaling=None):
        # compute strip bg and use it to estimate the linear bg parameters
        zz = SpecfitFuns.subac(yy, 1.000, 10000)
        n = float(len(zz))
        Sy = numpy.sum(zz)
        Sx = float(numpy.sum(xx))
        Sxx = float(numpy.sum(xx * xx))
        Sxy = float(numpy.sum(xx * zz))

        deno = n * Sxx - (Sx * Sx)
        if deno != 0:
            bg = (Sxx * Sy - Sx * Sxy) / deno
            slope = (n * Sxy - Sx * Sy) / deno
        else:
            bg = 0.0
            slope = 0.0
        estimated_par = [bg, slope]
        # code = 0: FREE
        constraints = [[0, 0], [0, 0], [0, 0]]
        return estimated_par, constraints
Ejemplo n.º 10
0
def test():
    import numpy
    from PyMca5.PyMcaMath.fitting import SpecfitFuns
    x = numpy.arange(1000.)
    data = numpy.zeros((50, 1000), numpy.float)

    #the peaks to be fitted
    p0 = [100., 300., 50.,
          200., 500., 30.,
          300., 800., 65]

    #generate the data to be fitted
    for i in range(data.shape[0]):
        nPeaks = 3 - i % 3
        data[i,:] = SpecfitFuns.gauss(p0[:3*nPeaks],x)

    oldShape = data.shape
    data.shape = 1,oldShape[0], oldShape[1]

    instance = StackSimpleFit()
    instance.setData(x, data)
    # TODO: Generate this file "on-the-fly" to be able to test everywhere
    instance.setConfigurationFile(r"C:\StackSimpleFit.cfg")
    instance.processStack()
Ejemplo n.º 11
0
 def stepdown(self,pars,x):
     """
     A fit function.
     """
     return SpecfitFuns.downstep(pars,x)
Ejemplo n.º 12
0
 def splitlorentz(self,pars,x):
    """
    Asymmetric lorentz.
    """
    return SpecfitFuns.splitlorentz(pars,x)
Ejemplo n.º 13
0
 def apvoigt(self,pars,x):
    """
    Fit function.
    """
    return SpecfitFuns.apvoigt(pars,x)
Ejemplo n.º 14
0
 def lorentz(self,pars,x):
    """
    Fit function.
    """
    #return pars[0] + pars [1] * x + SpecfitFuns.lorentz(pars[2:len(pars)],x)
    return SpecfitFuns.lorentz(pars,x)
Ejemplo n.º 15
0
 def agauss(self,pars,x):
    """
    A fit function.
    """
    return SpecfitFuns.agauss(pars,x)
Ejemplo n.º 16
0
    def update(self):
        if self._y is None:
            return

        pars = self.getParameters()

        #smoothed data
        y = numpy.ravel(numpy.array(self._y)).astype(numpy.float)
        ysmooth = SpecfitFuns.SavitskyGolay(y, pars['stripfilterwidth'])        
        f=[0.25,0.5,0.25]
        ysmooth[1:-1] = numpy.convolve(ysmooth,f,mode=0)
        ysmooth[0] = 0.5 *(ysmooth[0] + ysmooth[1])
        ysmooth[-1] = 0.5 * (ysmooth[-1] + ysmooth[-2])

        #loop for anchors
        x = self._x
        niter = pars['stripiterations']
        anchorslist = []
        if pars['stripanchorsflag']:
            if pars['stripanchorslist'] is not None:
                ravelled = x
                for channel in pars['stripanchorslist']:
                    if channel <= ravelled[0]:continue
                    index = numpy.nonzero(ravelled >= channel)[0]
                    if len(index):
                        index = min(index)
                        if index > 0:
                            anchorslist.append(index)
        if niter > 1000:
            stripBackground = SpecfitFuns.subac(ysmooth,
                                            pars['stripconstant'],
                                            niter,
                                            pars['stripwidth'],
                                            anchorslist)
            #final smoothing
            stripBackground = SpecfitFuns.subac(stripBackground,
                                  pars['stripconstant'],
                                  500,1,
                                  anchorslist)
        elif niter > 0:
            stripBackground = SpecfitFuns.subac(ysmooth,
                                            pars['stripconstant'],
                                            niter,
                                            pars['stripwidth'],
                                            anchorslist)
        else:
            stripBackground = 0.0 * ysmooth + ysmooth.min()

        if len(anchorslist) == 0:
            anchorslist = [0, len(ysmooth)-1]
        anchorslist.sort()
        snipBackground = 0.0 * ysmooth
        lastAnchor = 0
        width = pars['snipwidth']
        for anchor in anchorslist:
            if (anchor > lastAnchor) and (anchor < len(ysmooth)):
                snipBackground[lastAnchor:anchor] =\
                            SpecfitFuns.snip1d(ysmooth[lastAnchor:anchor], width, 0)
                lastAnchor = anchor
        if lastAnchor < len(ysmooth):
            snipBackground[lastAnchor:] =\
                            SpecfitFuns.snip1d(ysmooth[lastAnchor:], width, 0)

        self.graphWidget.addCurve(x, y, \
                                  legend='Input Data',\
                                  replace=True,
                                  replot=False)
        self.graphWidget.addCurve(x, stripBackground,\
                                  legend='Strip Background',\
                                  replot=False)
        self.graphWidget.addCurve(x, snipBackground,\
                                  legend='SNIP Background',
                                  replot=True)
Ejemplo n.º 17
0
 def agauss(self,pars,x):
    """
    A fit function.
    """
    return SpecfitFuns.agauss(pars,x)
Ejemplo n.º 18
0
    def XASNormalize(self):
        #all curves
        curves = self.getAllCurves()
        nCurves = len(curves)
        if nCurves < 1:
            raise ValueError("At least one curve needed")
            return

        #get active curve
        activeCurve = self.getActiveCurve()
        if activeCurve is None:
            raise ValueError("Please select an active curve")
            return

        x, y, legend0, info = activeCurve

        #sort the values
        idx = numpy.argsort(x, kind='mergesort')
        x0 = numpy.take(x, idx)
        y0 = numpy.take(y, idx)
        xmin, xmax = self.getGraphXLimits()

        # get calculation parameters
        if self.widget is None:
            self._createWidget(y0, x0)

        parameters = self.parameters
        if parameters['auto_edge']:
            edge = None
        else:
            edge = parameters['edge_energy']
        energy = x
        pre_edge_regions = parameters['pre_edge']['regions']
        post_edge_regions = parameters['post_edge']['regions']
        algorithm ='polynomial'
        algorithm_parameters = {}
        algorithm_parameters['pre_edge_order'] = parameters['pre_edge']\
                                                         ['polynomial']
        algorithm_parameters['post_edge_order'] = parameters['post_edge']\
                                                         ['polynomial']
        i = 0
        lastCurve = None
        for curve in curves:
            x, y, legend, info = curve[0:4]
            #take the portion ox x between limits
            idx = numpy.nonzero((x>=xmin) & (x<=xmax))[0]
            if not len(idx):
                #no overlap
                continue
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)

            idx = numpy.nonzero((x0>=x.min()) & (x0<=x.max()))[0]
            if not len(idx):
                #no overlap
                continue
            xi = numpy.take(x0, idx)
            yi = numpy.take(y0, idx)

            #perform interpolation
            xi.shape = -1, 1
            yw = SpecfitFuns.interpol([x], y, xi, yi.min())

            # try: ... except: here?
            yw.shape = -1
            xi.shape = -1
            x, y = XASNormalization.XASNormalization(yw,
                                energy=xi,
                                edge=edge,
                                pre_edge_regions=pre_edge_regions,
                                post_edge_regions=post_edge_regions,
                                algorithm=algorithm,
                                algorithm_parameters=algorithm_parameters)[0:2]
            #
            if i == 0:
                replace = True
                replot = True
                i = 1
            else:
                replot = False
                replace = False
            newLegend = " ".join(legend.split(" ")[:-1])
            if not newLegend.startswith('Norm.'):
                newLegend = "Norm. " + newLegend
            self.addCurve(x, y,
                          legend=newLegend,
                          info=info,
                          replot=replot,
                          replace=replace)
            lastCurve = [x, y, newLegend]
        self.addCurve(lastCurve[0],
                      lastCurve[1],
                      legend=lastCurve[2],
                      info=info,
                      replot=True,
                      replace=False)
Ejemplo n.º 19
0
    def estimate_gauss(self,xx,yy,zzz,xscaling=1.0,yscaling=None):
       if yscaling == None:
            try:
                yscaling=self.config['Yscaling']
            except:
                yscaling=1.0
       if yscaling == 0:
            yscaling=1.0
       fittedpar=[]
       zz=SpecfitFuns.subac(yy,1.000,10000)

       npoints = len(zz)
       if self.config['AutoFwhm']:
            search_fwhm=self.guess_fwhm(x=xx,y=yy)
       else:
            search_fwhm=int(float(self.config['FwhmPoints']))
       search_sens=float(self.config['Sensitivity'])
       search_mca=int(float(self.config['McaMode']))

       if search_fwhm < 3:
            search_fwhm = 3
            self.config['FwhmPoints']=3

       if search_sens < 1:
            search_sens = 1
            self.config['Sensitivity']=1

       if npoints > 1.5*search_fwhm:
            peaks=self.seek(yy,fwhm=search_fwhm,
                               sensitivity=search_sens,
                               yscaling=yscaling,
                               mca=search_mca)
            #print "estimate peaks = ",peaks
            #peaks=self.seek(yy-zz,fwhm=search_fwhm,
            #                   sensitivity=search_sens,
            #                   yscaling=yscaling,
            #                   mca=search_mca)
       else:
            peaks = []
       if not len(peaks):
            mca = int(float(self.config.get('McaMode', 0)))
            forcePeak =  int(float(self.config.get('ForcePeakPresence', 0)))
            if (not mca) and forcePeak:
                delta = yy - zz
                peaks  = [int(numpy.nonzero(delta == delta.max())[0])]

       #print "peaks = ",peaks
       #print "peaks subac = ",self.seek(yy-zz,fwhm=search_fwhm,
       #                        sensitivity=search_sens,
       #                        yscaling=yscaling,
       #                        mca=search_mca)
       largest_index = 0
       if len(peaks) > 0:
            j = 0
            for i in peaks:
                if j == 0:
                    sig=5*abs(xx[npoints-1]-xx[0])/npoints
                    peakpos = xx[int(i)]
                    if abs(peakpos) < 1.0e-16:
                        peakpos = 0.0
                    param = numpy.array([yy[int(i)] - zz[int(i)], peakpos ,sig])
                    largest = param
                else:
                    param2 = numpy.array([yy[int(i)] - zz [int(i)], xx[int(i)] ,sig])
                    param = numpy.concatenate((param,param2))
                    if (param2[0] > largest[0]):
                        largest = param2
                        largest_index = j
                j = j + 1
            xw = numpy.resize(xx,(npoints,1))
            if (0):
                sy = numpy.sqrt(abs(yy))
                yw = numpy.resize(yy-zz,(npoints,1))
                sy = numpy.resize(sy,(npoints,1))
                datawork = numpy.concatenate((xw,yw,sy),1)
            else:
                yw = numpy.resize(yy-zz,(npoints,1))
                datawork = numpy.concatenate((xw,yw),1)
            cons = numpy.zeros((3,len(param)),numpy.float64)
            cons [0] [0:len(param):3] = CPOSITIVE
            #force peaks to stay around their position
            if (1):
                cons [0] [1:len(param):3] = CQUOTED
                #This does not work!!!!
                #FWHM should be given in terms of X not of points!
                #cons [1] [1:len(param):3] = param[1:len(param):3]-0.5*search_fwhm
                #cons [2] [1:len(param):3] = param[1:len(param):3]+0.5*search_fwhm
                if len(xw) > search_fwhm:
                    fwhmx = numpy.fabs(xw[int(search_fwhm)]-xw[0])
                    cons [1] [1:len(param):3] = param[1:len(param):3]-0.5*fwhmx
                    cons [2] [1:len(param):3] = param[1:len(param):3]+0.5*fwhmx
                else:
                    cons [1] [1:len(param):3] = numpy.ones(shape(param[1:len(param):3]),numpy.float64)*min(xw)
                    cons [2] [1:len(param):3] = numpy.ones(shape(param[1:len(param):3]),numpy.float64)*max(xw)

            if 0:
                cons [0] [2:len(param):3] = CFACTOR
                cons [1] [2:len(param):3] = 2
                cons [2] [2:len(param):3] = 1.0
                cons [0] [2] = CPOSITIVE
                cons [1] [2] = 0
                cons [2] [2] = 0
            else:
                cons [0] [2:len(param):3] = CPOSITIVE
            fittedpar, chisq, sigmapar = LeastSquaresFit(SpecfitFuns.gauss,param,
                                            datawork,
                                            weightflag=self.config['WeightFlag'],
                                            maxiter=4,constrains=cons.tolist())
            #I already have the estimation
            #yw=yy-zz-SpecfitFuns.gauss(fittedpar,xx)
            #if DEBUG:
            #    SimplePlot.plot([xx,yw])
            #print self.seek(yw,\
            #                   fwhm=search_fwhm,\
            #                   sensitivity=search_sens,\
            #                   yscaling=yscaling)
       #else:
       #     #Use SPEC estimate ...
       #     peakpos,height,myidx = SpecArithmetic.search_peak(xx,yy-zz)
       #     fwhm,cfwhm         = SpecArithmetic.search_fwhm(xx,yy-zz,
       #                                    peak=peakpos,index=myidx)
       #     xx = numpy.array(xx)
       #     if npoints > 2:
       #         #forget SPEC estimation of fwhm
       #         fwhm=5*abs(xx[npoints-1]-xx[0])/npoints
       #     fittedpar=[height,peakpos,fwhm]
       #     largest=numpy.array([height,peakpos,fwhm])
       #     peaks=[peakpos]
       cons = numpy.zeros((3,len(fittedpar)),numpy.float64)
       j=0
       for i in range(len(peaks)):
                #Setup height area constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['HeightAreaFlag']:
                        #POSITIVE = 1
                        cons[0] [j] = 1
                        cons[1] [j] = 0
                        cons[2] [j] = 0
                j=j+1


                #Setup position constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['PositionFlag']:
                                #QUOTED = 2
                                cons[0][j]=2
                                cons[1][j]=min(xx)
                                cons[2][j]=max(xx)
                j=j+1

                #Setup positive FWHM constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['PosFwhmFlag']:
                                #POSITIVE=1
                                cons[0][j]=1
                                cons[1][j]=0
                                cons[2][j]=0
                    if self.config['SameFwhmFlag']:
                        if (i != largest_index):
                                #FACTOR=4
                                cons[0][j]=4
                                cons[1][j]=3*largest_index+2
                                cons[2][j]=1.0
                j=j+1
       return fittedpar,cons
Ejemplo n.º 20
0
    def seek(self,y,x=None,yscaling=None,
                           fwhm=None,
                           sensitivity=None,
                           mca=None):
        """
        SpecfitFunctions.seek(self,y,
                                x=None,
                                yscaling=None,fwhm=None,sensitivity=None,
                                mca=None)
        It searches for peaks in the y array. If x it is given, it gives back
        the closest x(s) to the position of the peak(s). Otherways it gives back
        the index of the closest point to the peak.
        """
        if yscaling is None:
            yscaling=self.config['Yscaling']

        if fwhm is None:
            if self.config['AutoFwhm']:
                fwhm=self.guess_fwhm(x=x,y=y)
            else:
                fwhm=self.config['FwhmPoints']
        if sensitivity is None:
            sensitivity=self.config['Sensitivity']
        if mca is None:
            mca=self.config['McaMode']

        search_fwhm=int(max(fwhm,3))
        search_sensitivity=max(1.0,sensitivity)
        mca=1.0
        if mca:
            ysearch = numpy.array(y) * yscaling
        else:
            ysearch = numpy.ones([len(y) + 2 * search_fwhm,], numpy.float64)
            if y[0]:
                ysearch[0:(search_fwhm+1)]=ysearch[0:(search_fwhm+1)]*y[0]*yscaling
            else:
                ysearch[0:(search_fwhm+1)]=ysearch[0:(search_fwhm+1)]*yscaling*sum(y[0:3])/3.0
            ysearch[-1:-(search_fwhm+1):-1]=ysearch[-1:-(search_fwhm+1):-1]*y[len(y)-1]*yscaling
            ysearch[search_fwhm:(search_fwhm+len(y))]=y*yscaling
        npoints=len(ysearch)
        if npoints > (1.5)*search_fwhm:
            peaks=SpecfitFuns.seek(ysearch,0,npoints,
                                    search_fwhm,
                                    search_sensitivity)
        else:
            peaks=[]

        if len(peaks) > 0:
            if mca == 0:
                for i in range(len(peaks)):
                    peaks[i]=int(peaks[i]-search_fwhm)
            for i in peaks:
                if (i < 1) | (i > (npoints-1)):
                    peaks.remove(i)
            if x is not None:
                if len(x) == len(y):
                    for i in range(len(peaks)):
                        peaks[i]=x[int(max(peaks[i],0))]
        #print "peaks found = ",peaks,"mca =",mca,"fwhm=",search_fwhm,\
        #        "sensi=",search_sensitivity,"scaling=",yscaling
        return peaks
Ejemplo n.º 21
0
 def slit(self,pars,x):
     """
     A fit function.
     """
     return 0.5*SpecfitFuns.slit(pars,x)
Ejemplo n.º 22
0
 def stepup(self,pars,x):
     """
     A fit function.
     """
     return SpecfitFuns.upstep(pars,x)
Ejemplo n.º 23
0
 def stepdown(self,pars,x):
     """
     A fit function.
     """
     return SpecfitFuns.downstep(pars,x)
Ejemplo n.º 24
0
 def slit(self,pars,x):
     """
     A fit function.
     """
     return 0.5*SpecfitFuns.slit(pars,x)
Ejemplo n.º 25
0
 def hypermet(self,pars,x):
    """
    A fit function.
    """
    return SpecfitFuns.ahypermet(pars,x,self.config['HypermetTails'],0)
Ejemplo n.º 26
0
    def divideByActiveCurve(self):
        #all curves
        curves = self.getAllCurves()
        nCurves = len(curves)
        if nCurves < 2:
            raise ValueError("At least two curves needed")
            return

        #get active curve
        activeCurve = self.getActiveCurve()
        if activeCurve is None:
            raise ValueError("Please select an active curve")
            return

        x, y, legend0, info = activeCurve
        xmin, xmax = self.getGraphXLimits()
        y = y.astype(numpy.float)

        #get the nonzero values
        idx = numpy.nonzero(abs(y) != 0.0)[0]
        if not len(idx):
            raise ValueError("All divisor values are zero!")
        x0 = numpy.take(x, idx)
        y0 = numpy.take(y, idx)

        #sort the values
        idx = numpy.argsort(x0, kind='mergesort')
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        i = 0
        for curve in curves:
            x, y, legend, info = curve[0:4]
            if legend == legend0:
                continue
            #take the portion ox x between limits
            idx = numpy.nonzero((x >= xmin) & (x <= xmax))[0]
            if not len(idx):
                #no overlap
                continue
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)

            idx = numpy.nonzero((x0 >= numpy.nanmin(x))
                                & (x0 <= numpy.nanmax(x)))[0]
            if not len(idx):
                #no overlap
                continue
            xi = numpy.take(x0, idx)
            yi = numpy.take(y0, idx)

            #perform interpolation
            xi.shape = -1, 1
            yw = SpecfitFuns.interpol([x], y, xi, yi.min())
            y = yw / yi
            if i == 0:
                replace = (self._plotType != "MCA")
                replot = True
                i = 1
            else:
                replot = False
                replace = False
            # this line is absolutely necessary!
            xi.shape = y.shape
            self.addCurve(xi,
                          y,
                          legend=legend,
                          info=info,
                          replot=replot,
                          replace=replace)
            lastCurve = [xi, y, legend]
        self.addCurve(lastCurve[0],
                      lastCurve[1],
                      legend=lastCurve[2],
                      info=info,
                      replot=True,
                      replace=False)
Ejemplo n.º 27
0
 def splitpvoigt(self,pars,x):
    """
    Asymmetric pseudovoigt.
    """
    return SpecfitFuns.splitpvoigt(pars,x)
Ejemplo n.º 28
0
    def estimate_periodic_gauss(self,xx,yy,zzz,xscaling=1.0,yscaling=None):
        if yscaling == None:
            try:
                yscaling=self.config['Yscaling']
            except:
                yscaling=1.0
        if yscaling == 0:
            yscaling=1.0
        fittedpar=[]
        zz=SpecfitFuns.subac(yy,1.000,10000)

        npoints = len(zz)
        if self.config['AutoFwhm']:
            search_fwhm=self.guess_fwhm(x=xx,y=yy)
        else:
            search_fwhm=int(float(self.config['FwhmPoints']))
        search_sens=float(self.config['Sensitivity'])
        search_mca=int(float(self.config['McaMode']))

        if search_fwhm < 3:
            search_fwhm = 3
            self.config['FwhmPoints']=3

        if search_sens < 1:
            search_sens = 1
            self.config['Sensitivity']=1

        if npoints > 1.5*search_fwhm:
            peaks=self.seek(yy,fwhm=search_fwhm,
                               sensitivity=search_sens,
                               yscaling=yscaling,
                               mca=search_mca)
        else:
             peaks = []
        npeaks = len(peaks)
        if not npeaks:
            fittedpar = []
            cons = numpy.zeros((3,len(fittedpar)), numpy.float)
            return fittedpar, cons

        fittedpar = [0.0, 0.0, 0.0, 0.0, 0.0]

        #The number of peaks
        fittedpar[0] = npeaks

        #The separation between peaks in x units
        delta  = 0.0
        height = 0.0
        for i in range(npeaks):
            height += yy[int(peaks[i])] - zz [int(peaks[i])]
            if i != ((npeaks)-1):
                delta += (xx[int(peaks[i+1])] - xx[int(peaks[i])])

        #delta between peaks
        if npeaks > 1:
            fittedpar[1] = delta/(npeaks-1)

        #starting height
        fittedpar[2] = height/npeaks

        #position of the first peak
        fittedpar[3] = xx[int(peaks[0])]

        #Estimate the fwhm
        fittedpar[4] = search_fwhm

        #setup constraints
        cons = numpy.zeros((3, 5), numpy.float)
        cons [0] [0] = CFIXED     #the number of gaussians
        if npeaks == 1:
            cons[0][1] = CFIXED  #the delta between peaks
        else:
            cons[0][1] = CFREE   #the delta between peaks
        j = 2
        #Setup height area constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['HeightAreaFlag']:
                #POSITIVE = 1
                cons[0] [j] = 1
                cons[1] [j] = 0
                cons[2] [j] = 0
        j=j+1

        #Setup position constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['PositionFlag']:
                        #QUOTED = 2
                        cons[0][j]=2
                        cons[1][j]=min(xx)
                        cons[2][j]=max(xx)
        j=j+1

        #Setup positive FWHM constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['PosFwhmFlag']:
                        #POSITIVE=1
                        cons[0][j]=1
                        cons[1][j]=0
                        cons[2][j]=0
        j=j+1
        return fittedpar,cons
Ejemplo n.º 29
0
    def estimate_periodic_gauss(self,xx,yy,zzz,xscaling=1.0,yscaling=None):
        if yscaling == None:
            try:
                yscaling=self.config['Yscaling']
            except:
                yscaling=1.0
        if yscaling == 0:
            yscaling=1.0
        fittedpar=[]
        zz=SpecfitFuns.subac(yy,1.000,10000)

        npoints = len(zz)
        if self.config['AutoFwhm']:
            search_fwhm=self.guess_fwhm(x=xx,y=yy)
        else:
            search_fwhm=int(float(self.config['FwhmPoints']))
        search_sens=float(self.config['Sensitivity'])
        search_mca=int(float(self.config['McaMode']))

        if search_fwhm < 3:
            search_fwhm = 3
            self.config['FwhmPoints']=3

        if search_sens < 1:
            search_sens = 1
            self.config['Sensitivity']=1

        if npoints > 1.5*search_fwhm:
            peaks=self.seek(yy,fwhm=search_fwhm,
                               sensitivity=search_sens,
                               yscaling=yscaling,
                               mca=search_mca)
        else:
             peaks = []
        npeaks = len(peaks)
        if not npeaks:
            fittedpar = []
            cons = numpy.zeros((3,len(fittedpar)), numpy.float)
            return fittedpar, cons

        fittedpar = [0.0, 0.0, 0.0, 0.0, 0.0]

        #The number of peaks
        fittedpar[0] = npeaks

        #The separation between peaks in x units
        delta  = 0.0
        height = 0.0
        for i in range(npeaks):
            height += yy[int(peaks[i])] - zz [int(peaks[i])]
            if i != ((npeaks)-1):
                delta += (xx[int(peaks[i+1])] - xx[int(peaks[i])])

        #delta between peaks
        if npeaks > 1:
            fittedpar[1] = delta/(npeaks-1)

        #starting height
        fittedpar[2] = height/npeaks

        #position of the first peak
        fittedpar[3] = xx[int(peaks[0])]

        #Estimate the fwhm
        fittedpar[4] = search_fwhm

        #setup constraints
        cons = numpy.zeros((3, 5), numpy.float)
        cons [0] [0] = CFIXED     #the number of gaussians
        if npeaks == 1:
            cons[0][1] = CFIXED  #the delta between peaks
        else:
            cons[0][1] = CFREE   #the delta between peaks
        j = 2
        #Setup height area constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['HeightAreaFlag']:
                #POSITIVE = 1
                cons[0] [j] = 1
                cons[1] [j] = 0
                cons[2] [j] = 0
        j=j+1

        #Setup position constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['PositionFlag']:
                        #QUOTED = 2
                        cons[0][j]=2
                        cons[1][j]=min(xx)
                        cons[2][j]=max(xx)
        j=j+1

        #Setup positive FWHM constrains
        if self.config['NoConstrainsFlag'] == 0:
            if self.config['PosFwhmFlag']:
                        #POSITIVE=1
                        cons[0][j]=1
                        cons[1][j]=0
                        cons[2][j]=0
        j=j+1
        return fittedpar,cons
Ejemplo n.º 30
0
 def splitgauss(self,pars,x):
    """
    Asymmetric gaussian.
    """
    return SpecfitFuns.splitgauss(pars,x)
Ejemplo n.º 31
0
 def hypermet(self,pars,x):
    """
    A fit function.
    """
    return SpecfitFuns.ahypermet(pars,x,self.config['HypermetTails'],0)
Ejemplo n.º 32
0
def _getROILineProfileCurve(image, roiStart, roiEnd, roiWidth,
                            lineProjectionMode):
    """Returns the profile values and the polygon in the given ROI.

    Works in image coordinates.

    See :func:`getAlignedROIProfileCurve`.
    """
    row0, col0 = roiStart
    row1, col1 = roiEnd

    deltaRow = abs(row1 - row0)
    deltaCol = abs(col1 - col0)

    if (lineProjectionMode == 'X' or
            (lineProjectionMode == 'D' and deltaCol >= deltaRow)):
        nPoints = deltaCol + 1
        coordsRange = col0, col1
    else:  # 'Y' or ('D' and deltaCol < deltaRow)
        nPoints = deltaRow + 1
        coordsRange = row0, row1

    if nPoints == 1:  # all points are the same
        if DEBUG:
            print("START AND END POINT ARE THE SAME!!")
        return None

    # the coordinates of the reference points
    x0 = numpy.arange(image.shape[0], dtype=numpy.float)
    y0 = numpy.arange(image.shape[1], dtype=numpy.float)

    if roiWidth < 1:
        x = numpy.zeros((nPoints, 2), numpy.float)
        x[:, 0] = numpy.linspace(row0, row1, nPoints)
        x[:, 1] = numpy.linspace(col0, col1, nPoints)
        # perform the interpolation
        ydata = SpecfitFuns.interpol((x0, y0), image, x)

        roiPolygonCols = numpy.array((col0, col1), dtype=numpy.float)
        roiPolygonRows = numpy.array((row0, row1), dtype=numpy.float)

    else:
        # find m and b in the line y = mx + b
        m = (row1 - row0) / float((col1 - col0))
        # Not used: b = row0 - m * col0
        alpha = numpy.arctan(m)
        # imagine the following sequence
        # - change origin to the first point
        # - clock-wise rotation to bring the line on the x axis of a new system
        #   so that the points (col0, row0) and (col1, row1)
        #   become (x0, 0) (x1, 0).
        # - counter clock-wise rotation to get the points (x0, -0.5 width),
        #   (x0, 0.5 width), (x1, 0.5 * width) and (x1, -0.5 * width) back to
        #   the original system.
        # - restore the origin to (0, 0)
        # - if those extremes are inside the image the selection is acceptable
        cosalpha = numpy.cos(alpha)
        sinalpha = numpy.sin(alpha)
        newCol0 = 0.0
        newCol1 = (col1 - col0) * cosalpha + (row1 - row0) * sinalpha
        newRow0 = 0.0
        newRow1 = - (col1 - col0) * sinalpha + (row1 - row0) * cosalpha

        if DEBUG:
            print("new X0 Y0 = %f, %f  " % (newCol0, newRow0))
            print("new X1 Y1 = %f, %f  " % (newCol1, newRow1))

        tmpX = numpy.linspace(newCol0, newCol1,
                              nPoints).astype(numpy.float)
        rotMatrix = numpy.zeros((2, 2), dtype=numpy.float)
        rotMatrix[0, 0] = cosalpha
        rotMatrix[0, 1] = - sinalpha
        rotMatrix[1, 0] = sinalpha
        rotMatrix[1, 1] = cosalpha
        if DEBUG:
            # test if I recover the original points
            testX = numpy.zeros((2, 1), numpy.float)
            colRow = numpy.dot(rotMatrix, testX)
            print("Recovered X0 = %f" % (colRow[0, 0] + col0))
            print("Recovered Y0 = %f" % (colRow[1, 0] + row0))
            print("It should be = %f, %f" % (col0, row0))
            testX[0, 0] = newCol1
            testX[1, 0] = newRow1
            colRow = numpy.dot(rotMatrix, testX)
            print("Recovered X1 = %f" % (colRow[0, 0] + col0))
            print("Recovered Y1 = %f" % (colRow[1, 0] + row0))
            print("It should be = %f, %f" % (col1, row1))

        # find the drawing limits
        testX = numpy.zeros((2, 4), numpy.float)
        testX[0, 0] = newCol0
        testX[0, 1] = newCol0
        testX[0, 2] = newCol1
        testX[0, 3] = newCol1
        testX[1, 0] = newRow0 - 0.5 * roiWidth
        testX[1, 1] = newRow0 + 0.5 * roiWidth
        testX[1, 2] = newRow1 + 0.5 * roiWidth
        testX[1, 3] = newRow1 - 0.5 * roiWidth
        colRow = numpy.dot(rotMatrix, testX)
        colLimits0 = colRow[0, :] + col0
        rowLimits0 = colRow[1, :] + row0

        for a in rowLimits0:
            if (a >= image.shape[0]) or (a < 0):
                print("outside row limits", a)
                return None
        for a in colLimits0:
            if (a >= image.shape[1]) or (a < 0):
                print("outside column limits", a)
                return None

        r0 = rowLimits0[0]
        r1 = rowLimits0[1]

        if r0 > r1:
            print("r0 > r1", r0, r1)
            raise ValueError("r0 > r1")

        x = numpy.zeros((2, nPoints), numpy.float)

        # oversampling solves noise introduction issues
        oversampling = roiWidth + 1
        oversampling = min(oversampling, 21)
        ncontributors = roiWidth * oversampling
        iterValues = numpy.linspace(-0.5 * roiWidth, 0.5 * roiWidth,
                                    ncontributors)
        tmpMatrix = numpy.zeros((nPoints * len(iterValues), 2),
                                dtype=numpy.float)
        x[0, :] = tmpX
        offset = 0
        for i in iterValues:
            x[1, :] = i
            colRow = numpy.dot(rotMatrix, x)
            colRow[0, :] += col0
            colRow[1, :] += row0
            # it is much faster to make one call to the interpolating
            # routine than making many calls
            tmpMatrix[offset:(offset + nPoints), 0] = colRow[1, :]
            tmpMatrix[offset:(offset + nPoints), 1] = colRow[0, :]
            offset += nPoints
        ydata = SpecfitFuns.interpol((x0, y0), image, tmpMatrix)
        ydata.shape = len(iterValues), nPoints
        ydata = ydata.sum(axis=0)
        # deal with the oversampling
        ydata /= oversampling

        roiPolygonCols, roiPolygonRows = colLimits0, rowLimits0

    return {'profileValues': ydata,
            'profileCoordsRange': coordsRange,
            'roiPolygonCols': roiPolygonCols,
            'roiPolygonRows': roiPolygonRows}
Ejemplo n.º 33
0
 def alorentz(self,pars,x):
    """
    Fit function.
    """
    return SpecfitFuns.alorentz(pars,x)
Ejemplo n.º 34
0
 def apvoigt(self,pars,x):
    """
    Fit function.
    """
    return SpecfitFuns.apvoigt(pars,x)
Ejemplo n.º 35
0
 def splitgauss(self,pars,x):
    """
    Asymmetric gaussian.
    """
    return SpecfitFuns.splitgauss(pars,x)
Ejemplo n.º 36
0
 def alorentz(self,pars,x):
    """
    Fit function.
    """
    return SpecfitFuns.alorentz(pars,x)
Ejemplo n.º 37
0
 def splitpvoigt(self,pars,x):
    """
    Asymmetric pseudovoigt.
    """
    return SpecfitFuns.splitpvoigt(pars,x)
Ejemplo n.º 38
0
    def fftAlignment(self):
        curves = self.getMonotonicCurves()
        nCurves = len(curves)
        if nCurves < 2:
            raise ValueError("At least 2 curves needed")
            return

        # get legend of active curve
        try:
            activeCurveLegend = self.getActiveCurve()[2]
            if activeCurveLegend is None:
                activeCurveLegend = curves[0][2]
            for curve in curves:
                if curve[2] == activeCurveLegend:
                    activeCurve = curve
                    break
        except:
            activeCurve = curves[0]
            activeCurveLegend = activeCurve[2]

        # apply between graph limits
        x0, y0 = activeCurve[0:2]
        xmin, xmax =self.getGraphXLimits()

        for curve in curves:
            xmax = float(min(xmax, curve[0][-1]))
            xmin = float(max(xmin, curve[0][0]))

        idx = numpy.nonzero((x0 >= xmin) & (x0 <= xmax))[0]
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        #make sure values are regularly spaced
        xi = numpy.linspace(x0[0], x0[-1], len(idx)).reshape(-1, 1)
        yi = SpecfitFuns.interpol([x0], y0, xi, y0.min())
        x0 = xi * 1
        y0 = yi * 1

        y0.shape = -1
        fft0 = numpy.fft.fft(y0)
        y0.shape = -1, 1
        x0.shape = -1, 1
        nChannels = x0.shape[0]

        # built a couple of temporary array of spectra for handy access
        shiftList = []
        curveList = []
        i = 0
        activeCurveIndex = 0
        for idx in range(nCurves):
            x, y, legend, info = curves[idx][0:4]
            if legend == activeCurveLegend:
                needInterpolation = False
                activeCurveIndex = idx
            elif x.size != x0.size:
                needInterpolation = True
            elif numpy.allclose(x, x0):
                # no need for interpolation
                needInterpolation = False
            else:
                needInterpolation = True

            if needInterpolation:
                # we have to interpolate
                x.shape = -1
                y.shape = -1
                xi = x0[:] * 1
                y = SpecfitFuns.interpol([x], y, xi, y0.min())
                x = xi

            y.shape = -1
            i += 1

            # now calculate the shift
            ffty = numpy.fft.fft(y)

            if numpy.allclose(fft0, ffty):
                shiftList.append(0.0)
                x.shape = -1
            else:
                shift = numpy.fft.ifft(fft0 * ffty.conjugate()).real
                shift2 = numpy.zeros(shift.shape, dtype=shift.dtype)
                m = shift2.size//2
                shift2[m:] = shift[:-m]
                shift2[:m] = shift[-m:]
                threshold = 0.80*shift2.max()
                #threshold = shift2.mean()
                idx = numpy.nonzero(shift2 > threshold)[0]
                #print("max indices = %d" % (m - idx))
                shift = (shift2[idx] * idx/shift2[idx].sum()).sum()
                #print("shift = ", shift - m, "in x units = ", (shift - m) * (x[1]-x[0]))

                # shift the curve
                shift = (shift - m) * (x[1]-x[0])
                x.shape = -1
                y = numpy.fft.ifft(numpy.exp(-2.0*numpy.pi*numpy.sqrt(numpy.complex(-1))*\
                                numpy.fft.fftfreq(len(x), d=x[1]-x[0])*shift)*ffty)
                y = y.real
                y.shape = -1
            curveList.append([x, y, legend + "SHIFT", False, False])
        curveList[-1][-2] = True
        curveList[-1][-1] = False
        x, y, legend, replot, replace = curveList[activeCurveIndex]
        self.addCurve(x, y, legend=legend, replot=True, replace=True)
        for i in range(len(curveList)):
            if i == activeCurveIndex:
                continue
            x, y, legend, replot, replace = curveList[i]
            self.addCurve(x,
                          y,
                          legend=legend,
                          info=None,
                          replot=replot,
                          replace=False)
        return
Ejemplo n.º 39
0
 def stepup(self,pars,x):
     """
     A fit function.
     """
     return SpecfitFuns.upstep(pars,x)
Ejemplo n.º 40
0
    def applyMedianFilter(self, width=3):
        curves = self.getAllCurves()
        nCurves = len(curves)
        if nCurves < width:
            raise ValueError("At least %d curves needed" % width)
            return

        if self.__randomization:
            indices = numpy.random.permutation(nCurves)
        else:
            indices = range(nCurves)

        # get active curve
        activeCurve = self.getActiveCurve()
        if activeCurve is None:
            activeCurve = curves[0]

        # apply between graph limits
        x0 = activeCurve[0][:]
        y0 = activeCurve[1][:]
        xmin, xmax =self.getGraphXLimits()
        idx = numpy.nonzero((x0 >= xmin) & (x0 <= xmax))[0]
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        #sort the values
        idx = numpy.argsort(x0, kind='mergesort')
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        #remove duplicates
        x0 = x0.ravel()
        idx = numpy.nonzero((x0[1:] > x0[:-1]))[0]
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        x0.shape = -1, 1
        nChannels = x0.shape[0]

        # built a couple of temporary array of spectra for handy access
        tmpArray = numpy.zeros((nChannels, nCurves), numpy.float64)
        medianSpectra = numpy.zeros((nChannels, nCurves), numpy.float64)
        i = 0
        for idx in indices:
            x, y, legend, info = curves[idx][0:4]
            #sort the values
            x = x[:]
            idx = numpy.argsort(x, kind='mergesort')
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)

            #take the portion of x between limits
            idx = numpy.nonzero((x>=xmin) & (x<=xmax))[0]
            if not len(idx):
                # no overlap
                continue
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)

            #remove duplicates
            x = x.ravel()
            idx = numpy.nonzero((x[1:] > x[:-1]))[0]
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)
            x.shape = -1, 1
            if numpy.allclose(x, x0):
                # no need for interpolation
                pass
            else:
                # we have to interpolate
                x.shape = -1
                y.shape = -1
                xi = x0[:]
                y = SpecfitFuns.interpol([x], y, xi, y0.min())
            y.shape = -1
            tmpArray[:, i] = y
            i += 1

        # now perform the median filter
        for i in range(nChannels):
            medianSpectra[i, :] = medfilt1d(tmpArray[i,:],
                                            kernel_size=width)
        tmpArray = None
        # now get the final spectrum
        y = medianSpectra.sum(axis=1) / nCurves
        x0.shape = -1
        y.shape = x0.shape
        legend = "%d Median from %s to %s" % (width,
                                              curves[0][2],
                                              curves[-1][2])
        self.addCurve(x0,
                      y,
                      legend=legend,
                      info=None,
                      replot=True,
                      replace=True)
Ejemplo n.º 41
0
 def lorentz(self,pars,x):
    """
    Fit function.
    """
    #return pars[0] + pars [1] * x + SpecfitFuns.lorentz(pars[2:len(pars)],x)
    return SpecfitFuns.lorentz(pars,x)
Ejemplo n.º 42
0
    def divideByActiveCurve(self):
        #all curves
        curves = self.getAllCurves()
        nCurves = len(curves)
        if nCurves < 2:
            raise ValueError("At least two curves needed")
            return

        #get active curve
        activeCurve = self.getActiveCurve()
        if activeCurve is None:
            raise ValueError("Please select an active curve")
            return

        x, y, legend0, info = activeCurve
        xmin, xmax = self.getGraphXLimits()
        y = y.astype(numpy.float)

        #get the nonzero values
        idx = numpy.nonzero(abs(y) != 0.0)[0]
        if not len(idx):
            raise ValueError("All divisor values are zero!")
        x0 = numpy.take(x, idx)
        y0 = numpy.take(y, idx)

        #sort the values
        idx = numpy.argsort(x0, kind='mergesort')
        x0 = numpy.take(x0, idx)
        y0 = numpy.take(y0, idx)

        i = 0
        for curve in curves:
            x, y, legend, info = curve[0:4]
            if legend == legend0:
                continue
            #take the portion ox x between limits
            idx = numpy.nonzero((x>=xmin) & (x<=xmax))[0]
            if not len(idx):
                #no overlap
                continue
            x = numpy.take(x, idx)
            y = numpy.take(y, idx)

            idx = numpy.nonzero((x0>=x.min()) & (x0<=x.max()))[0]
            if not len(idx):
                #no overlap
                continue
            xi = numpy.take(x0, idx)
            yi = numpy.take(y0, idx)

            #perform interpolation
            xi.shape = -1, 1
            yw = SpecfitFuns.interpol([x], y, xi, yi.min())
            y = yw / yi
            if i == 0:
                replace = True
                replot = True
                i = 1
            else:
                replot = False
                replace = False
            self.addCurve(x, y,
                          legend=legend,
                          info=info,
                          replot=replot,
                          replace=replace)
            lastCurve = [x, y, legend]
        self.addCurve(lastCurve[0],
                      lastCurve[1],
                      legend=lastCurve[2],
                      info=info,
                      replot=True,
                      replace=False)
Ejemplo n.º 43
0
    def seek(self,y,x=None,yscaling=None,
                           fwhm=None,
                           sensitivity=None,
                           mca=None):
        """
        SpecfitFunctions.seek(self,y,
                                x=None,
                                yscaling=None,fwhm=None,sensitivity=None,
                                mca=None)
        It searches for peaks in the y array. If x it is given, it gives back
        the closest x(s) to the position of the peak(s). Otherways it gives back
        the index of the closest point to the peak.
        """
        if yscaling is None:
            yscaling=self.config['Yscaling']

        if fwhm is None:
            if self.config['AutoFwhm']:
                fwhm=self.guess_fwhm(x=x,y=y)
            else:
                fwhm=self.config['FwhmPoints']
        if sensitivity is None:
            sensitivity=self.config['Sensitivity']
        if mca is None:
            mca=self.config['McaMode']

        search_fwhm=int(max(fwhm,3))
        search_sensitivity=max(1.0,sensitivity)
        mca=1.0
        if mca:
            ysearch = numpy.array(y) * yscaling
        else:
            ysearch = numpy.ones([len(y) + 2 * search_fwhm,], numpy.float)
            if y[0]:
                ysearch[0:(search_fwhm+1)]=ysearch[0:(search_fwhm+1)]*y[0]*yscaling
            else:
                ysearch[0:(search_fwhm+1)]=ysearch[0:(search_fwhm+1)]*yscaling*sum(y[0:3])/3.0
            ysearch[-1:-(search_fwhm+1):-1]=ysearch[-1:-(search_fwhm+1):-1]*y[len(y)-1]*yscaling
            ysearch[search_fwhm:(search_fwhm+len(y))]=y*yscaling
        npoints=len(ysearch)
        if npoints > (1.5)*search_fwhm:
            peaks=SpecfitFuns.seek(ysearch,0,npoints,
                                    search_fwhm,
                                    search_sensitivity)
        else:
            peaks=[]

        if len(peaks) > 0:
            if mca == 0:
                for i in range(len(peaks)):
                    peaks[i]=int(peaks[i]-search_fwhm)
            for i in peaks:
                if (i < 1) | (i > (npoints-1)):
                    peaks.remove(i)
            if x is not None:
                if len(x) == len(y):
                    for i in range(len(peaks)):
                        peaks[i]=x[int(max(peaks[i],0))]
        #print "peaks found = ",peaks,"mca =",mca,"fwhm=",search_fwhm,\
        #        "sensi=",search_sensitivity,"scaling=",yscaling
        return peaks
Ejemplo n.º 44
0
        self.setEnabled(True)

if __name__ == "__main__":
    import numpy
    from PyMca5.PyMcaMath.fitting import SpecfitFuns
    from PyMca5.PyMcaMath.fitting import SimpleFitUserEstimatedFunctions as Functions
    x = numpy.arange(1000.)
    data = numpy.zeros((50, 1000), numpy.float)

    #the peaks to be fitted
    p0 = [100., 300., 50.,
          200., 500., 30.,
          300., 800., 65]

    #generate the data to be fitted
    for i in range(data.shape[0]):
        nPeaks = 3 - i % 3
        data[i,:] = SpecfitFuns.gauss(p0[:3*nPeaks],x)
    #the spectrum for setup
    y = data.sum(axis=0)
    oldShape = data.shape
    data.shape = 1,oldShape[0], oldShape[1]
    app = qt.QApplication([])
    w = StackSimpleFitWindow()
    w.setSpectrum(x, y)
    w.setData(x, data)
    #w.importFunctions(Functions.__file__)
    #w.fitModule.setFitFunction('Gaussians')
    w.show()
    app.exec_()
Ejemplo n.º 45
0
    def estimate_gauss(self,xx,yy,zzz,xscaling=1.0,yscaling=None):
       if yscaling == None:
            try:
                yscaling=self.config['Yscaling']
            except:
                yscaling=1.0
       if yscaling == 0:
            yscaling=1.0
       fittedpar=[]
       zz=SpecfitFuns.subac(yy,1.000,10000)

       npoints = len(zz)
       if self.config['AutoFwhm']:
            search_fwhm=self.guess_fwhm(x=xx,y=yy)
       else:
            search_fwhm=int(float(self.config['FwhmPoints']))
       search_sens=float(self.config['Sensitivity'])
       search_mca=int(float(self.config['McaMode']))

       if search_fwhm < 3:
            search_fwhm = 3
            self.config['FwhmPoints']=3

       if search_sens < 1:
            search_sens = 1
            self.config['Sensitivity']=1

       if npoints > 1.5*search_fwhm:
            peaks=self.seek(yy,fwhm=search_fwhm,
                               sensitivity=search_sens,
                               yscaling=yscaling,
                               mca=search_mca)
            #print "estimate peaks = ",peaks
            #peaks=self.seek(yy-zz,fwhm=search_fwhm,
            #                   sensitivity=search_sens,
            #                   yscaling=yscaling,
            #                   mca=search_mca)
       else:
            peaks = []
       if not len(peaks):
            mca = int(float(self.config.get('McaMode', 0)))
            forcePeak =  int(float(self.config.get('ForcePeakPresence', 0)))
            if (not mca) and forcePeak:
                delta = yy - zz
                peaks  = [int(numpy.nonzero(delta == delta.max())[0])]

       #print "peaks = ",peaks
       #print "peaks subac = ",self.seek(yy-zz,fwhm=search_fwhm,
       #                        sensitivity=search_sens,
       #                        yscaling=yscaling,
       #                        mca=search_mca)
       largest_index = 0
       if len(peaks) > 0:
            j = 0
            for i in peaks:
                if j == 0:
                    sig=5*abs(xx[npoints-1]-xx[0])/npoints
                    peakpos = xx[int(i)]
                    if abs(peakpos) < 1.0e-16:
                        peakpos = 0.0
                    param = numpy.array([yy[int(i)] - zz[int(i)], peakpos ,sig])
                    largest = param
                else:
                    param2 = numpy.array([yy[int(i)] - zz [int(i)], xx[int(i)] ,sig])
                    param = numpy.concatenate((param,param2))
                    if (param2[0] > largest[0]):
                        largest = param2
                        largest_index = j
                j = j + 1
            xw = numpy.resize(xx,(npoints,1))
            if (0):
                sy = numpy.sqrt(abs(yy))
                yw = numpy.resize(yy-zz,(npoints,1))
                sy = numpy.resize(sy,(npoints,1))
                datawork = numpy.concatenate((xw,yw,sy),1)
            else:
                yw = numpy.resize(yy-zz,(npoints,1))
                datawork = numpy.concatenate((xw,yw),1)
            cons = numpy.zeros((3,len(param)),numpy.float)
            cons [0] [0:len(param):3] = CPOSITIVE
            #force peaks to stay around their position
            if (1):
                cons [0] [1:len(param):3] = CQUOTED
                #This does not work!!!!
                #FWHM should be given in terms of X not of points!
                #cons [1] [1:len(param):3] = param[1:len(param):3]-0.5*search_fwhm
                #cons [2] [1:len(param):3] = param[1:len(param):3]+0.5*search_fwhm
                if len(xw) > search_fwhm:
                    fwhmx = numpy.fabs(xw[int(search_fwhm)]-xw[0])
                    cons [1] [1:len(param):3] = param[1:len(param):3]-0.5*fwhmx
                    cons [2] [1:len(param):3] = param[1:len(param):3]+0.5*fwhmx
                else:
                    cons [1] [1:len(param):3] = numpy.ones(shape(param[1:len(param):3]),numpy.float)*min(xw)
                    cons [2] [1:len(param):3] = numpy.ones(shape(param[1:len(param):3]),numpy.float)*max(xw)

            if 0:
                cons [0] [2:len(param):3] = CFACTOR
                cons [1] [2:len(param):3] = 2
                cons [2] [2:len(param):3] = 1.0
                cons [0] [2] = CPOSITIVE
                cons [1] [2] = 0
                cons [2] [2] = 0
            else:
                cons [0] [2:len(param):3] = CPOSITIVE
            fittedpar, chisq, sigmapar = LeastSquaresFit(SpecfitFuns.gauss,param,
                                            datawork,
                                            weightflag=self.config['WeightFlag'],
                                            maxiter=4,constrains=cons.tolist())
            #I already have the estimation
            #yw=yy-zz-SpecfitFuns.gauss(fittedpar,xx)
            #if DEBUG:
            #    SimplePlot.plot([xx,yw])
            #print self.seek(yw,\
            #                   fwhm=search_fwhm,\
            #                   sensitivity=search_sens,\
            #                   yscaling=yscaling)
       #else:
       #     #Use SPEC estimate ...
       #     peakpos,height,myidx = SpecArithmetic.search_peak(xx,yy-zz)
       #     fwhm,cfwhm         = SpecArithmetic.search_fwhm(xx,yy-zz,
       #                                    peak=peakpos,index=myidx)
       #     xx = numpy.array(xx)
       #     if npoints > 2:
       #         #forget SPEC estimation of fwhm
       #         fwhm=5*abs(xx[npoints-1]-xx[0])/npoints
       #     fittedpar=[height,peakpos,fwhm]
       #     largest=numpy.array([height,peakpos,fwhm])
       #     peaks=[peakpos]
       cons = numpy.zeros((3,len(fittedpar)),numpy.float)
       j=0
       for i in range(len(peaks)):
                #Setup height area constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['HeightAreaFlag']:
                        #POSITIVE = 1
                        cons[0] [j] = 1
                        cons[1] [j] = 0
                        cons[2] [j] = 0
                j=j+1


                #Setup position constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['PositionFlag']:
                                #QUOTED = 2
                                cons[0][j]=2
                                cons[1][j]=min(xx)
                                cons[2][j]=max(xx)
                j=j+1

                #Setup positive FWHM constrains
                if self.config['NoConstrainsFlag'] == 0:
                    if self.config['PosFwhmFlag']:
                                #POSITIVE=1
                                cons[0][j]=1
                                cons[1][j]=0
                                cons[2][j]=0
                    if self.config['SameFwhmFlag']:
                        if (i != largest_index):
                                #FACTOR=4
                                cons[0][j]=4
                                cons[1][j]=3*largest_index+2
                                cons[2][j]=1.0
                j=j+1
       return fittedpar,cons
Ejemplo n.º 46
0
 def splitlorentz(self,pars,x):
    """
    Asymmetric lorentz.
    """
    return SpecfitFuns.splitlorentz(pars,x)
Ejemplo n.º 47
0
    def fitMultipleSpectra(self, x=None, y=None, xmin=None, xmax=None,
                           configuration=None, concentrations=False,
                           ysum=None, weight=None, refit=True,
                           livetime=None):
        """
        This method performs the actual fit. The y keyword is the only mandatory input argument.

        :param x: 1D array containing the x axis (usually the channels) of the spectra.
        :param y: 3D array containing the spectra as [nrows, ncolumns, nchannels]
        :param xmin: lower limit of the fitting region
        :param xmax: upper limit of the fitting region
        :param weight: 0 Means no weight, 1 Use an average weight, 2 Individual weights (slow)
        :param concentrations: 0 Means no calculation, 1 Calculate them
        :param refit: if False, no check for negative results. Default is True.
        :livetime: It will be used if not different from None and concentrations
                   are to be calculated by using fundamental parameters with
                   automatic time. The default is None.
        :return: A dictionnary with the parameters, uncertainties, concentrations and names as keys.
        """
        if y is None:
            raise RuntimeError("y keyword argument is mandatory!")

        if hasattr(y, "info") and hasattr(y, "data"):
            data = y.data
            mcaIndex = y.info.get("McaIndex", -1)
        else:
            data = y
            mcaIndex = -1

        if x is None:
            if hasattr(y, "info") and hasattr(y, "x"):
                x = y.x[0]

        if livetime is None:
            if hasattr(y, "info"):
                if "McaLiveTime" in y.info:
                    livetime = y.info["McaLiveTime"]
        t0 = time.time()
        if configuration is not None:
            self._mcaTheory.setConfiguration(configuration)
        elif self._config is None:
            raise ValueError("Fit configuration missing")
        else:
            _logger.debug("Setting default configuration")
            self._mcaTheory.setConfiguration(self._config)
        # read the current configuration
        # it is a copy, we can modify it at will
        config = self._mcaTheory.getConfiguration()
        if xmin is None:
            xmin = config['fit']['xmin']
        if xmax is None:
            xmax = config['fit']['xmax']
        toReconfigure = False

        # if concentrations and use times, it needs to be reconfigured
        # without using times and correct later on. If the concentrations
        # are to be calculated from internal standard there is no need to
        # raise an exception either.
        autotime = 0
        liveTimeFactor = 1.0
        if not concentrations:
            # ignore any time information to prevent unnecessary errors when
            # setting the fitting data whithout the time information
            if config['concentrations'].get("useautotime", 0):
                config['concentrations']["useautotime"] = 0
                toReconfigure = True
        elif config["concentrations"]["usematrix"]:
            if config['concentrations'].get("useautotime", 0):
                config['concentrations']["useautotime"] = 0
                toReconfigure = True
        else:
            # we are calculating concentrations from fundamental parameters
            autotime = config['concentrations'].get("useautotime", 0)
            nSpectra = data.size // data.shape[mcaIndex]
            if autotime:
                if livetime is None:
                    txt = "Automatic time requested but no time information provided"
                    raise RuntimeError(txt)
                elif numpy.isscalar(livetime):
                    liveTimeFactor = \
                        float(config['concentrations']["time"]) / livetime
                elif livetime.size == nSpectra:
                    liveTimeFactor = \
                        float(config['concentrations']["time"]) / livetime
                else:
                    raise RuntimeError( \
                        "Number of live times not equal number of spectra")
                config['concentrations']["useautotime"] = 0
                toReconfigure = True

        # use of strategies is not supported for the time being
        strategy = config['fit'].get('strategyflag', 0)
        if strategy:
            raise RuntimeError("Strategies are incompatible with fast fit")

        # background
        if config['fit']['stripflag']:
            if config['fit']['stripalgorithm'] == 1:
                _logger.debug("SNIP")
            else:
                raise RuntimeError("Please use the faster SNIP background")

        if weight is None:
            # dictated by the file
            weight = config['fit']['fitweight']
            if weight:
                # individual pixel weights (slow)
                weightPolicy = 2
            else:
                # No weight
                weightPolicy = 0
        elif weight == 1:
            # use average weight from the sum spectrum
            weightPolicy = 1
            if not config['fit']['fitweight']:
                 config['fit']['fitweight'] = 1
                 toReconfigure = True
        elif weight == 2:
           # individual pixel weights (slow)
            weightPolicy = 2
            if not config['fit']['fitweight']:
                 config['fit']['fitweight'] = 1
                 toReconfigure = True
            weight = 1
        else:
            # No weight
            weightPolicy = 0
            if config['fit']['fitweight']:
                 config['fit']['fitweight'] = 0
                 toReconfigure = True
            weight = 0

        if not config['fit']['linearfitflag']:
            #make sure we force a linear fit
            config['fit']['linearfitflag'] = 1
            toReconfigure = True

        if toReconfigure:
            # we must configure again the fit
            self._mcaTheory.setConfiguration(config)

        if len(data.shape) != 3:
            txt = "For the time being only three dimensional arrays supported"
            raise IndexError(txt)
        elif mcaIndex not in [-1, 2]:
            txt = "For the time being only mca arrays supported"
            raise IndexError(txt)
        else:
            # if the cumulated spectrum is present it should be better
            nRows = data.shape[0]
            nColumns = data.shape[1]
            nPixels =  nRows * nColumns
            if ysum is not None:
                firstSpectrum = ysum
            elif weightPolicy == 1:
                # we need to calculate the sum spectrum to derive the uncertainties
                totalSpectra = data.shape[0] * data.shape[1]
                jStep = min(5000, data.shape[1])
                ysum = numpy.zeros((data.shape[mcaIndex],), numpy.float)
                for i in range(0, data.shape[0]):
                    if i == 0:
                        chunk = numpy.zeros((data.shape[0], jStep), numpy.float)
                    jStart = 0
                    while jStart < data.shape[1]:
                        jEnd = min(jStart + jStep, data.shape[1])
                        ysum += data[i, jStart:jEnd, :].sum(axis=0, dtype=numpy.float)
                        jStart = jEnd
                firstSpectrum = ysum
            elif not concentrations:
                # just one spectrum is enough for the setup
                firstSpectrum = data[0, 0, :]
            else:
                firstSpectrum = data[0, :, :].sum(axis=0, dtype=numpy.float)

        # make sure we calculate the matrix of the contributions
        self._mcaTheory.enableOptimizedLinearFit()

        # initialize the fit
        # print("xmin = ", xmin)
        # print("xmax = ", xmax)
        # print("firstShape = ", firstSpectrum.shape)
        self._mcaTheory.setData(x=x, y=firstSpectrum, xmin=xmin, xmax=xmax)

        # and initialize the derivatives
        self._mcaTheory.estimate()

        # now we can get the derivatives respect to the free parameters
        # These are the "derivatives" respect to the peaks
        # linearMatrix = self._mcaTheory.linearMatrix

        # but we are still missing the derivatives from the background
        nFree = 0
        freeNames = []
        nFreeBackgroundParameters = 0
        for i, param in enumerate(self._mcaTheory.PARAMETERS):
            if self._mcaTheory.codes[0][i] != ClassMcaTheory.Gefit.CFIXED:
                nFree += 1
                freeNames.append(param)
                if i < self._mcaTheory.NGLOBAL:
                    nFreeBackgroundParameters += 1
        if nFree == 0:
            txt = "No free parameters to be fitted!\n"
            txt += "No peaks inside fitting region?"
            raise ValueError(txt)

        #build the matrix of derivatives
        derivatives = None
        idx = 0
        for i, param in enumerate(self._mcaTheory.PARAMETERS):
            if self._mcaTheory.codes[0][i] == ClassMcaTheory.Gefit.CFIXED:
                continue
            deriv= self._mcaTheory.linearMcaTheoryDerivative(self._mcaTheory.parameters,
                                                             i,
                                                             self._mcaTheory.xdata)
            deriv.shape = -1
            if derivatives is None:
                derivatives = numpy.zeros((deriv.shape[0], nFree), numpy.float)
            derivatives[:, idx] = deriv
            idx += 1


        #loop for anchors
        xdata = self._mcaTheory.xdata

        if config['fit']['stripflag']:
            anchorslist = []
            if config['fit']['stripanchorsflag']:
                if config['fit']['stripanchorslist'] is not None:
                    ravelled = numpy.ravel(xdata)
                    for channel in config['fit']['stripanchorslist']:
                        if channel <= ravelled[0]:continue
                        index = numpy.nonzero(ravelled >= channel)[0]
                        if len(index):
                            index = min(index)
                            if index > 0:
                                anchorslist.append(index)
            if len(anchorslist) == 0:
                anchorlist = [0, self._mcaTheory.ydata.size - 1]
            anchorslist.sort()

        # find the indices to be used for selecting the appropriate data
        # if the original x data were not ordered we have a problem
        # TODO: check for original ordering.
        if x is None:
            # we have an enumerated channels axis
            iXMin = xdata[0]
            iXMax = xdata[-1]
        else:
            iXMin = numpy.nonzero(x <= xdata[0])[0][-1]
            iXMax = numpy.nonzero(x >= xdata[-1])[0][0]
        # numpy 1.11.0 returns an array on previous expression
        # and then complains about a future deprecation warning
        # because of using an array and not an scalar in the selection
        if hasattr(iXMin, "shape"):
            if len(iXMin.shape):
                iXMin = iXMin[0]
        if hasattr(iXMax, "shape"):
            if len(iXMax.shape):
                iXMax = iXMax[0]

        dummySpectrum = firstSpectrum[iXMin:iXMax+1].reshape(-1, 1)
        # print("dummy = ", dummySpectrum.shape)

        # allocate the output buffer
        results = numpy.zeros((nFree, nRows, nColumns), numpy.float32)
        uncertainties = numpy.zeros((nFree, nRows, nColumns), numpy.float32)

        #perform the initial fit
        _logger.debug("Configuration elapsed = %f", time.time() - t0)
        t0 = time.time()
        totalSpectra = data.shape[0] * data.shape[1]
        jStep = min(100, data.shape[1])
        if weightPolicy == 2:
            SVD = False
            sigma_b = None
        elif weightPolicy == 1:
            # the +1 is to prevent misbehavior due to weights less than 1.0
            sigma_b = 1 + numpy.sqrt(dummySpectrum)/nPixels
            SVD = True
        else:
            SVD = True
            sigma_b = None
        last_svd = None
        for i in range(0, data.shape[0]):
            #print(i)
            #chunks of nColumns spectra
            if i == 0:
                chunk = numpy.zeros((dummySpectrum.shape[0],
                                     jStep),
                                     numpy.float)
            jStart = 0
            while jStart < data.shape[1]:
                jEnd = min(jStart + jStep, data.shape[1])
                chunk[:,:(jEnd - jStart)] = data[i, jStart:jEnd, iXMin:iXMax+1].T
                if config['fit']['stripflag']:
                    for k in range(jStep):
                        # obtain the smoothed spectrum
                        background=SpecfitFuns.SavitskyGolay(chunk[:, k],
                                                config['fit']['stripfilterwidth'])
                        lastAnchor = 0
                        for anchor in anchorslist:
                            if (anchor > lastAnchor) and (anchor < background.size):
                                background[lastAnchor:anchor] =\
                                        SpecfitFuns.snip1d(background[lastAnchor:anchor],
                                                           config['fit']['snipwidth'],
                                                           0)
                                lastAnchor = anchor
                        if lastAnchor < background.size:
                            background[lastAnchor:] =\
                                    SpecfitFuns.snip1d(background[lastAnchor:],
                                                       config['fit']['snipwidth'],
                                                       0)
                        chunk[:, k] -= background

                # perform the multiple fit to all the spectra in the chunk
                #print("SHAPES")
                #print(derivatives.shape)
                #print(chunk[:,:(jEnd - jStart)].shape)
                ddict=lstsq(derivatives, chunk[:,:(jEnd - jStart)],
                            sigma_b=sigma_b,
                            weight=weight,
                            digested_output=True,
                            svd=SVD,
                            last_svd=last_svd)
                last_svd = ddict.get('svd', None)
                parameters = ddict['parameters']
                results[:, i, jStart:jEnd] = parameters
                uncertainties[:, i, jStart:jEnd] = ddict['uncertainties']
                jStart = jEnd
        t = time.time() - t0
        _logger.debug("First fit elapsed = %f", t)
        if t > 0.:
            _logger.debug("Spectra per second = %f",
                          data.shape[0]*data.shape[1]/float(t))
        t0 = time.time()

        # cleanup zeros
        # start with the parameter with the largest amount of negative values
        if refit:
            negativePresent = True
        else:
            negativePresent = False
        nFits = 0
        while negativePresent:
            zeroList = []
            #totalNegative = 0
            for i in range(nFree):
                #we have to skip the background parameters
                if i >= nFreeBackgroundParameters:
                    t = results[i] < 0
                    tsum = t.sum()
                    if tsum > 0:
                        zeroList.append((tsum, i, t))
                    #totalNegative += tsum
            #print("totalNegative = ", totalNegative)

            if len(zeroList) == 0:
                negativePresent = False
                continue

            if nFits > (2 * (nFree - nFreeBackgroundParameters)):
                # we are probably in an endless loop
                # force negative pixels
                for item in zeroList:
                    i = item[1]
                    badMask = item[2]
                    results[i][badMask] = 0.0
                    _logger.warning("WARNING: %d pixels of parameter %s forced to zero",
                                    item[0], freeNames[i])
                continue
            zeroList.sort()
            zeroList.reverse()

            badParameters = []
            badParameters.append(zeroList[0][1])
            badMask = zeroList[0][2]
            if 1:
                # prevent and endless loop if two or more parameters have common pixels where they are
                # negative and one of them remains negative when forcing other one to zero
                for i, item in enumerate(zeroList):
                    if item[1] not in badParameters:
                        if item[0] > 0:
                            #check if they have common negative pixels
                            t = badMask * item[-1]
                            if t.sum() > 0:
                                badParameters.append(item[1])
                                badMask = t
            if badMask.sum() < (0.0025 * nPixels):
                # fit not worth
                for i in badParameters:
                    results[i][badMask] = 0.0
                    uncertainties[i][badMask] = 0.0
                    _logger.debug("WARNING: %d pixels of parameter %s set to zero",
                                  badMask.sum(), freeNames[i])
            else:
                _logger.debug("Number of secondary fits = %d", nFits + 1)
                nFits += 1
                A = derivatives[:, [i for i in range(nFree) if i not in badParameters]]
                #assume we'll not have too many spectra
                if data.dtype not in [numpy.float32, numpy.float64]:
                    if data.itemsize < 5:
                        data_dtype = numpy.float32
                    else:
                        data_dtype = numpy.floa64
                else:
                    data_dtype = data.dtype
                try:
                    if data.dtype != data_dtype:
                        spectra = numpy.zeros((int(badMask.sum()), 1 + iXMax - iXMin),
                                          data_dtype)
                        spectra[:] = data[badMask, iXMin:iXMax+1]
                    else:
                        spectra = data[badMask, iXMin:iXMax+1]
                    spectra.shape = badMask.sum(), -1
                except TypeError:
                    # in case of dynamic arrays, two dimensional indices are not
                    # supported by h5py
                    spectra = numpy.zeros((int(badMask.sum()), 1 + iXMax - iXMin),
                                          data_dtype)
                    selectedIndices = numpy.nonzero(badMask > 0)
                    tmpData = numpy.zeros((1, 1 + iXMax - iXMin), data_dtype)
                    oldDataRow = -1
                    j = 0
                    for i in range(len(selectedIndices[0])):
                        j = selectedIndices[0][i]
                        if j != oldDataRow:
                            tmpData = data[j]
                            olddataRow = j
                        spectra[i] = tmpData[selectedIndices[1][i], iXMin:iXMax+1]
                spectra = spectra.T
                #
                if config['fit']['stripflag']:
                    for k in range(spectra.shape[1]):
                        # obtain the smoothed spectrum
                        background=SpecfitFuns.SavitskyGolay(spectra[:, k],
                                                config['fit']['stripfilterwidth'])
                        lastAnchor = 0
                        for anchor in anchorslist:
                            if (anchor > lastAnchor) and (anchor < background.size):
                                background[lastAnchor:anchor] =\
                                        SpecfitFuns.snip1d(background[lastAnchor:anchor],
                                                           config['fit']['snipwidth'],
                                                           0)
                                lastAnchor = anchor
                        if lastAnchor < background.size:
                            background[lastAnchor:] =\
                                    SpecfitFuns.snip1d(background[lastAnchor:],
                                                       config['fit']['snipwidth'],
                                                       0)
                        spectra[:, k] -= background
                ddict = lstsq(A, spectra,
                              sigma_b=sigma_b,
                              weight=weight,
                              digested_output=True,
                              svd=SVD)
                idx = 0
                for i in range(nFree):
                    if i in badParameters:
                        results[i][badMask] = 0.0
                        uncertainties[i][badMask] = 0.0
                    else:
                        results[i][badMask] = ddict['parameters'][idx]
                        uncertainties[i][badMask] = ddict['uncertainties'][idx]
                        idx += 1

        if refit:
            t = time.time() - t0
            _logger.debug("Fit of negative peaks elapsed = %f", t)
            t0 = time.time()

        outputDict = {'parameters':results, 'uncertainties':uncertainties, 'names':freeNames}

        if concentrations:
            # check if an internal reference is used and if it is set to auto
            ####################################################
            # CONCENTRATIONS
            cTool = ConcentrationsTool.ConcentrationsTool()
            cToolConf = cTool.configure()
            cToolConf.update(config['concentrations'])

            fitFirstSpectrum = False
            if config['concentrations']['usematrix']:
                _logger.debug("USING MATRIX")
                if config['concentrations']['reference'].upper() == "AUTO":
                    fitFirstSpectrum = True
            elif autotime:
                # we have to calculate with the time in the configuration
                # and correct later on
                cToolConf["autotime"] = 0

            fitresult = {}
            if fitFirstSpectrum:
                # we have to fit the "reference" spectrum just to get the reference element
                mcafitresult = self._mcaTheory.startfit(digest=0, linear=True)
                # if one of the elements has zero area this cannot be made directly
                fitresult['result'] = self._mcaTheory.imagingDigestResult()
                fitresult['result']['config'] = config
                concentrationsResult, addInfo = cTool.processFitResult(config=cToolConf,
                                                    fitresult=fitresult,
                                                    elementsfrommatrix=False,
                                                    fluorates=self._mcaTheory._fluoRates,
                                                    addinfo=True)
                # and we have to make sure that all the areas are positive
                for group in fitresult['result']['groups']:
                    if fitresult['result'][group]['fitarea'] <= 0.0:
                        # give a tiny area
                        fitresult['result'][group]['fitarea'] = 1.0e-6
                config['concentrations']['reference'] = addInfo['ReferenceElement']
            else:
                fitresult['result'] = {}
                fitresult['result']['config'] = config
                fitresult['result']['groups'] = []
                idx = 0
                for i, param in enumerate(self._mcaTheory.PARAMETERS):
                    if self._mcaTheory.codes[0][i] == Gefit.CFIXED:
                        continue
                    if i < self._mcaTheory.NGLOBAL:
                        # background
                        pass
                    else:
                        fitresult['result']['groups'].append(param)
                        fitresult['result'][param] = {}
                        # we are just interested on the factor to be applied to the area to get the
                        # concentrations
                        fitresult['result'][param]['fitarea'] = 1.0
                        fitresult['result'][param]['sigmaarea'] = 1.0
                    idx += 1
            concentrationsResult, addInfo = cTool.processFitResult(config=cToolConf,
                                                    fitresult=fitresult,
                                                    elementsfrommatrix=False,
                                                    fluorates=self._mcaTheory._fluoRates,
                                                    addinfo=True)
            nValues = 1
            if len(concentrationsResult['layerlist']) > 1:
                nValues += len(concentrationsResult['layerlist'])
            nElements = len(list(concentrationsResult['mass fraction'].keys()))
            massFractions = numpy.zeros((nValues * nElements, nRows, nColumns),
                                        numpy.float32)


            referenceElement = addInfo['ReferenceElement']
            referenceTransitions = addInfo['ReferenceTransitions']
            _logger.debug("Reference <%s>  transition <%s>",
                          referenceElement, referenceTransitions)
            if referenceElement in ["", None, "None"]:
                _logger.debug("No reference")
                counter = 0
                for i, group in enumerate(fitresult['result']['groups']):
                    if group.lower().startswith("scatter"):
                        _logger.debug("skept %s", group)
                        continue
                    outputDict['names'].append("C(%s)" % group)
                    if counter == 0:
                        if hasattr(liveTimeFactor, "shape"):
                            liveTimeFactor.shape = results[nFreeBackgroundParameters+i].shape
                    massFractions[counter] = liveTimeFactor * \
                        results[nFreeBackgroundParameters+i] * \
                        (concentrationsResult['mass fraction'][group] / \
                         fitresult['result'][group]['fitarea'])
                    counter += 1
                    if len(concentrationsResult['layerlist']) > 1:
                        for layer in concentrationsResult['layerlist']:
                            outputDict['names'].append("C(%s)-%s" % (group, layer))
                            massFractions[counter] = liveTimeFactor * \
                                    results[nFreeBackgroundParameters+i] * \
                                    (concentrationsResult[layer]['mass fraction'][group] / \
                                     fitresult['result'][group]['fitarea'])
                            counter += 1
            else:
                _logger.debug("With reference")
                idx = None
                testGroup = referenceElement+ " " + referenceTransitions.split()[0]
                for i, group in enumerate(fitresult['result']['groups']):
                    if group == testGroup:
                        idx = i
                if idx is None:
                    raise ValueError("Invalid reference:  <%s> <%s>" %\
                                     (referenceElement, referenceTransitions))

                group = fitresult['result']['groups'][idx]
                referenceArea = fitresult['result'][group]['fitarea']
                referenceConcentrations = concentrationsResult['mass fraction'][group]
                goodIdx = results[nFreeBackgroundParameters+idx] > 0
                massFractions[idx] = referenceConcentrations
                counter = 0
                for i, group in enumerate(fitresult['result']['groups']):
                    if group.lower().startswith("scatter"):
                        _logger.debug("skept %s", group)
                        continue
                    outputDict['names'].append("C(%s)" % group)
                    goodI = results[nFreeBackgroundParameters+i] > 0
                    tmp = results[nFreeBackgroundParameters+idx][goodI]
                    massFractions[counter][goodI] = (results[nFreeBackgroundParameters+i][goodI]/(tmp + (tmp == 0))) *\
                                ((referenceArea/fitresult['result'][group]['fitarea']) *\
                                (concentrationsResult['mass fraction'][group]))
                    counter += 1
                    if len(concentrationsResult['layerlist']) > 1:
                        for layer in concentrationsResult['layerlist']:
                            outputDict['names'].append("C(%s)-%s" % (group, layer))
                            massFractions[counter][goodI] = (results[nFreeBackgroundParameters+i][goodI]/(tmp + (tmp == 0))) *\
                                ((referenceArea/fitresult['result'][group]['fitarea']) *\
                                (concentrationsResult[layer]['mass fraction'][group]))
                            counter += 1
            outputDict['concentrations'] = massFractions
            t = time.time() - t0
            _logger.debug("Calculation of concentrations elapsed = %f", t)
            ####################################################
        return outputDict
Ejemplo n.º 48
0
def _getROILineProfileCurve(image, roiStart, roiEnd, roiWidth,
                            lineProjectionMode):
    """Returns the profile values and the polygon in the given ROI.

    Works in image coordinates.

    See :func:`getAlignedROIProfileCurve`.
    """
    row0, col0 = roiStart
    row1, col1 = roiEnd

    deltaRow = abs(row1 - row0)
    deltaCol = abs(col1 - col0)

    if (lineProjectionMode == 'X'
            or (lineProjectionMode == 'D' and deltaCol >= deltaRow)):
        nPoints = deltaCol + 1
        coordsRange = col0, col1
    else:  # 'Y' or ('D' and deltaCol < deltaRow)
        nPoints = deltaRow + 1
        coordsRange = row0, row1

    if nPoints == 1:  # all points are the same
        if DEBUG:
            print("START AND END POINT ARE THE SAME!!")
        return None

    # the coordinates of the reference points
    x0 = numpy.arange(image.shape[0], dtype=numpy.float)
    y0 = numpy.arange(image.shape[1], dtype=numpy.float)

    if roiWidth < 1:
        x = numpy.zeros((nPoints, 2), numpy.float)
        x[:, 0] = numpy.linspace(row0, row1, nPoints)
        x[:, 1] = numpy.linspace(col0, col1, nPoints)
        # perform the interpolation
        ydata = SpecfitFuns.interpol((x0, y0), image, x)

        roiPolygonCols = numpy.array((col0, col1), dtype=numpy.float)
        roiPolygonRows = numpy.array((row0, row1), dtype=numpy.float)

    else:
        # find m and b in the line y = mx + b
        m = (row1 - row0) / float((col1 - col0))
        # Not used: b = row0 - m * col0
        alpha = numpy.arctan(m)
        # imagine the following sequence
        # - change origin to the first point
        # - clock-wise rotation to bring the line on the x axis of a new system
        #   so that the points (col0, row0) and (col1, row1)
        #   become (x0, 0) (x1, 0).
        # - counter clock-wise rotation to get the points (x0, -0.5 width),
        #   (x0, 0.5 width), (x1, 0.5 * width) and (x1, -0.5 * width) back to
        #   the original system.
        # - restore the origin to (0, 0)
        # - if those extremes are inside the image the selection is acceptable
        cosalpha = numpy.cos(alpha)
        sinalpha = numpy.sin(alpha)
        newCol0 = 0.0
        newCol1 = (col1 - col0) * cosalpha + (row1 - row0) * sinalpha
        newRow0 = 0.0
        newRow1 = -(col1 - col0) * sinalpha + (row1 - row0) * cosalpha

        if DEBUG:
            print("new X0 Y0 = %f, %f  " % (newCol0, newRow0))
            print("new X1 Y1 = %f, %f  " % (newCol1, newRow1))

        tmpX = numpy.linspace(newCol0, newCol1, nPoints).astype(numpy.float)
        rotMatrix = numpy.zeros((2, 2), dtype=numpy.float)
        rotMatrix[0, 0] = cosalpha
        rotMatrix[0, 1] = -sinalpha
        rotMatrix[1, 0] = sinalpha
        rotMatrix[1, 1] = cosalpha
        if DEBUG:
            # test if I recover the original points
            testX = numpy.zeros((2, 1), numpy.float)
            colRow = numpy.dot(rotMatrix, testX)
            print("Recovered X0 = %f" % (colRow[0, 0] + col0))
            print("Recovered Y0 = %f" % (colRow[1, 0] + row0))
            print("It should be = %f, %f" % (col0, row0))
            testX[0, 0] = newCol1
            testX[1, 0] = newRow1
            colRow = numpy.dot(rotMatrix, testX)
            print("Recovered X1 = %f" % (colRow[0, 0] + col0))
            print("Recovered Y1 = %f" % (colRow[1, 0] + row0))
            print("It should be = %f, %f" % (col1, row1))

        # find the drawing limits
        testX = numpy.zeros((2, 4), numpy.float)
        testX[0, 0] = newCol0
        testX[0, 1] = newCol0
        testX[0, 2] = newCol1
        testX[0, 3] = newCol1
        testX[1, 0] = newRow0 - 0.5 * roiWidth
        testX[1, 1] = newRow0 + 0.5 * roiWidth
        testX[1, 2] = newRow1 + 0.5 * roiWidth
        testX[1, 3] = newRow1 - 0.5 * roiWidth
        colRow = numpy.dot(rotMatrix, testX)
        colLimits0 = colRow[0, :] + col0
        rowLimits0 = colRow[1, :] + row0

        for a in rowLimits0:
            if (a >= image.shape[0]) or (a < 0):
                if DEBUG:
                    print("outside row limits", a)
                return None
        for a in colLimits0:
            if (a >= image.shape[1]) or (a < 0):
                if DEBUG:
                    print("outside column limits", a)
                return None

        r0 = rowLimits0[0]
        r1 = rowLimits0[1]

        if r0 > r1:
            if DEBUG:
                print("r0 > r1", r0, r1)
            raise ValueError("r0 > r1")

        x = numpy.zeros((2, nPoints), numpy.float)

        # oversampling solves noise introduction issues
        oversampling = roiWidth + 1
        oversampling = min(oversampling, 21)
        ncontributors = roiWidth * oversampling
        iterValues = numpy.linspace(-0.5 * roiWidth, 0.5 * roiWidth,
                                    ncontributors)
        tmpMatrix = numpy.zeros((nPoints * len(iterValues), 2),
                                dtype=numpy.float)
        x[0, :] = tmpX
        offset = 0
        for i in iterValues:
            x[1, :] = i
            colRow = numpy.dot(rotMatrix, x)
            colRow[0, :] += col0
            colRow[1, :] += row0
            # it is much faster to make one call to the interpolating
            # routine than making many calls
            tmpMatrix[offset:(offset + nPoints), 0] = colRow[1, :]
            tmpMatrix[offset:(offset + nPoints), 1] = colRow[0, :]
            offset += nPoints
        ydata = SpecfitFuns.interpol((x0, y0), image, tmpMatrix)
        ydata.shape = len(iterValues), nPoints
        ydata = ydata.sum(axis=0)
        # deal with the oversampling
        ydata /= oversampling

        roiPolygonCols, roiPolygonRows = colLimits0, rowLimits0

    return {
        'profileValues': ydata,
        'profileCoordsRange': coordsRange,
        'roiPolygonCols': roiPolygonCols,
        'roiPolygonRows': roiPolygonRows
    }