Exemple #1
0
def lowTResolution(model, simulated, resolution, convolved, expdata=None,
                   costfile=None, **kwargs):
  """Convolve a simulated S(Q,E) with a resolution file

  Arguments:
    model: beamline model file (background, elastic line, convolution).
    simulated: Nexus file containing S(Q,E) from a simulation
    resolution: Nexus file containing the resolution. This will be used to produce a elastic line.
    convolved: Output Nexus file containing the convolution of the simulated S(Q,E) with the model beamline.
    expdata: Optional, experimental nexus file. If passed, output convolved will be binned as expdata.
    costfile: Optional, file to store cost. If passed, the cost of comparing convolved and expdata will be saved.
    [**kwargs]: extra options for the Mantid algorithms producing S(Q,E). For
            example:
             kwargs={'Fit':{'StartX'=-50.0, 'EndX'=50.0},
                    }

  Returns:
    Groupworkspace containing the convolved S(Q,E)
  """
  from mantid.simpleapi import (LoadNexus, ScaleX, Fit, ExtractSingleSpectrum, RenameWorkspace, AppendSpectra, SaveNexus)
  from mantidhelper.algorithm import findopts
  from mantidhelper.fitalg import parse_results
  from fitalg import parse_results
  algs_opt=locals()['kwargs']
  funcStr=open(model,'r').readline().strip() #read the model string
  wsr=LoadNexus(Filename=resolution,OutputWorkspace='resolutions')
  wse=ScaleX(InputWorkspace=wsr, OutputWorkspace='elastics',factor=-1)
  wss=LoadNexus(Filename=simulated,OutputWorkspace='simulateds')
  wsx=wss # wsx will be our reference to compare convolved in Fit algorithm
  if expdata: 
    wse=LoadNexus(Filename=expdata,OutputWorkspace='expdatas')
    wsx=wse # the reference will be the experimental data
  wsc=None # output convolved spectra
  cost=0
  for iw in range(wss.getNumberHistograms()):
    ExtractSingleSpectrum(wsr,OutputWorkspace='resolution',WorkspaceIndex=iw)
    ExtractSingleSpectrum(wse,OutputWorkspace='elastic',WorkspaceIndex=iw)
    ExtractSingleSpectrum(wss,OutputWorkspace='simulated',WorkspaceIndex=iw)
    ExtractSingleSpectrum(wsx,OutputWorkspace='reference',WorkspaceIndex=iw)
    r=Fit( funcStr, InputWorkspace='reference', CreateOutput='1', Output='fitted',
           MaxIterations=0, **findopts('Fit',algs_opt)
           )
    parsed=parse_results(r)
    cost+=parsed['Cost']
    RenameWorkspace(parsed['Calc'],OutputWorkspace='convolved')
    #ws=parse_results(r)['fitted_Workspace']
    if not wsc:
      wsc='convolveds'
      RenameWorkspace(InputWorkspace='convolved',OutputWorkspace=wsc)
    else:
      AppendSpectra(InputWorkspace1=wsc, InputWorkspace2='convolved', OutputWorkspace=wsc)
  SaveNexus(InputWorkspace=wsc, Filename=convolved)
  if costfile: open(costfile,'w').write(str(cost)+' obj-fn\n')
  return cost
Exemple #2
0
def elasticLineLowTemp(insqe, outres=None):
  '''Produces a resolution function based on the quasi-elastic signal at low temperature
  
  Argument:
    insqe: a Nexus file containing S(Q,E) at low temperature. One spectrum per Q-value.
    [outres]: output Nexus file containing Res(Q,E). Each spectrum is separately applied the Mantid::NormaliseToUnity algorithm.

  Returns:
    mantid workspace containing Res(Q,E)
  '''
  from mantid.simpleapi import (LoadNexus, ExtractSingleSpectrum, NormaliseToUnity, AppendSpectra, ScaleX, SaveNexus)
  wse=LoadNexus(Filename=insqe,OutputWorkspace='insqe')
  for iw in range(wse.getNumberHistograms()):
    iname='insqe'+str(iw)
    ExtractSingleSpectrum(wse,OutputWorkspace=iname,WorkspaceIndex=iw)
    NormaliseToUnity(InputWorkspace=iname, OutputWorkspace=iname)
    if iw:
      AppendSpectra(InputWorkspace1='insqe0', InputWorkspace2=iname, OutputWorkspace='insqe0')
  wsr=ScaleX(InputWorkspace='insqe0', OutputWorkspace='resolution',factor=-1)
  if outres:
    SaveNexus(InputWorkspace='resolution', Filename=outres)
  return wsr
 def nominal_solid_angle(self, name):
     """
     Generate an isotropic solid angle
     :param name: Name of the output workspace
     :return: reference to solid angle workspace
     """
     ws = LoadNexus(Filename=self._solid_angle_ws_, OutputWorkspace=name)
     ClearMaskFlag(ws)
     MaskDetectors(ws, MaskedWorkspace=self._t_mask)
     for i in range(ws.getNumberHistograms()):
         ws.dataY(i)[0] = 0.0 if ws.getDetector(i).isMasked() else 1.0
         ws.setX(i, self._momentum_range)
     return ws
