Ejemplo n.º 1
0
 def test_input_exceptions(self):
   ''' Test exceptions thrown upon wrong input '''
   if not self.isthere_dsfinterp():
     return
   import dsfinterp
   nf = 9
   fvalues, InputWorkspaces, xvalues, HWHM = self.generateWorkspaces(nf, 0.01, 0.01) # workspaces sim0 to sim8 (nine workpaces)
   # Try passing different number of InputWorkspaces and parameter values
   try:
     fvalueswrong = ' '.join(fvalues.split()[:-1]) # one less value
     func_string = 'name=DSFinterp1DFit,InputWorkspaces="{0}",ParameterValues="{1}",'.format(InputWorkspaces,fvalueswrong) +\
     'LoadErrors=0,LocalRegression=1,RegressionType=quadratic,RegressionWindow=6,' +\
     'WorkspaceIndex=0,Intensity=1.0,TargetParameter=0.01;'
     Fit( Function=func_string, InputWorkspace= 'targetW', WorkspaceIndex=0, StartX=xvalues[0], EndX=xvalues[-1], CreateOutput=1, MaxIterations=0 )
   except Exception as e:
     self.assertTrue('Number of InputWorkspaces and ParameterValues should be the same' in str(e))
   else:
     assert False, 'Did not raise any exception'
   # Try passing the wrong workspace index
   try:
     func_string = 'name=DSFinterp1DFit,InputWorkspaces="{0}",ParameterValues="{1}",'.format(InputWorkspaces,fvalues) +\
     'LoadErrors=0,LocalRegression=1,RegressionType=quadratic,RegressionWindow=6,' +\
     'WorkspaceIndex=1,Intensity=1.0,TargetParameter=0.01;'
     Fit( Function=func_string, InputWorkspace= 'targetW', WorkspaceIndex=0, StartX=xvalues[0], EndX=xvalues[-1], CreateOutput=1, MaxIterations=0 )
   except Exception as e:
     self.assertTrue('Numer of histograms in Workspace sim0 does not allow for workspace index 1' in str(e))
   else:
     assert False, 'Did not raise any exception'
   #Try passing the wrong type of regression
   try:
     func_string = 'name=DSFinterp1DFit,InputWorkspaces="{0}",ParameterValues="{1}",'.format(InputWorkspaces,fvalues) +\
     'LoadErrors=0,LocalRegression=1,RegressionType=baloney,RegressionWindow=6,' +\
     'WorkspaceIndex=0,Intensity=1.0,TargetParameter=0.01;'
     Fit( Function=func_string, InputWorkspace= 'targetW', WorkspaceIndex=0, StartX=xvalues[0], EndX=xvalues[-1], CreateOutput=1, MaxIterations=0 )
   except Exception as e:
     self.assertTrue('Regression type baloney not implemented' in str(e))
   else:
     assert False, 'Did not raise any exception'
   # Try passing an inappropriate regression window for the regression type selected
   try:
     func_string = 'name=DSFinterp1DFit,InputWorkspaces="{0}",ParameterValues="{1}",'.format(InputWorkspaces,fvalues) +\
     'LoadErrors=0,LocalRegression=1,RegressionType=quadratic,RegressionWindow=3,' +\
     'WorkspaceIndex=0,Intensity=1.0,TargetParameter=0.01;'
     Fit( Function=func_string, InputWorkspace= 'targetW', WorkspaceIndex=0, StartX=xvalues[0], EndX=xvalues[-1], CreateOutput=1, MaxIterations=0 )
   except Exception as e:
     self.assertTrue('RegressionWindow must be equal or bigger than 4 for regression type quadratic' in str(e))
   else:
     assert False, 'Did not raise any exception'
   self.cleanup(nf)
Ejemplo n.º 2
0
 def test_function_returns_are_correct_type_when_output_ws_is_requested(self):
     if  platform.system() == 'Darwin': # crashes
         return
     output_name = "fitWS"
     retvals = Fit("name=FlatBackground", self._raw_ws, Output="fitWS")
     self._check_returns_are_correct_type_with_workspaces(retvals)
     self.assertTrue(output_name + '_Workspace' in mtd)
Ejemplo n.º 3
0
 def test_function_accepts_all_arguments_as_keywords(self):
     if  platform.system() == 'Darwin': # crashes
         return
     output_name = "kwargsfitWS"
     retvals = Fit(Function="name=FlatBackground", InputWorkspace=self._raw_ws, Output=output_name)
     self._check_returns_are_correct_type_with_workspaces(retvals)
     self.assertTrue(output_name + '_Workspace' in mtd)
Ejemplo n.º 4
0
 def test_function_returns_are_correct_type_when_no_output_ws_requested(self):
     if  platform.system() == 'Darwin': # crashes
         return
     retvals = Fit("name=FlatBackground", self._raw_ws)
     self.assertEquals(len(retvals), 2)
     self.assertTrue(isinstance(retvals[0], str))
     self.assertTrue(isinstance(retvals[1], float))
Ejemplo n.º 5
0
 def test_function_returns_are_correct_type_when_no_output_ws_requested(
         self):
     if platform.system() == 'Darwin':  # crashes
         return
     retvals = Fit("name=FlatBackground", self._raw_ws)
     self.assertTrue(isinstance(retvals.OutputStatus, str))
     self.assertTrue(isinstance(retvals.OutputChi2overDoF, float))
