Пример #1
0
    def PyExec(self):
        # Check congruence of workspaces
        workspaces = self.getProperty('Workspaces').value
        fvalues = self.getProperty('ParameterValues').value
        if len(workspaces) != len(fvalues):
            mesg = 'Number of Workspaces and ParameterValues should be the same'
            #logger.error(mesg)
            raise IndexError(mesg)
        for workspace in workspaces[1:]:
            if not self.areWorkspacesCompatible(mantid.mtd[workspaces[0]],
                                                mantid.mtd[workspace]):
                mesg = 'Workspace {0} incompatible with {1}'.format(
                    workspace, workspaces[0])
                logger.error(mesg)
                raise ValueError(mesg)
    # Load the workspaces into a group of dynamic structure factors
        from dsfinterp.dsf import Dsf
        from dsfinterp.dsfgroup import DsfGroup
        from dsfinterp.channelgroup import ChannelGroup
        dsfgroup = DsfGroup()
        for idsf in range(len(workspaces)):
            dsf = Dsf()
            dsf.Load(mantid.mtd[workspaces[idsf]])
            if not self.getProperty('LoadErrors').value:
                dsf.errors = None  # do not incorporate error data
            dsf.SetFvalue(fvalues[idsf])
            dsfgroup.InsertDsf(dsf)
    # Create the intepolator if not instantiated before
        if not self.channelgroup:
            self.channelgroup = ChannelGroup()
            self.channelgroup.InitFromDsfGroup(dsfgroup)
            localregression = self.getProperty('LocalRegression').value
            if localregression:
                regressiontype = self.getProperty('RegressionType').value
                windowlength = self.getProperty('RegressionWindow').value
                self.channelgroup.InitializeInterpolator(
                    running_regr_type=regressiontype,
                    windowlength=windowlength)
            else:
                self.channelgroup.InitializeInterpolator(windowlength=0)

    # Invoke the interpolator and generate the output workspaces
        targetfvalues = self.getProperty('TargetParameters').value
        for targetfvalue in targetfvalues:
            if targetfvalue < min(fvalues) or targetfvalue > max(fvalues):
                mesg = 'Target parameters should lie in [{0}, {1}]'.format(
                    min(fvalues), max(fvalues))
                logger.error(mesg)
                raise ValueError(mesg)
        outworkspaces = self.getProperty('OutputWorkspaces').value
        if len(targetfvalues) != len(outworkspaces):
            mesg = 'Number of OutputWorkspaces and TargetParameters should be the same'
            logger.error(mesg)
            raise IndexError(mesg)
        for i in range(len(targetfvalues)):
            dsf = self.channelgroup(targetfvalues[i])
            outws = mantid.simpleapi.CloneWorkspace(
                mantid.mtd[workspaces[0]], OutputWorkspace=outworkspaces[i])
            dsf.Save(outws)  # overwrite dataY and dataE