Exemple #4
0
def modelB_EC_C(model, resolution, convolved, qvalues, assembled, expdata=None, costfile=None):
  """Assemble the Background, Elastic line and Convolution of the resolution with the simulated S(Q,E)
  This is a hard-coded model consisting of a linear background, and elastic line, and a convolution:
    b0+b1*E  +  +EC(Q)*e0*exp(-e1*Q^2)*Elastic(E)  +  c0*Resolution(E)xSimulated(Q,E)
    We load Resolution(E)xSimulated(Q,E) as Convolved(Q,E)
    EC(Q) is a fit to the Q-dependence of the integrated intensity of the empty can
    EC(Q) = 2.174495971 - 2.065826056*Q + 0.845367259*Q^2
    
  Arguments:
    model: beamline model file is a single line, e.g,
           b0=1.3211; b1=0.00 e0=0.99; e1=1.9; c0=2.3
    resolution: Nexus file containing the resolution. This will be used to produce a elastic line.
    convolved: Nexus file containing the convolution of the simulated S(Q,E) with the resolution.
    qvalues: single-column file containing list of Q-values
    assembled: output Nexus file containing the assembled S(Q,E) of the beamline model and the simulated S(Q,E)
    expdata: Optional, experimental nexus file. If passed, output convolved will be binned as expdata.
    costfile: Optional, file to store cost. If passed, the cost of comparing convolved and expdata will be saved.

  Returns:
    workspace containing the assembled S(Q,E)
  """
  import numpy
  from mantid.simpleapi import (LoadNexus, ScaleX, ConvertToPointData, SaveNexus, DakotaChiSquared)
  EC = lambda Q: 2.174495971 - 2.065826056*Q + 0.845367259*Q*Q
  Q=[float(q) for q in open(qvalues,'r').read().split('\n')]
  p={}
  for pair in open(model,'r').readline().split(';'):
    key,val=pair.split('=')
    p[key.strip()]=float(val.strip())
  wsr=LoadNexus(Filename=resolution,OutputWorkspace='resolution')
  wsr=ConvertToPointData(wsr)
  E=wsr.readX(0)
  wse=ScaleX(InputWorkspace=wsr, OutputWorkspace='elastic',factor=-1) # elastic line
  wsc=LoadNexus(Filename=convolved,OutputWorkspace='convolved')
  for i in range(wsc.getNumberHistograms()):
    elastic=wse.readY(i) # elastic spectrum at a given Q
    convolved=wsc.readY(i) # convolved spectrum at a given Q
    wsc.setY(i, (p['b0']+p['b1']*E) + (EC(Q[i])*p['e0']*numpy.exp(-p['e1']*Q[i])*elastic) + (p['c0']*convolved) ) # overwrite spectrum
  SaveNexus(InputWorkspace=wsc, Filename=assembled)
  if expdata and costfile:
    DakotaChiSquared(DataFile=assembled,CalculatedFile=expdata,OutputFile=costfile)
  return wsc
Exemple #5
0
  p.add_argument('-explain', action='store_true', help='print message explaining the arguments to pass for the particular service')
  if set(['-h', '-help', '--help']).intersection(set(sys.argv)): args=p.parse_args() # check if help message is requested

  if 'itp_simple' in sys.argv:
    p.description='For all spectra of a mantid workspace, shift a small amount and interpolate through Mantid::Rebin' # update help message
    for action in p._actions:
      if action.dest=='service': action.help='substitue "service" with "itp_simple"' # update help message
    p.add_argument('--assembled',help='name of the Nexus file containing assembled S(Q,E) model')
    p.add_argument('--model', help='file name for the model beamline string. Should contain "eshift=X", with X being the current value of the shift')
    p.add_argument('--interpolated',help='name of the Nexus file to output the interpolated S(Q,E) model')
    p.add_argument('--expdata',help='optional, experimental nexus file. If passed, output convolved will be binned as expdata.')
    p.add_argument('--costfile',help='optional, file to store cost. If passed, the cost of comparing convolved and expdata will be saved.')
    if '-explain' in sys.argv:
      p.parse_args(args=('-h',))
    else:
      args=p.parse_args()
      from mantid.simpleapi import (LoadNexus, SaveNexus, DakotaChiSquared)
      #trace()
      eshift=float(re.search('eshift\s*=\s*(-*\d+\.*\d+[e|E]*-*\d*)', open(args.model,'r').read()).groups()[0])
      ws=LoadNexus(Filename=args.assembled)
      ws=itp_simple(ws, eshift)
      SaveNexus(InputWorkspace=ws.getName(),Filename=args.interpolated)
      if args.expdata and args.costfile:
        chisq,wR=DakotaChiSquared(DataFile=args.expdata,CalculatedFile=args.interpolated,OutputFile=args.costfile,ResidualsWorkspace='wR')
        f=open(args.costfile,'w')
        for i in range(wR.getNumberHistograms()):
            Ry=wR.readY(i)
            for j in range(len(Ry)):
                f.write(str(Ry[j])+" least_squares_term\n")