Ejemplo n.º 6
0
    def setUpClass(cls):
        delta = 0.33
        x = np.linspace(0., 15., 100)
        x_offset = np.linspace(delta / 2, 15. + delta / 2, 100)
        x_offset_neg = np.linspace(-delta / 2, 15. - delta / 2, 100)

        testFunction = GausOsc(Frequency=1.5, A=0.22)
        y1 = testFunction(x_offset_neg)
        y2 = testFunction(x_offset)
        y = y1 / 2 + y2 / 2
        ws = CreateWorkspace(x, y)

        convolution = FunctionFactory.createCompositeFunction('Convolution')
        innerFunction = FunctionFactory.createInitialized('name=GausOsc,A=0.2,Sigma=0.2,Frequency=1,Phi=0')
        deltaFunctions = FunctionFactory.createInitialized(
            '(name=DeltaFunction,Height=0.5,Centre={},ties=(Height=0.5,Centre={});name=DeltaFunction,Height=0.5,'
            'Centre={},ties=(Height=0.5,Centre={}))'.format(
                -delta / 2, -delta / 2, delta / 2, delta / 2))
        convolution.setAttributeValue('FixResolution', False)
        convolution.add(innerFunction)
        convolution.add(deltaFunctions)

        MultiDomainSingleFunction = FunctionFactory.createInitializedMultiDomainFunction(
            'name=GausOsc,A=0.2,Sigma=0.2,Frequency=1,Phi=0', 2)
        MultiDomainConvolutionFunction = FunctionFactory.createInitializedMultiDomainFunction(str(convolution), 2)

        DoublePulseFit(Function=MultiDomainSingleFunction, InputWorkspace=ws, InputWorkspace_1=ws, CreateOutput=True,
                       PulseOffset=delta, StartX=0.0, EndX=15.0, Output='DoublePulseFit', MaxIterations=1)
        Fit(Function=MultiDomainConvolutionFunction, InputWorkspace=ws, InputWorkspace_1=ws, CreateOutput=True,
            StartX=0.0, EndX=15.0, Output='Fit', MaxIterations=1)
Ejemplo n.º 7
0
    def do_fit_all(self, ws_list, do_sequential=True):
        fitprop_list = []
        prev_fitprop = self.view.read_fitprop_from_browser()
        for ws in ws_list:
            logger.notice(f'Starting to fit workspace {ws}')
            fitprop = deepcopy(prev_fitprop)
            # update I/O workspace name
            fitprop['properties']['Output'] = ws
            fitprop['properties']['InputWorkspace'] = ws
            # do fit
            fit_output = Fit(**fitprop['properties'])
            # update results
            fitprop['status'] = fit_output.OutputStatus
            funcstr = str(fit_output.Function.fun)
            fitprop['properties']['Function'] = funcstr
            if "success" in fitprop['status'].lower() and do_sequential:
                # update function in prev fitprop to use for next workspace
                prev_fitprop['properties']['Function'] = funcstr
            # update last fit in fit browser and save setup
            self.view.update_browser(fit_output.OutputStatus, funcstr, ws)
            # append a deep copy to output list (will be initial parameters if not successful)
            fitprop_list.append(fitprop)

        logger.notice('Sequential fitting finished.')
        self.fit_all_done_notifier.notify_subscribers(fitprop_list)
 def _findLine(self, ws):
     """Return a peak position workspace."""
     # TODO There should be a better algorithm in Mantid to achieve this.
     integratedWSName = self._names.withSuffix('integrated')
     integratedWS = Integration(InputWorkspace=ws,
                                OutputWorkspace=integratedWSName,
                                EnableLogging=self._subalgLogging)
     transposedWSName = self._names.withSuffix('transposed')
     transposedWS = Transpose(InputWorkspace=integratedWS,
                              OutputWorkspace=transposedWSName,
                              EnableLogging=self._subalgLogging)
     self._cleanup.cleanup(integratedWS)
     # Convert spectrum numbers to WS indices.
     wsIndices = numpy.arange(0, ws.getNumberHistograms())
     xs = transposedWS.dataX(0)
     ys = transposedWS.readY(0)
     numpy.copyto(xs, wsIndices)
     indexOfMax = ys.argmax()
     heightGuess = ys[indexOfMax]
     posGuess = xs[indexOfMax]
     sigmaGuess = 3
     f = 'name=Gaussian, PeakCentre={}, Height={}, Sigma={}'.format(
         posGuess, heightGuess, sigmaGuess)
     fitResult = Fit(Function=f,
                     InputWorkspace=transposedWS,
                     EnableLogging=self._subalgLogging)
     self._cleanup.cleanup(transposedWS)
     peakPos = fitResult.Function.PeakCentre
     posTable = self._createFakePeakPositionTable(peakPos)
     return posTable
Ejemplo n.º 9
0
    def refit_peaks(self, bad_params):
        xvals = self.getProperty('InputWorkspace').value.readX(0).copy()

        if not bad_params:
            return np.zeros(len(xvals)), None

        fit_func = ''
        fit_constr = ''
        for i, (centre, height, width) in enumerate(bad_params):
            fit_func += 'name=Gaussian,PeakCentre=%f,Height=%f,Sigma=%f;' % (
                centre, height, width)
            fit_constr += '%f<f%d.PeakCentre<%f,%f<f%d.Height<%f,%f<f%d.Sigma<%d,' \
                          % (centre * (1 - self._refit_tolerance), i, centre * (1 + self._refit_tolerance),
                             height * (1 - self._refit_tolerance), i, height * (1 + self._refit_tolerance),
                             self._min_sigma, i, self._max_sigma)

        if fit_constr.count('PeakCentre') == 1:
            fit_constr = fit_constr.replace('f0.', '')

        _, _, _, param, fit_result, _, _ = Fit(
            Function=fit_func,
            InputWorkspace=self.getProperty('InputWorkspace').value,
            Output='fit_result',
            Minimizer='Levenberg-MarquardtMD',
            OutputCompositeMembers=True,
            StartX=min(xvals),
            EndX=max(xvals),
            Constraints=fit_constr,
            StoreInADS=False)

        return fit_result.readY(1).copy(), param