Пример #2
0
class DSFinterp1DFit(IFunction1D):

    _RegressionTypes = None
    _minWindow = None
    _InputWorkspaces = None
    _LoadErrors = None
    _WorkspaceIndex = None
    _ParameterValues = None
    _fmin = None
    _fmax = None
    _LocalRegression = None
    _RegressionType = None
    _RegressionWindow = None
    _xvalues = None
    _channelgroup = None

    def category(self):
        return 'QuasiElastic'

    def init(self):
        '''Declare parameters and attributes that participate in the fitting'''
        # Active fitting parameters
        self.declareParameter('Intensity', 1.0, 'Intensity')
        self.declareParameter(
            'TargetParameter', 1.0,
            'Target value of the structure factor parameter')

        self.declareAttribute('InputWorkspaces', '')
        self.declareAttribute('LoadErrors', False)
        self.declareAttribute('WorkspaceIndex', 0)
        self.declareAttribute('ParameterValues', '')
        self.declareAttribute('LocalRegression', True)
        self.declareAttribute('RegressionType', 'quadratic')
        self.declareAttribute('RegressionWindow', 6)
        # "private" attributes associated to the declare function attributes
        self._InputWorkspaces = None
        self._LoadErrors = None
        self._WorkspaceIndex = None
        self._ParameterValues = None
        self._fmin = None
        self._fmax = None
        self._LocalRegression = None
        self._RegressionType = None
        self._RegressionTypes = set(['linear', 'quadratic'
                                     ])  #valid syntaxfor python >= 2.6
        self._RegressionWindow = None
        self._minWindow = {'linear': 3, 'quadratic': 4}
        # channelgroup to interpolate values
        self._channelgroup = None
        self._xvalues = None  #energies of the channels

    def setAttributeValue(self, name, value):
        if name == "InputWorkspaces":
            self._InputWorkspaces = value.split()
            if ',' in value:
                self._InputWorkspaces = [x.strip() for x in value.split(',')]
        elif name == 'LoadErrors':
            self._LoadErrors = bool(value)
        elif name == 'WorkspaceIndex':
            self._WorkspaceIndex = int(value)
        elif name == 'ParameterValues':
            self._ParameterValues = []
            self._fmin = 0.0
            self._fmax = 0.0
            if value:
                self._ParameterValues = [float(f) for f in value.split()]
                self._fmin = min(self._ParameterValues)
                self._fmax = max(self._ParameterValues)
        elif name == 'LocalRegression':
            self._LocalRegression = bool(value)
        elif name == 'RegressionType':
            self._RegressionType = value.lower()
        elif name == 'RegressionWindow':
            self._RegressionWindow = value

    def validateParams(self):
        '''Check parameters within expected range'''
        intensity = self.getParameterValue('Intensity')
        if intensity <= 0:
            message = 'Parameter Intensity in DSFinterp1DFit must be positive. Got {0} instead'.format(
                intensity)
            logger.error(message)
            return None
        f = self.getParameterValue('TargetParameter')
        if f < self._fmin or f > self._fmax:
            message = 'TargetParameter {0} is out of bounds [{1}, {2}]. Applying penalty...'.format(
                f, self._fmin, self._fmax)
            logger.error(message)
            return None
        return {'Intensity': intensity, 'TargetParameter': f}

    def function1D(self, xvals):
        ''' Fit using the interpolated structure factor '''
        p = self.validateParams()
        if not p:
            return numpy.zeros(
                len(xvals),
                dtype=float)  # return zeros if parameters not valid
        # The first time the function is called requires initialization of the interpolator
        if self._channelgroup is None:
            # Check consistency of the input
            # check InputWorkspaces have at least the workspace index
            for w in self._InputWorkspaces:
                if mtd[w].getNumberHistograms() <= self._WorkspaceIndex:
                    message = 'Numer of histograms in Workspace {0} does not allow for workspace index {1}'.format(
                        w, self._WorkspaceIndex)
                    logger.error(message)
                    raise IndexError(message)
            # check number of input workspaces and parameters is the same
            if len(self._ParameterValues) != len(self._InputWorkspaces):
                message = 'Number of InputWorkspaces and ParameterValues should be the same.'+\
                          ' Found {0} and {1}, respectively'.format(len(self._InputWorkspaces), len(self._ParameterValues))
                logger.error(message)
                raise ValueError(message)
            # check the regression type is valid
            if self._RegressionType not in self._RegressionTypes:
                message = 'Regression type {0} not implemented. choose one of {1}'.format(
                    self._RegressionType, ', '.join(self._RegressionTypes))
                logger.error(message)
                raise NotImplementedError(message)
            # check the regression window is appropriate for the regression type selected
            if self._RegressionWindow < self._minWindow[self._RegressionType]:
                message = 'RegressionWindow must be equal or bigger than '+\
                          '{0} for regression type {1}'.format(self._minWindow[self._RegressionType], self._RegressionType)
                logger.error(message)
                raise ValueError(message)
            # Initialize the energies of the channels with the first of the input workspaces
            self._xvalues = numpy.copy(mtd[self._InputWorkspaces[0]].dataX(
                self._WorkspaceIndex))
            if len(self._xvalues) == 1 + len(
                    mtd[self._InputWorkspaces[0]].dataY(self._WorkspaceIndex)):
                self._xvalues = (self._xvalues[1:] + self._xvalues[:-1]
                                 ) / 2.0  # Deal with histogram data
            # Initialize the channel group
            nf = len(self._ParameterValues)
            # Load the InputWorkspaces into a group of dynamic structure factors
            from dsfinterp.dsf import Dsf
            from dsfinterp.dsfgroup import DsfGroup
            dsfgroup = DsfGroup()
            for idsf in range(nf):
                dsf = Dsf()
                dsf.SetIntensities(mtd[self._InputWorkspaces[idsf]].dataY(
                    self._WorkspaceIndex))
                dsf.errors = None  # do not incorporate error data
                if self._LoadErrors:
                    dsf.SetErrors(mtd[self._InputWorkspaces[idsf]].dataE(
                        self._WorkspaceIndex))
                dsf.SetFvalue(self._ParameterValues[idsf])
                dsfgroup.InsertDsf(dsf)
            # Create the interpolator
            from dsfinterp.channelgroup import ChannelGroup
            self._channelgroup = ChannelGroup()
            self._channelgroup.InitFromDsfGroup(dsfgroup)
            if self._LocalRegression:
                self._channelgroup.InitializeInterpolator(
                    running_regr_type=self._RegressionType,
                    windowlength=self._RegressionWindow)
            else:
                self._channelgroup.InitializeInterpolator(windowlength=0)
        # channel group has been initialized, so evaluate the interpolator
        dsf = self._channelgroup(p['TargetParameter'])
        # Linear interpolation between the energies of the channels and the xvalues we require
        # NOTE: interpolator evaluates to zero for any of the xvals outside of the domain defined by self._xvalues
        intensities_interpolator = scipy.interpolate.interp1d(self._xvalues,
                                                              p['Intensity'] *
                                                              dsf.intensities,
                                                              kind='linear')
        return intensities_interpolator(xvals)  # can we pass by reference?