Exemple #6
0
from mantid.simpleapi import LoadNexus

for run in range(6530,6534):
    print('HB2C_{}.nxs'.format(run))
    ws = LoadNexus('/HFIR/HB2C/IPTS-7776/shared/autoreduce/HB2C_{}.nxs'.format(run))
Exemple #7
0
def convolution(simulated, resolution, expdata, convolved, dak=None, norm2one=False):
  """Convolve a simulated S(Q,E) with a resolution file

  Arguments:
    simulated: Nexus file containing S(Q,E) from a simulation
    resolution: Nexus file containing the resolution. This will be used to produce a elastic line.
    convolved: Output Nexus file containing the convolution of the simulated S(Q,E) with the model beamline.
    expdata: Optional, experimental nexus file. Convolved will be binned as expdata. 
  Returns:
    workspace for the convolution
  """
  from mantid.simpleapi import (LoadNexus, Rebin, ConvertToHistogram, NormaliseToUnity, SaveNexus, SaveAscii, AddSampleLog)
  wss=LoadNexus(Filename=simulated,OutputWorkspace='simulated')
  width=wss.readX(0)[1]-wss.readX(0)[0] # rebin resolution as simulated
  wsr=LoadNexus(Filename=resolution,OutputWorkspace='resolution')

  #symmetrize the domain of the resolution function. Otherwise the
  #convolution results in a function with its peak shifted from the origin
  min=wsr.readX(0)[0]
  max=wsr.readX(0)[-1]
  delta=min+max
  if delta<0:
    wsr=Rebin(wsr, Params=(-max,width,max))
  elif delta>0:
    wsr=Rebin(wsr, Params=(min,width,-min))
  else:
    wsr=Rebin(wsr, Params=(min,width,max))

  # convolve now, overwriting simulateds
  for i in range(wss.getNumberHistograms()):
    v=wsr.readY(i)
    w=wss.readY(i)
    x=camm_convolve(w,v,mode='same')
    wss.setY(i,x)
    
  wse=LoadNexus(Filename=expdata,OutputWorkspace='expdata')
  width=wse.readX(0)[1]-wse.readX(0)[0] # rebin simulated as expdata
  Rebin(InputWorkspace='simulated', Params=(wse.readX(0)[0],width,wse.readX(0)[-1]), OutputWorkspace='convolved')
  ConvertToHistogram(InputWorkspace='convolved', OutputWorkspace='convolved') # remember that output from sassena are point-data
  if norm2one:
    wsc=NormaliseToUnity(InputWorkspace='convolved', OutputWorkspace='convolved')
  AddSampleLog(Workspace='convolved',LogName='NormaliseToUnity',LogText=str(float(norm2one)),LogType='Number')
  if dak:
    dakota_vals = getParams(dak) # read in Dakota params file
    AddSampleLog(Workspace='convolved',LogName='FF1',LogText=str(dakota_vals["FF1"]),LogType='Number')
  from mantid.simpleapi import mtd
  SaveNexus(InputWorkspace='convolved', Filename=convolved)
  return
    def PyExec(self):
        # remove possible old temp workspaces
        [
            DeleteWorkspace(ws) for ws in self.temp_workspace_list
            if mtd.doesExist(ws)
        ]

        _background = bool(self.getProperty("Background").value)
        _load_inst = bool(self.getProperty("LoadInstrument").value)
        _detcal = bool(self.getProperty("DetCal").value)
        _masking = bool(self.getProperty("MaskFile").value)
        _outWS_name = self.getPropertyValue("OutputWorkspace")

        UBList = self._generate_UBList()

        dim0_min, dim0_max, dim0_bins = self.getProperty('BinningDim0').value
        dim1_min, dim1_max, dim1_bins = self.getProperty('BinningDim1').value
        dim2_min, dim2_max, dim2_bins = self.getProperty('BinningDim2').value
        MinValues = "{},{},{}".format(dim0_min, dim1_min, dim2_min)
        MaxValues = "{},{},{}".format(dim0_max, dim1_max, dim2_max)
        AlignedDim0 = ",{},{},{}".format(dim0_min, dim0_max, int(dim0_bins))
        AlignedDim1 = ",{},{},{}".format(dim1_min, dim1_max, int(dim1_bins))
        AlignedDim2 = ",{},{},{}".format(dim2_min, dim2_max, int(dim2_bins))

        LoadNexus(Filename=self.getProperty("SolidAngle").value,
                  OutputWorkspace='__sa')
        LoadNexus(Filename=self.getProperty("Flux").value,
                  OutputWorkspace='__flux')

        if _masking:
            LoadMask(Instrument=mtd['__sa'].getInstrument().getName(),
                     InputFile=self.getProperty("MaskFile").value,
                     OutputWorkspace='__mask')
            MaskDetectors(Workspace='__sa', MaskedWorkspace='__mask')
            DeleteWorkspace('__mask')

        XMin = mtd['__sa'].getXDimension().getMinimum()
        XMax = mtd['__sa'].getXDimension().getMaximum()

        newXMin = self.getProperty("MomentumMin").value
        newXMax = self.getProperty("MomentumMax").value
        if newXMin != Property.EMPTY_DBL or newXMax != Property.EMPTY_DBL:
            if newXMin != Property.EMPTY_DBL:
                XMin = max(XMin, newXMin)
            if newXMax != Property.EMPTY_DBL:
                XMax = min(XMax, newXMax)
            logger.notice("Using momentum range {} to {} A^-1".format(
                XMin, XMax))
            CropWorkspace(InputWorkspace='__flux',
                          OutputWorkspace='__flux',
                          XMin=XMin,
                          XMax=XMax)
            for spectrumNumber in range(mtd['__flux'].getNumberHistograms()):
                Y = mtd['__flux'].readY(spectrumNumber)
                mtd['__flux'].setY(spectrumNumber,
                                   (Y - Y.min()) / (Y.max() - Y.min()))

        if _background:
            Load(Filename=self.getProperty("Background").value,
                 OutputWorkspace='__bkg',
                 FilterByTofMin=self.getProperty("FilterByTofMin").value,
                 FilterByTofMax=self.getProperty("FilterByTofMax").value)
            if _load_inst:
                LoadInstrument(
                    Workspace='__bkg',
                    Filename=self.getProperty("LoadInstrument").value,
                    RewriteSpectraMap=False)
            if _detcal:
                LoadIsawDetCal(InputWorkspace='__bkg',
                               Filename=self.getProperty("DetCal").value)
            MaskDetectors(Workspace='__bkg', MaskedWorkspace='__sa')
            ConvertUnits(InputWorkspace='__bkg',
                         OutputWorkspace='__bkg',
                         Target='Momentum')
            CropWorkspace(InputWorkspace='__bkg',
                          OutputWorkspace='__bkg',
                          XMin=XMin,
                          XMax=XMax)

        progress = Progress(
            self, 0.0, 1.0,
            len(UBList) * len(self.getProperty("Filename").value))

        for run in self.getProperty("Filename").value:
            logger.notice("Working on " + run)

            Load(Filename=run,
                 OutputWorkspace='__run',
                 FilterByTofMin=self.getProperty("FilterByTofMin").value,
                 FilterByTofMax=self.getProperty("FilterByTofMax").value)
            if _load_inst:
                LoadInstrument(
                    Workspace='__run',
                    Filename=self.getProperty("LoadInstrument").value,
                    RewriteSpectraMap=False)
            if _detcal:
                LoadIsawDetCal(InputWorkspace='__run',
                               Filename=self.getProperty("DetCal").value)
            MaskDetectors(Workspace='__run', MaskedWorkspace='__sa')
            ConvertUnits(InputWorkspace='__run',
                         OutputWorkspace='__run',
                         Target='Momentum')
            CropWorkspace(InputWorkspace='__run',
                          OutputWorkspace='__run',
                          XMin=XMin,
                          XMax=XMax)

            if self.getProperty('SetGoniometer').value:
                SetGoniometer(
                    Workspace='__run',
                    Goniometers=self.getProperty('Goniometers').value,
                    Axis0=self.getProperty('Axis0').value,
                    Axis1=self.getProperty('Axis1').value,
                    Axis2=self.getProperty('Axis2').value)

            # Set background Goniometer to be the same as data
            if _background:
                mtd['__bkg'].run().getGoniometer().setR(
                    mtd['__run'].run().getGoniometer().getR())

            for ub in UBList:
                SetUB(Workspace='__run', UB=ub)
                ConvertToMD(InputWorkspace='__run',
                            OutputWorkspace='__md',
                            QDimensions='Q3D',
                            dEAnalysisMode='Elastic',
                            Q3DFrames='HKL',
                            QConversionScales='HKL',
                            Uproj=self.getProperty('Uproj').value,
                            Vproj=self.getProperty('Vproj').value,
                            Wproj=self.getProperty('wproj').value,
                            MinValues=MinValues,
                            MaxValues=MaxValues)
                MDNormSCD(
                    InputWorkspace=mtd['__md'],
                    FluxWorkspace='__flux',
                    SolidAngleWorkspace='__sa',
                    OutputWorkspace='__data',
                    SkipSafetyCheck=True,
                    TemporaryDataWorkspace='__data'
                    if mtd.doesExist('__data') else None,
                    OutputNormalizationWorkspace='__norm',
                    TemporaryNormalizationWorkspace='__norm'
                    if mtd.doesExist('__norm') else None,
                    AlignedDim0=mtd['__md'].getDimension(0).name + AlignedDim0,
                    AlignedDim1=mtd['__md'].getDimension(1).name + AlignedDim1,
                    AlignedDim2=mtd['__md'].getDimension(2).name + AlignedDim2)
                DeleteWorkspace('__md')

                if _background:
                    SetUB(Workspace='__bkg', UB=ub)
                    ConvertToMD(InputWorkspace='__bkg',
                                OutputWorkspace='__bkg_md',
                                QDimensions='Q3D',
                                dEAnalysisMode='Elastic',
                                Q3DFrames='HKL',
                                QConversionScales='HKL',
                                Uproj=self.getProperty('Uproj').value,
                                Vproj=self.getProperty('Vproj').value,
                                Wproj=self.getProperty('Wproj').value,
                                MinValues=MinValues,
                                MaxValues=MaxValues)
                    MDNormSCD(
                        InputWorkspace='__bkg_md',
                        FluxWorkspace='__flux',
                        SolidAngleWorkspace='__sa',
                        SkipSafetyCheck=True,
                        OutputWorkspace='__bkg_data',
                        TemporaryDataWorkspace='__bkg_data'
                        if mtd.doesExist('__bkg_data') else None,
                        OutputNormalizationWorkspace='__bkg_norm',
                        TemporaryNormalizationWorkspace='__bkg_norm'
                        if mtd.doesExist('__bkg_norm') else None,
                        AlignedDim0=mtd['__bkg_md'].getDimension(0).name +
                        AlignedDim0,
                        AlignedDim1=mtd['__bkg_md'].getDimension(1).name +
                        AlignedDim1,
                        AlignedDim2=mtd['__bkg_md'].getDimension(2).name +
                        AlignedDim2)
                    DeleteWorkspace('__bkg_md')
                progress.report()
            DeleteWorkspace('__run')

        if _background:
            # outWS = data / norm - bkg_data / bkg_norm * BackgroundScale
            DivideMD(LHSWorkspace='__data',
                     RHSWorkspace='__norm',
                     OutputWorkspace=_outWS_name + '_normalizedData')
            DivideMD(LHSWorkspace='__bkg_data',
                     RHSWorkspace='__bkg_norm',
                     OutputWorkspace=_outWS_name + '_normalizedBackground')
            CreateSingleValuedWorkspace(
                OutputWorkspace='__scale',
                DataValue=self.getProperty('BackgroundScale').value)
            MultiplyMD(LHSWorkspace=_outWS_name + '_normalizedBackground',
                       RHSWorkspace='__scale',
                       OutputWorkspace='__scaled_background')
            DeleteWorkspace('__scale')
            MinusMD(LHSWorkspace=_outWS_name + '_normalizedData',
                    RHSWorkspace='__scaled_background',
                    OutputWorkspace=_outWS_name)
            if self.getProperty('KeepTemporaryWorkspaces').value:
                RenameWorkspaces(InputWorkspaces=[
                    '__data', '__norm', '__bkg_data', '__bkg_norm'
                ],
                                 WorkspaceNames=[
                                     _outWS_name + '_data',
                                     _outWS_name + '_normalization',
                                     _outWS_name + '_background_data',
                                     _outWS_name + '_background_normalization'
                                 ])
        else:
            # outWS = data / norm
            DivideMD(LHSWorkspace='__data',
                     RHSWorkspace='__norm',
                     OutputWorkspace=_outWS_name)
            if self.getProperty('KeepTemporaryWorkspaces').value:
                RenameWorkspaces(InputWorkspaces=['__data', '__norm'],
                                 WorkspaceNames=[
                                     _outWS_name + '_data',
                                     _outWS_name + '_normalization'
                                 ])

        self.setProperty("OutputWorkspace", mtd[_outWS_name])

        # remove temp workspaces
        [
            DeleteWorkspace(ws) for ws in self.temp_workspace_list
            if mtd.doesExist(ws)
        ]