Ejemplo n.º 10
0
 def test_LorentzianFit(self):
     ''' Fit a set or Lorentzians with "noisy" HWHM against a reference lorentzian '''
     if not self.isthere_dsfinterp():
         return
     import dsfinterp
     nf = 20
     startf = 0.01
     df = 0.01
     fvalues, InputWorkspaces, xvalues, HWHM = self.generateWorkspaces(
         nf, startf, df, e=True)
     # Do the fit starting from different initial guesses
     for iif in range(0, nf, 6):
         guess = startf + iif * df
         func_string = 'name=DSFinterp1DFit,InputWorkspaces="{0}",ParameterValues="{1}",'.format(InputWorkspaces,fvalues) +\
         'LoadErrors=0,LocalRegression=1,RegressionType=quadratic,RegressionWindow=6,' +\
         'WorkspaceIndex=0,Intensity=1.0,TargetParameter={0};'.format(guess)
         Fit(Function=func_string,
             InputWorkspace='targetW',
             WorkspaceIndex=0,
             StartX=xvalues[0],
             EndX=xvalues[-1],
             CreateOutput=1,
             MaxIterations=20)
         ws = mtd['targetW_Parameters']
         optimizedf = ws.row(1)['Value']
         self.assertTrue(
             abs(1.0 - optimizedf / HWHM) < 0.05)  #five percent error
     self.cleanup(nf)
Ejemplo n.º 11
0
    def test_multi_domain_fit(self):
        x = np.linspace(-10, 10)
        y1 = np.exp(-(x-2)**2)
        y2 = 2*np.exp(-x**2)
        y3 = 3*np.exp(-(x+2)**2)

        ws1 = CreateWorkspace(x, y1)
        ws2 = CreateWorkspace(x, y2)
        ws3 = CreateWorkspace(x, y3)

        mdf = MultiDomainFunction(Gaussian(), Gaussian(), Gaussian(), Global=["Sigma"])
        res = Fit(mdf, InputWorkspace=ws1, InputWorkspace_1=ws2, InputWorkspace_2=ws3)
        f = res.Function

        self.assertAlmostEqual(f[0].Sigma, 0.707107, 6)
        self.assertAlmostEqual(f[1].Sigma, 0.707107, 6)
        self.assertAlmostEqual(f[2].Sigma, 0.707107, 6)

        self.assertAlmostEqual(f[0].Height, 1, 6)
        self.assertAlmostEqual(f[1].Height, 2, 6)
        self.assertAlmostEqual(f[2].Height, 3, 6)

        self.assertAlmostEqual(f[0].PeakCentre, 2, 6)
        self.assertAlmostEqual(f[1].PeakCentre, 0, 6)
        self.assertAlmostEqual(f[2].PeakCentre, -2, 6)
Ejemplo n.º 12
0
def do_a_fit(x, function, guess, target, atol=0.01):
    r"""Carry out a fit and compare to target parameters

    Parameters
    ----------
    x : sequence of floats
        Domain values for evaluating the function .
    function : str
        Registered function name.
    guess : dict
        Parameter names with their initial values.
    target : dict
        Parameter names with the values to be obtained after the fit.
    atol : float
        Absolute tolerance parameter when evaluating expected_output against
        output values.
    """
    model = FunctionWrapper(function, **target)
    w = CreateWorkspace(x,
                        model(x) * np.random.uniform(0.95, 1.05, len(x)),
                        np.ones(len(x)),
                        Nspec=1)
    fit = Fit(FunctionWrapper(function, **guess), w)
    otarget = OrderedDict(target)
    np.allclose([fit.Function[p] for p in otarget.keys()],
                list(otarget.values()), atol)
Ejemplo n.º 13
0
 def test_other_arguments_are_accepted_by_keyword(self):
     if  platform.system() == 'Darwin': # crashes
         return
     output_name = "otherargs_fitWS"
     retvals = Fit("name=FlatBackground", self._raw_ws, MaxIterations=2, Output=output_name)
     self._check_returns_are_correct_type_with_workspaces(retvals)
     self.assertTrue(output_name + '_Workspace' in mtd)
Ejemplo n.º 14
0
    def test_Fit_works_with_multidomain_functions(self):
        x1 = np.arange(10)
        y1 = np.empty(0)
        y2 = np.empty(0)
        y3 = np.empty(0)

        for x in x1:
            y1 = np.append(y1, 3)
            y2 = np.append(y2, 2.9 + 3*x)
            y3 = np.append(y3, 3.1 + 3*x*x)

        x = np.concatenate((x1,x1,x1))
        y = np.concatenate((y1,y2,y3))

        data_name = 'dataWS'
        run_algorithm('CreateWorkspace',OutputWorkspace=data_name,DataX=x, DataY=y,DataE=np.ones(30),NSpec=3,UnitX='TOF')

        f1 = ';name=UserFunction,$domains=i,Formula=a+b*x+c*x^2'
        func= 'composite=MultiDomainFunction,NumDeriv=1' + f1 + f1 + f1 + ';ties=(f2.a=f1.a=f0.a)'

        output_name = "fitWS"
        Fit(Function=func,InputWorkspace=data_name,WorkspaceIndex=0,Output=output_name,
            InputWorkspace_1=data_name,WorkspaceIndex_1=1,InputWorkspace_2=data_name,WorkspaceIndex_2=2)

        self.assertTrue(output_name + '_Parameters' in mtd)
        params = mtd[output_name+'_Parameters']
        self.assertEqual(params.rowCount(), 10)

        self.assertAlmostEqual(params.row(0)['Value'], 3.0, 10)
        self.assertAlmostEqual(params.row(3)['Value'], 3.0, 10)
        self.assertAlmostEqual(params.row(6)['Value'], 3.0, 10)
        self.assertAlmostEqual(params.row(4)['Value'], 3.0, 1)
        self.assertAlmostEqual(params.row(8)['Value'], 3.0, 1)