Пример #3
0
 def function1D(self, xvals):
     ''' Fit using the interpolated structure factor '''
     p = self.validateParams()
     if not p:
         return numpy.zeros(
             len(xvals),
             dtype=float)  # return zeros if parameters not valid
     # The first time the function is called requires initialization of the interpolator
     if self._channelgroup is None:
         # Check consistency of the input
         # check InputWorkspaces have at least the workspace index
         for w in self._InputWorkspaces:
             if mtd[w].getNumberHistograms() <= self._WorkspaceIndex:
                 message = 'Numer of histograms in Workspace {0} does not allow for workspace index {1}'.format(
                     w, self._WorkspaceIndex)
                 logger.error(message)
                 raise IndexError(message)
         # check number of input workspaces and parameters is the same
         if len(self._ParameterValues) != len(self._InputWorkspaces):
             message = 'Number of InputWorkspaces and ParameterValues should be the same.'+\
                       ' Found {0} and {1}, respectively'.format(len(self._InputWorkspaces), len(self._ParameterValues))
             logger.error(message)
             raise ValueError(message)
         # check the regression type is valid
         if self._RegressionType not in self._RegressionTypes:
             message = 'Regression type {0} not implemented. choose one of {1}'.format(
                 self._RegressionType, ', '.join(self._RegressionTypes))
             logger.error(message)
             raise NotImplementedError(message)
         # check the regression window is appropriate for the regression type selected
         if self._RegressionWindow < self._minWindow[self._RegressionType]:
             message = 'RegressionWindow must be equal or bigger than '+\
                       '{0} for regression type {1}'.format(self._minWindow[self._RegressionType], self._RegressionType)
             logger.error(message)
             raise ValueError(message)
         # Initialize the energies of the channels with the first of the input workspaces
         self._xvalues = numpy.copy(mtd[self._InputWorkspaces[0]].dataX(
             self._WorkspaceIndex))
         if len(self._xvalues) == 1 + len(
                 mtd[self._InputWorkspaces[0]].dataY(self._WorkspaceIndex)):
             self._xvalues = (self._xvalues[1:] + self._xvalues[:-1]
                              ) / 2.0  # Deal with histogram data
         # Initialize the channel group
         nf = len(self._ParameterValues)
         # Load the InputWorkspaces into a group of dynamic structure factors
         from dsfinterp.dsf import Dsf
         from dsfinterp.dsfgroup import DsfGroup
         dsfgroup = DsfGroup()
         for idsf in range(nf):
             dsf = Dsf()
             dsf.SetIntensities(mtd[self._InputWorkspaces[idsf]].dataY(
                 self._WorkspaceIndex))
             dsf.errors = None  # do not incorporate error data
             if self._LoadErrors:
                 dsf.SetErrors(mtd[self._InputWorkspaces[idsf]].dataE(
                     self._WorkspaceIndex))
             dsf.SetFvalue(self._ParameterValues[idsf])
             dsfgroup.InsertDsf(dsf)
         # Create the interpolator
         from dsfinterp.channelgroup import ChannelGroup
         self._channelgroup = ChannelGroup()
         self._channelgroup.InitFromDsfGroup(dsfgroup)
         if self._LocalRegression:
             self._channelgroup.InitializeInterpolator(
                 running_regr_type=self._RegressionType,
                 windowlength=self._RegressionWindow)
         else:
             self._channelgroup.InitializeInterpolator(windowlength=0)
     # channel group has been initialized, so evaluate the interpolator
     dsf = self._channelgroup(p['TargetParameter'])
     # Linear interpolation between the energies of the channels and the xvalues we require
     # NOTE: interpolator evaluates to zero for any of the xvals outside of the domain defined by self._xvalues
     intensities_interpolator = scipy.interpolate.interp1d(self._xvalues,
                                                           p['Intensity'] *
                                                           dsf.intensities,
                                                           kind='linear')
     return intensities_interpolator(xvals)  # can we pass by reference?