Exemple #9
0
def modelB_freeE_C(modeltpl, elastic, convolved, expdata, initparfile=None):
  """Estimate initial beamline parameters for the modelB_freeE_C
  This is a hard-coded model consisting of a linear background, and elastic line, and a convolution:
    b0+b1*E  +  +e0(Q)*Elastic(E)  +  c0*Resolution(E)xSimulated(Q,E)
    We load Resolution(E)xSimulated(Q,E) as Convolved(Q,E)
    e0(Q) are a set of fitting parameters, one for each Q
  Initial values are estimated as follows:
  b0:0.0
  b1:0.0
  Evaluation of the model at E=0:
    e0*elastic(Q,0) + c0*convolved(Q,0) ~ experiment(Q,0) {Eq.1},
    with 'convolved' the convolution of the experimental resolution and the Fourier transform
    of the simulated intermediate structure factor
  For the lowest Q, we assume contributions fromt the elastic line and simuation are equal. Thus:
    c0*convolved(Qmin,0) ~ 1/2*experiment(Qmin,0) ---> provides estimation for c0
    e0(Qmin)*elastic(Qmin,0) ~ 1/2*experiment(Qmin,0) ---> provides estimation for e0
  For the remaining Q, we use {Eq.1} substituting the c0 found above.
  Finally, eshift:0.0
  
  Arguments:
    model: beamline template model file (xml format)
    elastic: Nexus file containing the elastic line
    convolved: Nexus file containing convolution of the resolution and simulated structure factor
    expdata: Nexus file containing the experimental data
    [initparfile]: Output the initial parameters as a string in file with name initparfile

  Returns:
    initparms: string with initial values for the parameters
  """
  from simulation.src.molmec.ffupdate.ff_update import loadFFtpl,updateTemplate
  from mantid.simpleapi import LoadNexus

  wse=LoadNexus(Filename=elastic,OutputWorkspace='elastic')
  wsc=LoadNexus(Filename=convolved,OutputWorkspace='convolved')
  wsx=LoadNexus(Filename=expdata,OutputWorkspace='experiment')

  parl,template=loadFFtpl(modeltpl)
  pard={}
  for par in parl: pard[par._name]=par

  nhist=wsx.getNumberHistograms()
  le=len(wsx.readX(0))
  for ws in wse,wsc:
    if ws.getNumberHistograms()!=nhist or len(ws.readX(0))!=le:
      error_message='%s %d histograms of length %d do not conform to those of experiment'%(ws.getName(),ws.getNumberHistograms(),len(ws.readX(0)))
      ws.getName()+' histograms do not conform to those of experiment'
      g_log.error(error_message)
      raise StandardError(error_message)

  pard['b0'].setValue(1e-10) # needs to be positive
  pard['b1'].setValue(0.)
  ezero=le/2 # assume E=0 in the middle of the histogram span
  pard['c0'].setValue(0.5*wsx.readY(0)[ezero]/wsc.readY(0)[ezero])
  pard['e0.0'].setValue(0.5*wsx.readY(0)[ezero]/wse.readY(0)[ezero])
  trace()
  for ihist in range(1,nhist):
    pard['e0.'+str(ihist)].setValue((wsx.readY(ihist)[ezero] - pard['c0']._value*wsc.readY(ihist)[ezero]) / wse.readY(ihist)[ezero])
  pard['eshift'].setValue(0.)
  template=updateTemplate(template,parl)

  if initparfile: open(initparfile,'w').write(template)
  return template