Ejemplo n.º 15
0
    def do_fit_gaussian(self, index):
        """
        Performs gaussian fit of the specified spectrum
        returns fitStatus, chiSq, covarianceTable, paramTable
        """
        result = None

        x_values = np.array(self.workspace.readX(index))
        y_values = np.array(self.workspace.readY(index))

        # get peak centre position, assuming that it is the point with the highest value
        imax = np.argmax(y_values)
        height = y_values[imax]

        # check for zero or negative signal
        if height <= 0.:
            self.log().warning("Workspace %s, detector %d has maximum <= 0" %
                               (self.workspace.getName(), index))
            return result

        # guess sigma (assume the signal is sufficiently smooth)
        # the _only_ peak is at least three samples wide
        # selecting samples above .5 ("full width at half maximum")
        indices = np.argwhere(y_values > 0.5 * height)
        nentries = len(indices)

        if nentries < 3:
            self.log().warning(
                "Spectrum " + str(index) + " in workspace " +
                self.workspace.getName() +
                " has a too narrow peak. Cannot guess sigma. Check your data.")
            return result

        minIndex = indices[0, 0]
        maxIndex = indices[-1, 0]

        # full width at half maximum: fwhm = sigma * (2.*np.sqrt(2.*np.log(2.)))
        fwhm = np.fabs(x_values[maxIndex] - x_values[minIndex])
        sigma = fwhm / (2. * np.sqrt(2. * np.log(2.)))

        # execute Fit algorithm
        tryCentre = x_values[imax]
        fitFun = "name=Gaussian,PeakCentre=%s,Height=%s,Sigma=%s" % (
            tryCentre, height, sigma)
        startX = tryCentre - 3.0 * fwhm
        endX = tryCentre + 3.0 * fwhm

        # pylint: disable=assignment-from-none
        # result = fitStatus, chiSq, covarianceTable, paramTable
        result = Fit(InputWorkspace=self.workspace,
                     WorkspaceIndex=index,
                     StartX=startX,
                     EndX=endX,
                     Output='EPPfit',
                     Function=fitFun,
                     CreateOutput=True,
                     OutputParametersOnly=True)

        return result
Ejemplo n.º 16
0
    def PyExec(self):
        workspace = self.getProperty("Workspace").value
        index     = self.getProperty("Index").value
        nhist     = workspace.getNumberHistograms()

        # index must be in <0,nhist)
        if index >= nhist:
            self._error("Index " + str(index) + " is out of range for the workspace " + workspace.name())

        x_values = np.array(workspace.readX(index))
        y_values = np.array(workspace.readY(index))

        # get peak centre position, assuming that it is the point with the highest value
        imax   = np.argmax(y_values)
        height = y_values[imax]

        # check for zero or negative signal
        if height <= 0.:
            self._warning("Workspace %s, detector %d has maximum <= 0" % (workspace.name(), index))
            return

        # guess sigma (assume the signal is sufficiently smooth)
        # the _only_ peak is at least three samples wide
        # selecting samples above .5 ("full width at half maximum")
        indices  = np.argwhere(y_values > 0.5*height)
        nentries = len(indices)

        if nentries < 3:
            self._warning("Spectrum " + str(index) + " in workspace " + workspace.name()
                          + " has a too narrow peak. Cannot guess sigma. Check your data.")
            return

        minIndex = indices[0,0]
        maxIndex = indices[-1,0]

        # full width at half maximum: fwhm = sigma * (2.*np.sqrt(2.*np.log(2.)))
        fwhm  = np.fabs(x_values[maxIndex] - x_values[minIndex])
        sigma = fwhm / (2.*np.sqrt(2.*np.log(2.)))

        # execute Fit algorithm
        tryCentre = x_values[imax]
        fitFun = "name=Gaussian,PeakCentre=%s,Height=%s,Sigma=%s" % (tryCentre,height,sigma)
        startX = tryCentre - 3.0*fwhm
        endX   = tryCentre + 3.0*fwhm

        # pylint: disable = unpacking-non-sequence, assignment-from-none
        fit_output = Fit(
            InputWorkspace=workspace, WorkspaceIndex=index,
            Function=fitFun, CreateOutput=True, OutputParametersOnly=True,
            StartX=startX, EndX=endX)

        if not 'success' == fit_output.OutputStatus:
            self._warning("For detector " + str(index) + " in workspace " + workspace.name()
                          + "fit was not successful. Input guess parameters were " + str(fitFun))
            return

        fitParams = fit_output.OutputParameters.column(1)
        self._setOutput(fitParams[1],fitParams[2]) # [peakCentre,sigma]
Ejemplo n.º 17
0
 def test_Fit_accepts_EnableLogging_keyword(self):
     if platform.system() == 'Darwin':  # crashes
         return
     output_name = "otherargs_fitWS"
     retvals = Fit("name=FlatBackground",
                   self._raw_ws,
                   MaxIterations=2,
                   Output=output_name,
                   EnableLogging=False)
     self.assertTrue(output_name + '_Workspace' in mtd)
Ejemplo n.º 18
0
 def test_use_in_fit(self):
     workspace = create_test_workspace(
         create_model("MsdGauss", Height=1.0, MSD=0.05), 1000)
     function_string = create_function_string("MsdGauss",
                                              Height=1.0,
                                              MSD=0.05)
     Fit(Function=function_string,
         InputWorkspace=workspace,
         StartX=1.2,
         EndX=1200)