Пример #4
0
class DSFinterp(PythonAlgorithm):

    channelgroup = None

    def category(self):
        return "Transforms\\Smoothing"

    def name(self):
        return 'DSFinterp'

    def summary(self):
        return 'Given a set of parameter values {Ti} and corresponding structure factors S(Q,E,Ti), this algorithm '\
        'interpolates S(Q,E,T) for any value of parameter T within the range spanned by the {Ti} set.'

    def PyInit(self):
        arrvalidator = StringArrayMandatoryValidator()
        lrg='Input'
        self.declareProperty(StringArrayProperty('Workspaces', values=[], validator=arrvalidator,\
            direction=Direction.Input), doc='list of input workspaces')
        self.declareProperty('LoadErrors', True, direction=Direction.Input,\
            doc='Do we load error data contained in the workspaces?')
        self.declareProperty(FloatArrayProperty('ParameterValues', values=[],\
            validator=FloatArrayMandatoryValidator(),direction=Direction.Input), doc='list of input parameter values')
        self.setPropertyGroup('Workspaces', lrg)
        self.setPropertyGroup('LoadErrors', lrg)
        self.setPropertyGroup('ParameterValues', lrg)

        self.declareProperty('LocalRegression', True, direction=Direction.Input, doc='Perform running local-regression?')
        condition = EnabledWhenProperty("LocalRegression", PropertyCriterion.IsDefault)
        self.declareProperty('RegressionWindow', 6, direction=Direction.Input, doc='window size for the running local-regression')
        self.setPropertySettings("RegressionWindow", condition)
        regtypes = [ 'linear', 'quadratic']
        self.declareProperty('RegressionType', 'quadratic', StringListValidator(regtypes),\
            direction=Direction.Input, doc='type of local-regression; linear and quadratic are available')
        self.setPropertySettings("RegressionType", condition)
        lrg = 'Running Local Regression Options'
        self.setPropertyGroup('LocalRegression', lrg)
        self.setPropertyGroup('RegressionWindow', lrg)
        self.setPropertyGroup('RegressionType', lrg)

        lrg='Output'
        self.declareProperty(FloatArrayProperty('TargetParameters', values=[], ), doc="Parameters to interpolate the structure factor")
        self.declareProperty(StringArrayProperty('OutputWorkspaces', values=[], validator=arrvalidator),\
            doc='list of output workspaces to save the interpolated structure factors')
        self.setPropertyGroup('TargetParameters', lrg)
        self.setPropertyGroup('OutputWorkspaces', lrg)
        self.channelgroup = None

    def areWorkspacesCompatible(self, a, b):
        sizeA = a.blocksize() * a.getNumberHistograms()
        sizeB = b.blocksize() * b.getNumberHistograms()
        return sizeA == sizeB

    def PyExec(self):
    # Check congruence of workspaces
        workspaces = self.getProperty('Workspaces').value
        fvalues = self.getProperty('ParameterValues').value
        if len(workspaces) != len(fvalues):
            mesg = 'Number of Workspaces and ParameterValues should be the same'
      #logger.error(mesg)
            raise IndexError(mesg)
        for workspace in workspaces[1:]:
            if not self.areWorkspacesCompatible(mantid.mtd[workspaces[0]],mantid.mtd[workspace]):
                mesg = 'Workspace {0} incompatible with {1}'.format(workspace, workspaces[0])
                logger.error(mesg)
                raise ValueError(mesg)
    # Load the workspaces into a group of dynamic structure factors
        from dsfinterp.dsf import Dsf
        from dsfinterp.dsfgroup import DsfGroup
        from dsfinterp.channelgroup import ChannelGroup
        dsfgroup = DsfGroup()
        for idsf in range(len(workspaces)):
            dsf = Dsf()
            dsf.Load( mantid.mtd[workspaces[idsf]] )
            if not self.getProperty('LoadErrors').value:
                dsf.errors = None # do not incorporate error data
            dsf.SetFvalue( fvalues[idsf] )
            dsfgroup.InsertDsf(dsf)
    # Create the intepolator if not instantiated before
        if not self.channelgroup:
            self.channelgroup = ChannelGroup()
            self.channelgroup.InitFromDsfGroup(dsfgroup)
            localregression = self.getProperty('LocalRegression').value
            if localregression:
                regressiontype = self.getProperty('RegressionType').value
                windowlength = self.getProperty('RegressionWindow').value
                self.channelgroup.InitializeInterpolator(running_regr_type=regressiontype, windowlength=windowlength)
            else:
                self.channelgroup.InitializeInterpolator(windowlength=0)
    # Invoke the interpolator and generate the output workspaces
        targetfvalues = self.getProperty('TargetParameters').value
        for targetfvalue in targetfvalues:
            if targetfvalue < min(fvalues) or targetfvalue > max(fvalues):
                mesg = 'Target parameters should lie in [{0}, {1}]'.format(min(fvalues),max(fvalues))
                logger.error(mesg)
                raise ValueError(mesg)
        outworkspaces = self.getProperty('OutputWorkspaces').value
        if len(targetfvalues) != len(outworkspaces):
            mesg = 'Number of OutputWorkspaces and TargetParameters should be the same'
            logger.error(mesg)
            raise IndexError(mesg)
        for i in range(len(targetfvalues)):
            dsf = self.channelgroup( targetfvalues[i] )
            outws = mantid.simpleapi.CloneWorkspace( mantid.mtd[workspaces[0]], OutputWorkspace=outworkspaces[i])
            dsf.Save(outws) # overwrite dataY and dataE