Exemple #10
0
def modelB_freeE_C(model, resolution, convolved, assembled, expdata=None, costfile=None, derivdata=None, derivexclude=[], doshift=None):
  """Assemble the Background, Elastic line and Convolution of the resolution with the simulated S(Q,E)
  This is a hard-coded model consisting of a linear background, and elastic line, and a convolution:
    b0+b1*E  +  +e0(Q)*Elastic(E)  +  c0*Resolution(E)xSimulated(Q,E)
    We load Resolution(E)xSimulated(Q,E) as Convolved(Q,E)
    e0(Q) are a set of fitting parameters, one for each Q
    
  Arguments:
    model: beamline model file is a single line, e.g,
           b0=1.3211; b1=0.00; e0.0=0.99; e0.1=0.99; e0.2=0.99;...e0.N=0.99; e1=1.9; c0=2.3
    resolution: Nexus file containing the resolution. This will be used to produce a elastic line.
    convolved: Nexus file containing the convolution of the simulated S(Q,E) with the resolution.
    assembled: output Nexus file containing the assembled S(Q,E) of the beamline model and the simulated S(Q,E)
    expdata: Optional, experimental nexus file. If passed, output convolved will be binned as expdata.
    costfile: Optional, file to store cost. If passed, residuals and (optionally) partial derivatives will be stored
    derivdata: Optional, perform analytic derivatives (store in costfile if provided)
    derivexclude: list of fitting parameters for which partial derivatives will not be computed
    doshift: Optional, perform the shift of the model function

  Returns:
    wsm: workspace containing the assembled S(Q,E)
    gradients: dictionary of partial derivatives with respect to model parameters
  """
  import numpy
  from copy import copy,deepcopy
  from mantid.simpleapi import (LoadNexus, ScaleX, ConvertToPointData, SaveNexus, DakotaChiSquared, AddSampleLog)
  from math import sqrt

  def shiftalongX(*kargs,**kwargs):
    """ Function to do the shift along the E-axis. By default, does nothing """
    pass
  import interpX
  if doshift: # replace the dummy function with the real thing
    if doshift in dir(interpX):
      shiftalongX=getattr(__import__('interpX'), doshift)
    else:
      shiftalongX = getattr(__import__('interpX'), 'itp_simple')

  def computemodel(p,wse,wsc):
    """Assemble the model
    Arguments
      p: dictionary with parameter values
      wse: Mantid workspace holding the elastic line
      wsc: Mantid workspace holding the convolution of the resolution and the simulation
    Returns:
      wsm: Mantid workspace holding the resulting model
    """
    from mantid.simpleapi import CloneWorkspace
    wsm=CloneWorkspace(wsc)
    E=wse.readX(0) # energy values, bins boundary values
    Eshifted=(E[1:]+E[:-1])/2 # energy values, center bin values
    for i in range(wsc.getNumberHistograms()):
      elastic=wse.readY(i)   # elastic spectrum at a given Q
      convolved=wsc.readY(i) # convolved spectrum at a given Q
      wsm.setY(i, p['b0']+p['b1']*Eshifted + p['e0.'+str(i)]*elastic + p['c0']*convolved) # overwrite spectrum
    return wsm

  # init list of parameters names for which analytical derivative exists, same order as in the input model file
  derivparnames=[] # filled only if derivdata different than None
  p={}
  for pair in open(model,'r').readline().split(';'):
    key,val=[x.strip() for x in pair.split('=')]
    if derivdata and key not in derivexclude: derivparnames.append(key)
    p[key]=float(val)

  # read various inputs
  wsr=LoadNexus(Filename=resolution,OutputWorkspace='resolution')
  wse=ScaleX(InputWorkspace=wsr, OutputWorkspace='elastic',factor=-1) # elastic line
  wsc=LoadNexus(Filename=convolved,OutputWorkspace='convolved')
  E=wsr.readX(0) # energy values, bins boundary values
  de=E[1]-E[0]   # assume all bins have same bin width
  Eshifted=(E[1:]+E[:-1])/2 # energy values, center bin values
  nhist=wsc.getNumberHistograms()
  nrsl=len(Eshifted)*nhist # number of residuals

  # calculate partial numerical derivative with respect to eshift 
  gradients={}
  if 'eshift' in derivparnames: 
    wsm=computemodel(p,wse,wsc)
    eshiftderiv=(shiftalongX(wsm,p['eshift']+0.5*de,newWorkspace='wsplus') - shiftalongX(wsm,p['eshift']-0.5*de,newWorkspace='wsminus')) / de # forward-backward difference with a 0.5*de step
    gradients['eshift']=numpy.zeros(0)
    for i in range(eshiftderiv.getNumberHistograms()): gradients['eshift'] = numpy.concatenate([gradients['eshift'], eshiftderiv.readY(i)])

  # do eshift of component workspaces
  if doshift: Eshifted-=p['eshift']
  wse=shiftalongX(wse,p['eshift']) # shift the spectrum, does nothing if shiftalongX is the dummy function
  wsc=shiftalongX(wsc,p['eshift']) # shift the spectrum, does nothing if shiftalongX is the dummy function

  # find difference in convolutions with FF1 changed
  if 'FF1' not in derivexclude:
    derivparnames.append('FF1')
    # difference in FF1 workspaces
    convolvedf=convolved.replace('.nxs','_1.nxs')
    wscf=LoadNexus(Filename=convolvedf,OutputWorkspace='convolvedf')
    convolvedb=convolved.replace('.nxs','_0.nxs')
    wscb=LoadNexus(Filename=convolvedb,OutputWorkspace='convolvedb')
    wksp_diff=wscf-wscb
 
  # calculate analytic partial derivatives with respect to the fit parameters
  if derivparnames:
    gradients['b0']=numpy.ones(nrsl)
    gradients['b1']=numpy.zeros(0)
    gradients['c0']=numpy.zeros(0)
    gradients['FF1']=numpy.zeros(0)
    for i in range(nhist):
      gradients['b1'] = numpy.concatenate([gradients['b1'], Eshifted])
      gradients['c0'] = numpy.concatenate([gradients['c0'], wsc.readY(i)])
      if 'FF1' not in derivexclude:
        gradients['FF1'] = numpy.concatenate([gradients['FF1'], wksp_diff.readY(i)])
      gradients['e0.'+str(i)]=numpy.zeros(0)
      for j in range(nhist):
        if i==j: 
          gradients['e0.'+str(i)] = numpy.concatenate([gradients['e0.'+str(i)], wse.readY(i)])
        else:
          gradients['e0.'+str(i)] = numpy.concatenate([gradients['e0.'+str(i)], numpy.zeros(len(Eshifted))])

  if 'FF1' not in derivexclude:
    FF1_f=wscf.getRun().getLogData('FF1').value
    FF1_b=wscb.getRun().getLogData('FF1').value
    gradients['FF1'] *= p['c0']/(FF1_f-FF1_b)

  # save model to file
  wsm=computemodel(p,wse,wsc)
  # add all parameters to assembled file
  for pair in open(model,'r').readline().split(';'):
    key,val=[x.strip() for x in pair.split('=')]
    AddSampleLog(Workspace=wsm,LogName=key,LogText=str(p[key]),LogType='Number')
    print key, "=",  p[key]
  print "FF1 =", wsm.getRun().getLogData('FF1').value

  SaveNexus(InputWorkspace=wsm, Filename=assembled)

  # save residuals and partial derivatives
  buf=''
  if expdata and costfile:
    wex=LoadNexus(Filename=expdata,OutputWorkspace='experiment')
    chisq,wR=DakotaChiSquared(DataFile=expdata,CalculatedFile=assembled,OutputFile=costfile,ResidualsWorkspace='wR')
    Xe=numpy.zeros(0) # list of errors for each residual
    for i in range(nhist):
      Xe = numpy.concatenate([Xe, wex.readE(i)])
      Ry=wR.readY(i)
      for j in range(len(Ry)):
        buf+=str(Ry[j])+" least_sq_term_"+str(i*len(Ry)+j+1)+"\n"
    for parname in derivparnames: gradients[parname]/=numpy.where(Xe>0,Xe,1) # divide by experimental error (with non-positive elements replaced by one)
    if derivparnames:
      for i in range(nrsl):
        buf+="["
        for parname in derivparnames: buf+=" %.10e"%(-gradients[parname][i])
        buf+=" ]\n"
    open(costfile,'w').write(buf)

  AddSampleLog(Workspace=wsm,LogName="chisq",LogText=str(chisq),LogType='Number')
  norm_chisq=chisq/(len(Ry)-len(derivparnames))
  print costfile, " R = ", sqrt(norm_chisq)
  AddSampleLog(Workspace=wsm,LogName="norm_chisq",LogText=str(norm_chisq),LogType='Number')
  AddSampleLog(Workspace=wsm,LogName="norm_chi",LogText=str(sqrt(norm_chisq)),LogType='Number')
  SaveNexus(InputWorkspace=wsm, Filename=assembled)

  return {'model':wsm, 'gradients':gradients}