Ejemplo n.º 19
0
    def test_fit(self):
        if self.skipTest():  # python2.6 doesn't have skipping decorators
            return

        from random import random
        variation = lambda x: x * (
            1 + (random() - 0.5) / 5.
        )  # range [x*0.9, x*1.1] should be bigger but not until parameter constraints have been exposed to python
        #Generate a data workspace using random parameters around {'height':0.1,'tau':100,'beta':1}
        parms = {
            'height': variation(0.1),
            'tau': variation(100),
            'beta': variation(1)
        }

        Nh = 2000
        de = 0.0004
        AlgorithmFactory.subscribe(_InternalMakeSEFTData)
        alg = testhelpers.run_algorithm('_InternalMakeSEFTData',
                                        nhalfbins=Nh,
                                        de=de,
                                        OutputWorkspace='_test_seft_data',
                                        **parms)

        sx = -Nh * de + de / 2
        ex = (Nh - 1) * de + de / 2
        func_string = 'name=StretchedExpFT,height=0.1,tau=100,beta=1'
        Fit(Function=func_string,
            InputWorkspace='_test_seft_data',
            StartX=sx,
            EndX=ex,
            CreateOutput=1,
            MaxIterations=20)

        ws = mtd['_test_seft_data_Parameters']
        fitted = ''
        for irow in range(ws.rowCount()):
            row = ws.row(irow)
            name = row['Name']
            if name == 'Cost function value':
                value = row['Value']
            elif name in parms.keys():
                fitted += '{0}={1}, '.format(name, row['Value'])
        target = ', '.join('{0}={1}'.format(key, val)
                           for key, val in parms.items())
        msg = 'Cost function {0} too high\nTargets were {1},\nbut obtained {2}'.format(
            value, target, fitted)
        self.assertTrue(value < 5.0, msg)
        msg = 'Cost function {0}\nStarted with height=0.1, tau=100, beta=1\nTargets were {1},\nobtained {2}'.format(
            value, target, fitted)

        mtd.remove('_test_seft_data')
        mtd.remove('_test_seft_data_NormalisedCovarianceMatrix')
        mtd.remove('_test_seft_data_Parameters')
        mtd.remove('_test_seft_data_Workspace')
Ejemplo n.º 20
0
    def test_fit_succeeds_with_expected_answer(self):
        AlgorithmFactory.subscribe(_InternalMakeLinear)
        alg = testhelpers.run_algorithm("_InternalMakeLinear", A0=1.0,A1=0.75,OutputWorkspace='_test_linear')

        func_string="name=Example1DFunction,A0=0.0,A1=0.0"
        Fit(Function=func_string,InputWorkspace="_test_linear",StartX=1000,EndX=6000,CreateOutput=1,MaxIterations=2)

        mtd.remove('_test_linear')
        mtd.remove('_test_linear_NormalisedCovarianceMatrix')
        mtd.remove('_test_linear_Parameters')
        mtd.remove('_test_linear_Workspace')
Ejemplo n.º 21
0
def do_fit(tg, fString, shape):
    """
    Given a target shape and initial fit function guess, carry out the fit
    :param tg: dictionary of target fitting parameters
    :param fString: initial guess of the fit function
    :param shape: Gaussian or Lorentzian, either integrated or not 
    :return: success or failure of the fit
    """
    if 'Gaussian' in shape:
        E0 = planck_constant / tg['tau']
        # Analytical Fourier transform of exp(-(t/tau)**2)
        functor = lambda E: np.sqrt(np.pi) / E0 * np.exp(-(np.pi * E / E0)**2)
    elif 'Lorentzian' in shape:
        hwhm = planck_constant / (2 * np.pi * tg['tau'])
        # Analytical Fourier transform of exp(-t/tau)
        functor = lambda E: (1.0 / np.pi) * hwhm / (hwhm**2 + E**2)
    if 'Integrated' in shape:
        # when testing function PrimStretchedExpFT
        def ifunctor(E):
            """Numerical integral of the functor within each energy bin"""
            de = (E[-1] - E[0]) / (len(E) - 1.0)  # energy spacing
            rf = 100  # make the energy domain a grid 100 times finer
            efine = np.arange(E[0] - de, E[-1] + 2 * de, de / rf)
            values = functor(efine)  # evaluate on the finer grid
            primitive = np.cumsum(
                values) / rf  # cummulative sum, giving the integral
            # bb are bin boundaries delimiting bins of width de and centered at the E values
            bb = (E[1:] + E[:-1]) / 2  # internal bin boundaries
            bb = np.insert(bb, 0,
                           2 * E[0] - bb[0])  # external lower bin boundary
            bb = np.append(bb,
                           2 * E[-1] - bb[-1])  # external upper bin boundary
            # return the integral over each energy bin
            return np.interp(bb[1:], efine, primitive) - np.interp(
                bb[:-1], efine, primitive)

        createData(ifunctor)
    else:
        # when testing function StretchedExpFT
        createData(functor)  # Create workspace "data"
    Fit(Function=fString,
        InputWorkspace="data",
        MaxIterations=100,
        Output="fit")
    return assertFit(mtd["fit_Parameters"], tg)
Ejemplo n.º 22
0
    def general_fit(self, xvals, yvals, peakids):
        if not peakids:
            return np.zeros(len(yvals)), None

        fit_func = ''
        fit_constr = ''
        for i, pid in enumerate(peakids):
            win_size = int(self._estimate_sigma * len(xvals) /
                           (max(xvals) - min(xvals)))
            if win_size < 2:
                win_size = 2
            centre, height, sigma = tuple(
                self.estimate_single_parameters(xvals, yvals, pid, win_size))
            if sigma < self._min_sigma:
                centre = xvals[pid]
                height = yvals[pid]
                sigma = self._estimate_sigma
            fit_func += 'name=Gaussian,PeakCentre={},Height={},Sigma={};'.format(
                centre, height, sigma)
            fit_constr += '%f<f%d.PeakCentre<%f,%f<f%d.Height<%f,%f<f%d.Sigma<%d,' \
                          % (xvals[pid] * (1 - self._general_tolerance), i, xvals[pid] * (1 + self._general_tolerance),
                             yvals[pid] * (1 - self._general_tolerance), i, yvals[pid] * (1 + self._general_tolerance),
                             self._min_sigma, i, self._max_sigma)

        if fit_func == '':
            return yvals, self.function_difference(yvals, np.zeros(len(yvals)),
                                                   np.sqrt(yvals))

        if fit_constr.count('PeakCentre') == 1:
            fit_constr = fit_constr.replace('f0.', '')

        _, _, _, param, fit_result, _, _ = Fit(
            Function=fit_func,
            InputWorkspace=self.getProperty('InputWorkspace').value,
            Output='fit_result',
            Minimizer='Levenberg-MarquardtMD',
            OutputCompositeMembers=True,
            StartX=min(xvals),
            EndX=max(xvals),
            Constraints=fit_constr,
            StoreInADS=False)

        return fit_result.readY(1).copy(), param