Exemple #11
0
def handle_saving_event_workspace_when_saving_as_histogram(
        binning, runs, def_type, inst):
    ws_in_monitor = mtd[ADD_FILES_SUM_TEMPORARY_MONITORS]
    if binning == 'Monitors':
        mon_x = ws_in_monitor.dataX(0)
        binning = str(mon_x[0])
        bin_gap = mon_x[1] - mon_x[0]
        binning = binning + "," + str(bin_gap)
        for j in range(2, len(mon_x)):
            next_bin_gap = mon_x[j] - mon_x[j - 1]
            if next_bin_gap != bin_gap:
                bin_gap = next_bin_gap
                binning = binning + "," + str(
                    mon_x[j - 1]) + "," + str(bin_gap)
        binning = binning + "," + str(mon_x[len(mon_x) - 1])

    sanslog.notice(binning)
    Rebin(InputWorkspace=ADD_FILES_SUM_TEMPORARY,
          OutputWorkspace='AddFilesSumTemporary_Rebin',
          Params=binning,
          PreserveEvents=False)

    # loading the nexus file using LoadNexus is necessary because it has some metadata
    # that is not in LoadEventNexus. This must be fixed.
    filename, ext = _make_filename(runs[0], def_type, inst)
    workspace_type = get_workspace_type(filename)
    if workspace_type is WorkspaceType.MultiperiodEvent:
        # If we are dealing with multi-period event workspaces then there is no way of getting any other
        # sample log information hence we use make a copy of the monitor workspace and use that instead
        # of the reloading the first file again
        CloneWorkspace(InputWorkspace=ADD_FILES_SUM_TEMPORARY_MONITORS,
                       OutputWorkspace=ADD_FILES_SUM_TEMPORARY)
    else:
        LoadNexus(Filename=filename,
                  OutputWorkspace=ADD_FILES_SUM_TEMPORARY,
                  SpectrumMax=ws_in_monitor.getNumberHistograms())
    # User may have selected a binning which is different from the default
    Rebin(InputWorkspace=ADD_FILES_SUM_TEMPORARY,
          OutputWorkspace=ADD_FILES_SUM_TEMPORARY,
          Params=binning)
    # For now the monitor binning must be the same as the detector binning
    # since otherwise both cannot exist in the same output histogram file
    Rebin(InputWorkspace=ADD_FILES_SUM_TEMPORARY_MONITORS,
          OutputWorkspace=ADD_FILES_SUM_TEMPORARY_MONITORS,
          Params=binning)

    ws_in_monitor = mtd[ADD_FILES_SUM_TEMPORARY_MONITORS]
    wsOut = mtd[ADD_FILES_SUM_TEMPORARY]
    ws_in_detector = mtd['AddFilesSumTemporary_Rebin']

    # We loose added sample log information since we reload a single run workspace
    # and conjoin with the added workspace. In order to preserve some added sample
    # logs we need to transfer them at this point
    transfer_special_sample_logs(from_ws=ws_in_detector, to_ws=wsOut)

    mon_n = ws_in_monitor.getNumberHistograms()
    for i in range(mon_n):
        wsOut.setY(i, ws_in_monitor.dataY(i))
        wsOut.setE(i, ws_in_monitor.dataE(i))
    ConjoinWorkspaces(wsOut, ws_in_detector, CheckOverlapping=True)

    if 'AddFilesSumTemporary_Rebin' in mtd:
        DeleteWorkspace('AddFilesSumTemporary_Rebin')
Exemple #12
0
from mantid.simpleapi import LoadNexus
import numpy as np
import h5py

run = 6558

van = LoadNexus(
    '/HFIR/HB2C/IPTS-7776/shared/autoreduce/HB2C_{}.nxs'.format(run))

y = van.extractY()
e = van.extractY()
s2 = van.run().getLogData('HB2C:Mot:s2.RBV').timeAverageValue()
detz = van.run().getLogData('HB2C:Mot:detz.RBV').timeAverageValue()
s1 = van.run().getLogData('HB2C:Mot:s1').timeAverageValue()
w = 1.488

with h5py.File('HB2C_{}.nxs'.format(run), 'w') as f:
    data = f.create_group("data")
    data.attrs['instrument'] = 'WAND'
    data.attrs['wavelength'] = w
    data.attrs['s1'] = s1
    data.attrs['s2'] = s2
    data.attrs['detz'] = detz
    dset = data.create_dataset("y", data=y)
    dset = data.create_dataset("e", data=e)