Ejemplo n.º 23
0
 def _fit_gaussian(self, inWS, ws, x, y, startX, endX, output_fit):
     """fits ws to Gaussian + Flat background"""
     function = f"name=FlatBackground, A0={np.nanmin(y)};" \
                f"name=Gaussian, PeakCentre={x[np.nanargmax(y)]}, Height={np.nanmax(y) - np.nanmin(y)}, Sigma=0.25"
     constraints = f"f0.A0 > 0, f1.Height > 0, {x.min()} < f1.PeakCentre < {x.max()}"
     fit_result = ""
     try:
         fit_result = Fit(function,
                          ws,
                          Output=str(ws),
                          IgnoreInvalidData=True,
                          OutputParametersOnly=not output_fit,
                          Constraints=constraints,
                          StartX=startX,
                          EndX=endX,
                          EnableLogging=False)
     except RuntimeError as e:
         self.log().warning("Failed to fit workspace {}: {}".format(
             inWS, e))
     return fit_result
Ejemplo n.º 24
0
    def test_fit_succeeds_with_expected_answer(self):
        AlgorithmFactory.subscribe(_InternalMakeGaussian)
        alg = testhelpers.run_algorithm("_InternalMakeGaussian",
                                        Height=300,
                                        Centre=2100,
                                        Sigma=700,
                                        OutputWorkspace='_test_gauss')

        func_string = "name=ExamplePeakFunction,NTerms=3,Height=309.92,PeakCentre=2105,Sigma=710.2"
        Fit(Function=func_string,
            InputWorkspace="_test_gauss",
            StartX=150,
            EndX=4310,
            CreateOutput=1,
            MaxIterations=2)

        mtd.remove('_test_gauss')
        mtd.remove('_test_gauss_NormalisedCovarianceMatrix')
        mtd.remove('_test_gauss_Parameters')
        mtd.remove('_test_gauss_Workspace')
Ejemplo n.º 25
0
 def testLorentzian(self):
     """ Test the Fourier transform of a exponential is a Lorentzian"""
     if self.skipTest:  # python2.6 doesn't have skipping decorators
         return
     # Target parameters
     tau = 100.0  # picoseconds
     beta = 1.0  # exponential
     height = 1.0  # We want identity, not just proporcionality
     # Analytical Fourier transform of exp(-t/tau)
     hwhm = StretchedExpFTTest._planck_constant / (2 * np.pi * tau)
     functor = lambda E: (1.0 / np.pi) * hwhm / (hwhm**2 + E**2)
     self.createData(functor)  # Create workspace "data"
     # Initial guess reasonably far from target parameters
     fString = "name=StretchedExpFT,Height=3.0,Tau=50,Beta=1.5,Centre=0.0002;" +\
               "name=FlatBackground,A0=0.0"
     Fit(Function=fString,
         InputWorkspace="data",
         MaxIterations=100,
         Output="fit")
     self.asserFit(mtd["fit_Parameters"], height, beta, tau)
     self.cleanFit()
Ejemplo n.º 26
0
def do_a_fit(x, function, guess, target, fixes=None, atol=0.01):
    r"""Carry out a fit and compare to target parameters

    Parameters
    ----------
    x : sequence of floats
        Domain values for evaluating the function .
    function : str
        Registered function name.
    guess : dict
        Parameter names with their initial values.
    target : dict
        Parameter names with the values to be obtained after the fit.
    fixes : list
        List of fitting parameters to fix during the fit
    atol : float
        Absolute tolerance parameter when evaluating expected_output against
        output values.

    Returns
    -------
    list
        [0] Evaluation of the comparison between evaluated and expected values.
        [1] output of the call to Fit algorithm
    """
    target_model = FunctionWrapper(function, **target)
    y = target_model(x)
    e = np.ones(len(x))
    w = CreateWorkspace(x, y, e, Nspec=1)
    model = FunctionWrapper(function, **guess)
    if fixes is not None:
        [model.fix(p) for p in fixes]
    fit = Fit(model, w, NIterations=2000)
    otarget = OrderedDict(target)
    return np.allclose([fit.Function[p] for p in otarget.keys()],
                       list(otarget.values()), atol), fit
Ejemplo n.º 27
0
def sel_const(runs,
              dist=4.0,
              thickness=5e-3,
              show_fits=False,
              show_quality=False):
    """Calculate the spin echo length of the instrument

    Parameters
    ----------
    runs: list of Workspaces
      A list of the workspecaes containing the polarisation versus wavelength
      for consecutive detector tubes
    dist: float
      The distances from the sample to the detector in meters.  The default
      is 4.0
    thickness: float
      The distance between detector tubes in meters.  Defaults to 5mm.
    show_fits: bool
      If true, plots the sinusoid fits used to calculate the frequency
    show_quality: bool
      If true, plots the frequency versus tube position to confirm that the
      frequency grows linearly with position.

    Returns
    -------
    A float containing the spin echo length, in nanometers, of a one angstrom
    neutron.
    """
    freqs = []
    for run in runs:
        x = run.extractX()[0]
        x = (x[1:] + x[:-1]) / 2
        p = run.extractY()[0]
        p[np.isnan(p)] = 0
        fp = np.fft.fft(p)

        conv = len(x) / (np.max(x) - np.min(x))
        max_arg = (np.nanargmax(np.abs(fp[1:int(len(p) / 2)])) + 1)
        amp = np.abs(fp[max_arg]) / len(x)
        max_arg = max_arg * conv / len(x)

        model = "name=UserFunction,Formula=e*cos(x*f),f={},e={}"
        Fit(Function=model.format(max_arg * 2 * np.pi, amp),
            InputWorkspace=run,
            StartX=3,
            EndX=7,
            CreateOutput=True)

        result = mtd[run.getName() + "_Parameters"]

        freqs.append(np.abs(result.column(1)[1] / 2 / np.pi))
        if not show_fits:
            DeleteWorkspace(run.getName() + "_Parameters")
            DeleteWorkspace(run.getName() + "_NormalisedCovarianceMatrix")
            DeleteWorkspace(run.getName() + "_Workspace")

    def model(x, m, b):
        """A simple linear model"""
        return m * x + b

    xs = np.arange(len(runs)) * thickness
    fit, _ = curve_fit(model, xs, freqs)

    sel_fits = CreateWorkspace(xs, freqs)
    Fit(Function="name=LinearBackground",
        InputWorkspace=sel_fits,
        CreateOutput=True)
    result = 0.1 * mtd["sel_fits_Parameters"].column(1)[1] * dist
    if not show_quality:
        DeleteWorkspace("sel_fits_Parameters")
        DeleteWorkspace("sel_fits_NormalisedCovarianceMatrix")
        DeleteWorkspace("sel_fits_Workspace")
        DeleteWorkspace("sel_fits")

    return result
Ejemplo n.º 28
0
def _create_fit_workspace():
    fn_input = FIT_DICT['properties']
    Fit(**fn_input)
Ejemplo n.º 29
0
    def test_fit(self):
        if self.skipTest:  # python2.6 doesn't have skipping decorators
            return

        from random import random
        # the variation range below is [x*0.9, x*1.1]. Should be bigger,
        # but not until parameter constraints have been exposed to python
        variation = lambda x: x * (1 + (random() - 0.5) / 5.)

        # Generate data workspace using random parameters around height=0.1,tau=100, beta=1,
        # and centered at the origin
        parms = {
            'height': variation(0.1),
            'tau': variation(100),
            'beta': variation(1)
        }

        Nh = 2000
        de = 0.0004
        AlgorithmFactory.subscribe(_InternalMakeSEFTData)
        alg = testhelpers.run_algorithm('_InternalMakeSEFTData',
                                        nhalfbins=Nh,
                                        de=de,
                                        OutputWorkspace='_test_seft_data',
                                        **parms)

        sx = -Nh * de + de / 2
        ex = (Nh - 1) * de + de / 2
        # Our initial guess is not centered at the origin, but around de
        initial_parameters = 'height=0.1, tau=100, beta=1, Origin=%f' % variation(
            de)
        func_string = 'name=StretchedExpFT,%s' % initial_parameters
        Fit(Function=func_string,
            InputWorkspace='_test_seft_data',
            StartX=sx,
            EndX=ex,
            CreateOutput=1,
            MaxIterations=20)

        parms[
            'Origin'] = 0.0  # insert (Origin,0.0) to parameter dictionary for assessment of fit results
        ws = mtd['_test_seft_data_Parameters']
        #tr()
        fitted = ''
        unacceptable_chi_square = 3.0
        chi_square = unacceptable_chi_square
        for irow in range(ws.rowCount()):
            row = ws.row(irow)
            name = row['Name']
            if name == 'Cost function value':
                chi_square = row['Value']
            elif name in parms.keys():
                fitted += '{0}={1}, '.format(name, row['Value'])
        target = ', '.join('{0}={1}'.format(key, val)
                           for key, val in parms.items())
        msg = 'Cost function {0} too high\nTargets were {1},\nbut obtained {2}'.format(
            chi_square, target, fitted)
        self.assertTrue(chi_square < unacceptable_chi_square, msg)
        msg = 'Cost function ={0}\n'.format(chi_square)
        msg += 'Target parameters were {0}\n'.format(target)
        msg += 'Started with parameters {0}\n'.format(initial_parameters)
        msg += 'obtained fitted parameters {0}'.format(fitted)
        print msg
        mtd.remove('_test_seft_data')
        mtd.remove('_test_seft_data_NormalisedCovarianceMatrix')
        mtd.remove('_test_seft_data_Parameters')
        mtd.remove('_test_seft_data_Workspace')
Ejemplo n.º 30
0
    def PyExec(self):
        # ----------------------------------------------------------
        # Imports resonance parameters from ResParam dictionary depending on the selected foil type.
        # ----------------------------------------------------------
        files = self.getProperty("Files").value
        files = self.validateFileInputs(files)
        foilType = self.getProperty("FoilType").value
        divE = float(self.getProperty("Ediv").value)
        isCalib = self.getProperty("Calibration").value
        mass = self.ResParamsDict[foilType + '_Mass']
        TD = self.ResParamsDict[foilType + '_TD']
        # Energy parameters are in eV
        energy = self.ResParamsDict[foilType + '_En']
        TwogG = self.ResParamsDict[foilType+'_TwogG']
        Gg = self.ResParamsDict[foilType+'_Gg']
        startE = self.ResParamsDict[foilType+'_startE']
        endE = self.ResParamsDict[foilType+'_endE']
        refTemp = float(self.getProperty("ReferenceTemp").value)
        isDebug = self.getProperty("Debug").value

        if not isCalib:
            if 'S_fit_Parameters' not in mtd:
                self.log().warning("No calibration files found. Please run this algorithm will 'Calibration' ticked to "
                                   "generate the calibration workspace.")
                return

        self.monitorTransfit(files, foilType, divE)
        file = files[0]
        discard, fileName = path.split(file)
        fnNoExt = path.splitext(fileName)[0]

        # Define the gaussian width at the reference temperature
        # Factor of 1e3 converting to meV for Mantid

        width_300 = 1000.0 * np.sqrt(4 * energy * self.k * refTemp * mass / (self.e * (1 + mass) ** 2))

        # ----------------------------------------------------------
        # Perform fits based on whether isCalib is flagged (calibration or measurement)
        # ----------------------------------------------------------
        if isCalib:
            lorentzFWHM = 1000.0 * (0.5 * TwogG + Gg)
            # Take peak position starting guess from tabulated value
            peakPosGuess = energy * 1000
            fileName_monitor = fnNoExt + '_monitor'
            # For guessing initial background values, read in y-data and use starting value as value for b0
            wsBgGuess = mtd[fileName_monitor]
            bg0guess = 0.86 * wsBgGuess.readY(0)[0]
            # New Voigt function as from Igor pro function
            Fit(Function='name=PEARLTransVoigt,Position=' + str(peakPosGuess) + ',LorentzianFWHM=' + str(
                lorentzFWHM) + ',GaussianFWHM=' + str(width_300) + ',Amplitude=1.6,Bg0=' + str(
                bg0guess) + ',Bg1=0.0063252,Bg2=0,constraints=(1<LorentzianFWHM,' + str(width_300)
                + '<GaussianFWHM)', InputWorkspace=fileName_monitor, MaxIterations=200, Output='S_fit')
            #
            DeleteWorkspace('S_fit_NormalisedCovarianceMatrix')
            DeleteWorkspace(fileName_monitor)

        else:
            S_fit = mtd['S_fit_Parameters']
            lorentzFWHM = S_fit.column(1)[1]
            gaussianFWHM = S_fit.column(1)[2]

            # Calculates the gaussian resolution contribution, sometimes constraints are broken and the value can drop
            # below that from width_300 alone, in which case the instrument contribution is set to zero.
            if gaussianFWHM > width_300:
                gaussianFWHM_inst = np.sqrt(gaussianFWHM**2 - width_300**2)
            else:
                gaussianFWHM_inst = 0
            #
            # New Voigt function as from Igor pro function
            Fit(Function='name=PEARLTransVoigt,Position=' + str(S_fit.column(1)[0]) + ',LorentzianFWHM='
                         + str(lorentzFWHM) + ',GaussianFWHM=' + str(gaussianFWHM) + ',Amplitude='
                         + str(S_fit.column(1)[3]) + ',Bg0=' + str(S_fit.column(1)[4]) + ',Bg1='
                         + str(S_fit.column(1)[5]) + ',Bg2=' + str(S_fit.column(1)[6]) + ',constraints=('
                         + str(gaussianFWHM) + '<GaussianFWHM),ties=(LorentzianFWHM=' + str(lorentzFWHM) + ')',
                InputWorkspace=fnNoExt + '_monitor', MaxIterations=200, Output='T_fit')
            #
            DeleteWorkspace('T_fit_NormalisedCovarianceMatrix')
            DeleteWorkspace(fnNoExt + '_monitor')
            T_fit = mtd['T_fit_Parameters']
            gaussian_FWHM_fitted = T_fit.column(1)[2]
            width_T = np.sqrt(gaussian_FWHM_fitted ** 2 - gaussianFWHM_inst ** 2)
            # Factor of 1e-3 converts back from meV to eV
            Teff = (((width_T * 1e-3) ** 2) * self.e * ((1 + mass) ** 2)) / (4 * 1e-3 * T_fit.column(1)[0] * self.k
                                                                             * mass)
            Teff_low = ((((width_T - T_fit.column(2)[2]) * 1e-3) ** 2) * self.e
                        * ((1 + mass) ** 2))/(4 * 1e-3 * (T_fit.column(1)[0] + T_fit.column(2)[0]) * self.k * mass)
            Teff_high = ((((width_T + T_fit.column(2)[2]) * 1e-3) ** 2) * self.e * ((1 + mass) ** 2)) /\
                        (4 * 1e-3 * (T_fit.column(1)[0] - T_fit.column(2)[0]) * self.k * mass)
            errTeff = 0.5*(Teff_high-Teff_low)
            # ----------------------------------------------------------
            # If the temperature is too far below the Debye temperature, then the result is inaccurate. Else the
            # temperature is calculated assuming free gas formulation
            # ----------------------------------------------------------
            if 8 * Teff < 3 * TD:
                self.log().information("The effective temperature is currently too far below the Debye temperature to"
                                       "give an accurate measure.")
                Tactual = Teff
                Terror = errTeff
            else:
                Tactual = 3 * TD / (4 * np.log((8 * Teff + 3 * TD)/(8 * Teff - 3 * TD)))
                Tactual_high = 3 * TD / (4 * np.log((8 * (Teff + errTeff) + 3 * TD) / (8 * (Teff + errTeff) - 3 * TD)))
                Tactual_low = 3 * TD / (4 * np.log((8 * (Teff - errTeff) + 3 * TD) / (8 * (Teff - errTeff) - 3 * TD)))
                Terror = 0.5 * (np.abs(Tactual - Tactual_high) + np.abs(Tactual - Tactual_low))
            # Introduce a catchment for unphysically small determined errors, setting to defualt value if below a set
            # threshold
            Terror_flag = 0
            if Terror < 5.0:
                Terror_flag = 1
                Terror = 10.0
            if isDebug:
                self.log().information("-----------------------------")
                self.log().information("Debugging....")
                self.log().information("The Debye temperature is " + str(TD) + " K")
                self.log().information("The effective temperature is: {:.1f}"
                                       .format(Teff) + "+/- {:.1f}".format(errTeff) + " K")
                self.log().information("Energy bin width set to " + str(1000 * divE) + " meV")
                self.log().information("E range is between " + str(startE) + " and " + str(endE))
                self.log().information("Gaussian width at this reference temperature is: {:.2f}".format(width_300)
                                       + " meV")
                self.log().information("Lorentzian FWHM is fixed: {:.2f}".format(lorentzFWHM)+" meV")
                self.log().information("Gaussian FWHM is fitted as: {:.2f}".format(gaussian_FWHM_fitted) + " meV")
                self.log().information("Instrumental contribution is: {:.2f}".format(gaussianFWHM_inst) + " meV")
                self.log().information("Temperature contribution is: {:.2f}".format(width_T) + " meV")
                self.log().information("-----------------------------")

            self.log().information("Sample temperature is: {:.1f}".format(Tactual) + " +/- {:.1f}".format(Terror)
                                   + " K")
            if Terror_flag == 1:
                self.log().information("(the default error, as determined error unphysically small)")