From 8452054c83cd5f485495b2c2fec8d921621ecd67 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Wed, 23 Oct 2013 11:36:50 +0100 Subject: [PATCH 001/403] Refs #8176 Add algorithm to Mantid. --- .../IndirectTransmission.py | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py new file mode 100644 index 000000000000..ed43ba9e69cd --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -0,0 +1,104 @@ +"""*WIKI* + +Calculates the scattering & transmission for Indirect Geometry spectrometers. The sample chemical formula is input for the SetSampleMaterial algorithm to calculate the cross-sections. +The instrument analyser reflection is selected to obtain the wavelength to calculate the absorption cross-section. The sample number density & thickness is input to then calculate the percentage scattering & transmission. + +*WIKI*""" + +from mantid.simpleapi import * +from mantid.api import PythonAlgorithm, AlgorithmFactory +from mantid.kernel import StringListValidator, StringMandatoryValidator +from mantid import config +from IndirectCommon import StartTime, EndTime +import os.path, math + +class IndirectTransmission(PythonAlgorithm): + + def category(self): + return "Workflow\\MIDAS;PythonAlgorithms" + + def PyInit(self): + self.declareProperty(name='Instrument',defaultValue='IRIS',validator=StringListValidator(['IRIS','OSIRIS']), doc='Instrument') + self.declareProperty(name='Analyser',defaultValue='graphite',validator=StringListValidator(['graphite','fmica']), doc='Analyser') + self.declareProperty(name='Reflection',defaultValue='002',validator=StringListValidator(['002','004']), doc='Reflection') + self.declareProperty(name='Chemical Formula',defaultValue='',validator=StringMandatoryValidator(), doc='Sample chemical formula') + self.declareProperty(name='Number Density', defaultValue=0.1, doc='Number denisty. Default=0.1') + self.declareProperty(name='Thickness', defaultValue=0.1, doc='Sample thickness. Default=0.1') + + def PyExec(self): + + StartTime('IndirectTransmission') + + instrumentName = self.getPropertyValue('Instrument') + analyser = self.getPropertyValue('Analyser') + reflection = self.getPropertyValue('Reflection') + formula = self.getPropertyValue('Chemical Formula') + density = self.getPropertyValue('Number Density') + thickness = self.getPropertyValue('Thickness') + + #Load instrument defintion file + idfDir = config['instrumentDefinition.directory'] + idf = idfDir + instrumentName + '_Definition.xml' + workspace = '__empty_'+instrumentName + LoadEmptyInstrument(OutputWorkspace=workspace, Filename=idf) + + #Load instrument parameter file + nameStem = instrumentName + '_' + analyser + '_' + reflection + ipf = idfDir + nameStem + '_Parameters.xml' + LoadParameterFile(Workspace=workspace, Filename=ipf) + + #Get efixed value + instrument = mtd[workspace].getInstrument() + efixed = instrument.getNumberParameter('efixed-val')[0] + + logger.notice('Analyser : ' +analyser+reflection +' with energy = ' + str(efixed)) + + result = SetSampleMaterial(InputWorkspace=workspace,ChemicalFormula=formula) + + #elastic wavelength + wave=1.8*math.sqrt(25.2429/efixed) + + absorptionXSection = result[5]*wave/1.7982 + coherentXSection = result[4] + incoherentXSection = result[3] + scatteringXSection = result[3] + + thickness = float(thickness) + density = float(density) + + totalXSection = absorptionXSection + scatteringXSection + + transmission = math.exp(-density*totalXSection*thickness) + scattering = 1.0 - math.exp(-density*scatteringXSection*thickness) + + #Create table workspace to store calculations + tableWs = nameStem + '_Transmission' + tableWs = CreateEmptyTableWorkspace(OutputWorkspace=tableWs) + tableWs.addColumn("str", "Name") + tableWs.addColumn("str", "Value") + + # Names for each of the output values + outputNames = ['Absorption Xsection at wavelength', 'Coherent Xsection', 'Incoherent Xsection', + 'Total scattering Xsection', 'Number density', 'Thickness', 'Transmission (abs+scatt)', 'Total scattering'] + + # List of the calculated values + outputValues = [str(wave) + ' A = '+ str(absorptionXSection), coherentXSection, incoherentXSection, scatteringXSection, + density, thickness, transmission, scattering] + + # Convert all values to string + outputValues = map (str, outputValues) + + output = zip (outputNames, outputValues) + + #build table of values + for name, value in output: + tableWs.addRow(name, value) + logger.notice(name, value) + + #remove idf/ipf workspace + DeleteWorkspace(workspace) + + EndTime('IndirectTransmission') + +# Register algorithm with Mantid +AlgorithmFactory.subscribe(IndirectTransmission) \ No newline at end of file From 417300b1910483fe6aa5f3d73c0c92697d6515ae Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Wed, 23 Oct 2013 11:53:26 +0100 Subject: [PATCH 002/403] Refs #8176 Fixed algorithm output --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index ed43ba9e69cd..fc8ca7fcdd2f 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -92,8 +92,8 @@ def PyExec(self): #build table of values for name, value in output: - tableWs.addRow(name, value) - logger.notice(name, value) + tableWs.addRow([name, value]) + logger.notice(name + ": " + value) #remove idf/ipf workspace DeleteWorkspace(workspace) From 1515194640727007e6725e4a6bb6b4033f6629c7 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Wed, 23 Oct 2013 12:40:04 +0100 Subject: [PATCH 003/403] Refs #8176 Change algorithm parameter names to remove space. --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index fc8ca7fcdd2f..7308bf3e506c 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -21,8 +21,8 @@ def PyInit(self): self.declareProperty(name='Instrument',defaultValue='IRIS',validator=StringListValidator(['IRIS','OSIRIS']), doc='Instrument') self.declareProperty(name='Analyser',defaultValue='graphite',validator=StringListValidator(['graphite','fmica']), doc='Analyser') self.declareProperty(name='Reflection',defaultValue='002',validator=StringListValidator(['002','004']), doc='Reflection') - self.declareProperty(name='Chemical Formula',defaultValue='',validator=StringMandatoryValidator(), doc='Sample chemical formula') - self.declareProperty(name='Number Density', defaultValue=0.1, doc='Number denisty. Default=0.1') + self.declareProperty(name='ChemicalFormula',defaultValue='',validator=StringMandatoryValidator(), doc='Sample chemical formula') + self.declareProperty(name='NumberDensity', defaultValue=0.1, doc='Number denisty. Default=0.1') self.declareProperty(name='Thickness', defaultValue=0.1, doc='Sample thickness. Default=0.1') def PyExec(self): @@ -32,8 +32,8 @@ def PyExec(self): instrumentName = self.getPropertyValue('Instrument') analyser = self.getPropertyValue('Analyser') reflection = self.getPropertyValue('Reflection') - formula = self.getPropertyValue('Chemical Formula') - density = self.getPropertyValue('Number Density') + formula = self.getPropertyValue('ChemicalFormula') + density = self.getPropertyValue('NumberDensity') thickness = self.getPropertyValue('Thickness') #Load instrument defintion file From 404fadf45f8f50fd8754a52b70a0c48113beedf9 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 29 Oct 2013 17:24:50 -0400 Subject: [PATCH 004/403] Started to implement the algorithm. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 590 ++++++++++++++++++ 1 file changed, 590 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py new file mode 100644 index 000000000000..1e253e05dfa9 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -0,0 +1,590 @@ +###################################################################### +# +# This is a partial copy from LeBailFitScript.py +# +# Python Script as Step 1 of Le Bail Fitting to +# 1. Load file +# 2. Create LeBailFitInput +# 3. Fit Peaks +# +# Step 1: Load data, model (HKL list) and starting instrument parameters values, +# and do an initial LeBailFit/calculation to see how much the starting +# values are off; +# +###################################################################### + +import mantid.simpleapi as api +from mantid.api import * +from mantid.kernel import * + + +#from Calibration_ImportInformation import * + + +#-------------------------------------------------------------------------------- +class RefinePowderDiffProfileSeq(PythonAlgorithm): + """ Refine powder diffractometer profile by Le Bail algorithm sequentially + """ + def category(self): + """ Category + """ + return "Diffraction" + + def name(self): + """ Algorithm name + """ + return "RefinePowderDiffProfileSeq" + + def PyInit(self): + """ Declare properties + """ + self.setWikiSummary("""Refine powder diffractomer profile parameters sequentially.""") + + self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional), + "Name of table workspace containing sequential refinement information.") + + self.declareProperty(ITableWorkspaceProperty("InputProfileWorkspace", "", Direction.Input, PropertyMode.Optional), + "Name of table workspace containing starting profile parameters.") + + self.declareProperty(ITableWorkspaceProperty("InputBraggPeaksWorkspace", "", Direction.Input, PropertyMode.Optional), + "Name of table workspace containing a list of reflections. ") + + self.declareProperty(ITableWorkspaceProperty("InputBackgroundParameterWorkspace", "", Direction.Input, + PropertyMode.Optional), "Name of table workspace containing a list of reflections. ") + + self.declareProperty("StartX", -0., "Start X (TOF) to refine diffraction pattern.") + self.declareProperty("EndX", -0., "End X (TOF) to refine diffraction pattern.") + + funcoptions = ["Setup", "Refine"] + self.declareProperty("FunctionOption", "Refine-Levenberg", StringListValidator(funcoptions), "Options of functionality") + + refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] + self.declareProperty("RefinementOption", "Refine-Levenberg", StringListValidator(funcoptions), + "Options of algorithm to refine. ") + + self.declareProperty(StringArrayProperty("Parameters2Refine", values=[], direction=Direction.Input), + "List of parameters to refine.") + + self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") + + bkgdtypes = ["Polynomial", "Chebyshev"] + self.declareProperty("BackgroundType", "Polynomial", StringListValidator(bkgdtypes), + "Type of background function.") + + return + + + def PyExec(self): + """ Main + """ + # Process input + self._processInputProperties() + + # Instantiaze sequential refinement + seqrefine = SeqRefineProfile("IDx890", globalfilename) + + # Execute + if self.functionoption == "Setup": + # Set up + if seqrefine.isSetup() is True: + raise NotImplementedError("Impossible to have it set up already.") + + seqrefine.initSetup(self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, + self.startx, self.endx) + + elif self.functionoption == "Refine": + # Refine + if seqrefine.isSetup() is False: + raise NotImplementedError("Exception because sequential refinement is not set up.") + seqrefine.refine(self.paramstofit, self.numcycles, self.startx, self.endx) + + else: + # None-support + raise NotImplementedError("Function is not supported.") + + return + + + def _processInputProperties(self): + """ Process input properties + """ + self.startx = self.getProperty("StartX").value + self.endx = self.getProperty("EndX").value + + self.functionoption = slef.getProperty("FunctionOption").value + if self.functionoption == "Setup": + self.bkgdtype = self.getProperty("BackgroundType").value + self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value + self.profilews = self.getProperty("InputProfileWorkspace").value + self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value + + elif self.functionoptions == "Refine": + self.paramstofit = self.getProperty("Parameters2Refine").value + self.numcycles = self.Property("NumRefineCycle").value + + return + + +#-------------------------------------------------------------------- +class SeqRefineProfile: + """ A class to do sequential refinement on peak profile + + Use case: + 1. Set class object such as : ID/StartDate/Directory + 2. Run main to refine some parameters + 3. Check result + 4. If no further instruction, only need to set up parameters to refine + the input/starting values should be from the last + """ + def __init__(self, ID): + """ + """ + self._ID = str(ID) + + self._recordwsname = "Record%sTable" % (str(ID)) + + return + + def initSetup(self, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): + """ Set up the properties for LeBailFit as the first time + including profilews, braggpeakws, and etc + """ + # Profile + self._profileWS = profilews + self._braggpeakws = braggpeakws + self._bkgdtype = bkgdtype + self._bkgdparws = bkgdparws + + # Generate record table + self._genRecordTable() + + # Check input parameters, i.e., verification/examine input parameters + runner = RefineProfileParameters() + + runner.startx = startx + runner.endx = endx + + runner.inprofilewsname = self._profileWS + runner.inreflectionwsname = self._braggpeakws + + runner.bkgdtype = self._bkgdtype + runner.bkgdtablewsname = self._bkgdparws + + runner.outprofilewsname = self._profileWS + runner.outreflectionwsname = self._braggpeakws + + self._recordPreRefineInfo(runner) + runner.calculate() + self._recordPostRefineInfo(runner) + + return + + def refine(self, parametersToFit, numcycles, startx, endx): + """ Refine parameters + """ + runner = RefineProfileParameters(self._globalFilename) + + # Locate refinement record table + profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname = self._parseRecordTable() + + # Set up runner and refine + runner.numsteps = numcycles + runner.paramToFit = parametersToFit + + runner.startx = startx + runner.endx = endx + + runner.inprofilewsname = profilewsname + runner.inreflectionwsname = braggpeakwsname + + runner.bkgdtype = bkgdtype + runner.bkgdtablewsname = bkgdparamwsname + + # Refine + self._recordPreRefineInfo(runner) + + outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(runner.datawsname, profilewsname, braggpeakwsname) + runner.outwsname = outwsname + runner.outprofilewsname = outprofilewsname + runner.outreflectionwsname = outbraggpeakwsname + + runner.refine() + self._recordPostRefineInfo(runner) + + return + + def _genRecordTable(self): + """ Generate record table + """ + tablews = CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname) + + tablews.addColumn("int", "Step") + tablews.addColumn("str", "OutProfile") + tablews.addColumn("str", "OutReflection") + tablews.addColumn("str", "OutBackgroud") + tablews.addColumn("str", "OutBckgroundParam") + tablews.addColumn("str", "Refine") + tablews.addColumn("double", "RwpOut") + tablews.addColumn("int", "LastStep") + tablews.addColumn("double", "RwpIn") + tablews.addColumn("str", "InProfile") + tablews.addColumn("str", "InReflection") + tablews.addColumn("str", "InBackgroud") + tablews.addColumn("str", "InBckgroundParam") + + return + + def _parseRecordTable(self): + """ Parse record table and return the last refinement result + Notice that 'last row' in record table might not be a valid row (incomplete). + It might be caused by an exception raised in refinement or its setup. + Class variable _lastrowinvalid is used to indicate this + """ + rectablews = mtd[self._recordwsname] + numrows = rectablews.rowCount() + if numrows == 0: + raise NotImplementedError("Empty record table workspace. ") + + lastrow = numrows-1 + + while lastrow >= 0: + profilewsname = rectablews.cell(lastrow, 1) + reflectwsname = rectablews.cell(lastrow, 2) + bkgdtype = rectablews.cell(lastrow, 3) + bkgdparamwsname = rectablews.cell(lastrow, 4) + + if profilewsname == "": + print "Profile workspace name is emtpy in row %d!" % (lastrow) + lastrow -= 1 + else: + break + # ENDWHILE + + if profilewsname == "": + raise NotImplementedError("Profile workspace name is empty!") + + self._lastrowinvalid = False + if lastrow != numrows-1: + self._lastrowinvalid = True + + return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname) + + + def _recordPreRefineInfo(self, refiner): + """ Record pre-refinement information + """ + rectablews = mtd[self._recordwsname] + numrows = rectablews.rowCount() + + if self._lastrowinvalid is False: + self._currstep = numrows + laststep = self._currstep-1 + rectablews.addRow([self._currstep, "", "", "", "", "", -1.0, laststep, -1.0, "profilews", "reflectionws", "Polynomial", "BkgdParm"]) + else: + self._currstep = numrows-1 + laststep = self._currstep-1 + + if len(refiner.paramToFit) > 0: + rectablews.setCell(self._currstep, 5, str(refiner.paramToFit)) + rectablews.setCell(self._currstep, 9, refiner.inprofilewsname) + rectablews.setCell(self._currstep, 10, refiner.inreflectionwsname) + rectablews.setCell(self._currstep, 11, refiner.bkgdtype) + rectablews.setCell(self._currstep, 12, refiner.bkgdtablewsname) + + return + + def _recordPostRefineInfo(self, refiner): + """ Record post-refinement information, i.e., refinement result + """ + # Parse profile table workspace + outprofilews = mtd[refiner.outprofilewsname] + # FIXME - Use Name[0], Value[1] as default + numpars = outprofilews.rowCount() + rwp = None + for i in xrange(numpars): + parname = outprofilews.cell(i, 0) + if parname.lower() == "rwp": + rwp = outprofilews.cell(i, 1) + break + + # Set the record table workspace + rectablews = mtd[self._recordwsname] + numrows = rectablews.rowCount() + # currstep = numrows-1 + + rectablews.setCell(self._currstep, 1, refiner.outprofilewsname) + rectablews.setCell(self._currstep, 2, refiner.outreflectionwsname) + rectablews.setCell(self._currstep, 3, refiner.bkgdtype) + rectablews.setCell(self._currstep, 4, refiner.bkgdtablewsname) + if rwp is not None: + rectablews.setCell(self._currstep, 6, rwp) + + return + + def _genOutputWorkspace(self, dataws, profilewsname, braggpeakwsname): + """ + """ + outwsname = "%s_%s_Step%d" % (dataws, self._ID, self._currstep) + + if profilewsname.count(self._ID) > 0: + outprofilewsname = profilewsname.split(self._ID)[0] + else: + outprofilewsname = profilewsname + print "Input: ", profilewsname, "Output: ", type(outprofilewsname), "ID = ", self._ID, "Step = ", self._currstep + outprofilewsname = "%s%s_Step%d" % (outprofilewsname, self._ID, self._currstep) + + if braggpeakwsname.count(str(self._ID)) > 0: + outbpwsname = braggpeakwsname.split(self._ID)[0] + else: + outbpwsname = braggpeakwsname + outbpwsname = "%s%s_Step%d"%(outbpwsname, self._ID, self._currstep) + + return (outwsname, outprofilewsname, outbpwsname) + +#-------------------------------------------------------------------- + +def generateMCSetupTable(wsname): + """ Generate a Le Bail fit Monte Carlo random walk setup table + """ + import mantid.simpleapi as api + + tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=str(wsname)) + + tablews.addColumn("str", "Name") + tablews.addColumn("double", "A0") + tablews.addColumn("double", "A1") + tablews.addColumn("int", "NonNegative") + tablews.addColumn("int", "Group") + + group = 0 + tablews.addRow(["Dtt1" , 5.0, 0.0, 0, group]) + tablews.addRow(["Dtt1t" , 5.0, 0.0, 0, group]) + tablews.addRow(["Dtt2t" , 1.0, 0.0, 0, group]) + tablews.addRow(["Zero" , 5.0, 0.0, 0, group]) + tablews.addRow(["Zerot" , 5.0, 0.0, 0, group]) + tablews.addRow(["Width" , 0.0, 0.1, 1, group]) + tablews.addRow(["Tcross", 0.0, 1.0, 1, group]) + + group = 1 + tablews.addRow(["Beta0" , 0.50, 1.0, 0, group]) + tablews.addRow(["Beta1" , 0.05, 1.0, 0, group]) + tablews.addRow(["Beta0t", 0.50, 1.0, 0, group]) + tablews.addRow(["Beta1t", 0.05, 1.0, 0, group]) + + group = 2 + tablews.addRow(["Alph0" , 0.05, 1.0, 0, group]) + tablews.addRow(["Alph1" , 0.02, 1.0, 0, group]) + tablews.addRow(["Alph0t", 0.10, 1.0, 0, group]) + tablews.addRow(["Alph1t", 0.05, 1.0, 0, group]) + + group = 3 + tablews.addRow(["Sig0", 2.0, 1.0, 1, group]) + tablews.addRow(["Sig1", 2.0, 1.0, 1, group]) + tablews.addRow(["Sig2", 2.0, 1.0, 1, group]) + + group = 4 + tablews.addRow(["Gam0", 2.0, 1.0, 0, group]) + tablews.addRow(["Gam1", 2.0, 1.0, 0, group]) + tablews.addRow(["Gam2", 2.0, 1.0, 0, group]) + + return tablews + +def breakParametersGroups(tablews): + """ Break the parameter groups. Such that each parameter/row has an individual group + """ + numrows = tablews.rowCount() + for ir in xrange(numrows): + tablews.setCell(ir, 4, ir) + + return + +def resetParametersGroups(tablews): + """ Set the group number to original setup + """ + numrows = tablews.rowCount() + for ir in xrange(numrows): + parname = tablews.cell(ir, 0) + if parname in ["Dtt1", "Dtt1t", "Dtt2t", "Zero", "Zerot", "Width", "Tcross"]: + group = 0 + elif parname in ["Beta0", "Beta1", "Beta0t", "Beta1t"]: + group = 1 + elif parname in ["Alph0", "Alph1", "Alph0t", "Alph1t"]: + group = 2 + elif parname in ["Sig0", "Sig1", "Sig2"]: + group = 3 + else: + group = 4 + tablews.setCell(ir, 4, group) + return + + +class RefineProfileParameters: + """ Class to refine profile parameters ONE step + """ + def __init__(self): + """ Initialization + """ + # bankid, calibDict = importCalibrationInformation(globalsfname) + + # self.bankid = int(bankid) + # bankid = self.bankid + + # self.sample = calibDict[bankid]["Sample"] + + # self.datafilename = calibDict["DataFileDir"] + calibDict[bankid]["DataFileName"] + # hklfilename = calibDict["HKLFileDir"] + calibDict[bankid]["HKLFileName"] + # irffilename = calibDict["IrfFileDir"] + calibDict[bankid]["IrfFileName"] + + # self.startx = float(calibDict[bankid]["LeBailFitMinTOF"]) + # self.endx = float(calibDict[bankid]["LeBailFitMaxTOF"]) + # + # self.run = calibDict[bankid]["Run"] + + # # Name of workspaces + # self.datawsname = calibDict[bankid]["DataWorkspace"] + # instrparamwsname = "Bank%sInstrumentParameterTable" % (bankid) + # braggpeakparamwsname = 'BraggPeakParameterTable' + + # # Background related + # usrbkgdpoints = calibDict[bankid]["UserSpecifiedBkgdPts"] + # self.bkgdwsname = self.datawsname+"_Background" + # backgroundtype = calibDict["BackgroundType"] + # backgroundorder = int(calibDict["BackgroundOrder"]) + # self.bkgdfilename = calibDict["WorkingDir"] + self.datawsname + "_Parameters.bak'" + # bkgdwsname = self.datawsname + "_Background" + # self.bkgdtablewsname = self.datawsname + "_Background_Parameters" + + # # Other constants + # latticesize = calibDict[bankid]["LatticeSize"] + + + # Output + self.outwsname = None + + self.numsteps = 0 + + # Refine + self.paramToFit = [] + + # Flags + self._inputIsSetup = False + self._outputIsSetup = False + + return + + def setInputs(self, datawsname, profilewsname, braggpeakwsname, bkgdtype, bkgdparwsname): + """ + """ + self.datawsname = datawsname + self.inprofilewsname = profilewsname + self.inreflectionwsname = braggpeakwsname + self.bkgdtype = bkgdtype + self.bkgdtablewsname = bkgdparwsname + + self._inputIsSetup = True + + return + + def setOutputs(self, outwsname, profilewsname, braggpeakwsname, bkgdparwsname): + """ Set up the variables for output + """ + self.outwsname = outwsname + self.outprofilewsname = profilewsname + self.outreflectionwsname = braggpeakwsname + self.outbkgdtablewsname = bkgdparwsname + + self._outputIsSetup = True + + return + + + def calculate(self, startx, endx): + """ Do Le bail calculation + """ + if (self._inputIsSetup and self.outputIsSetup) is False: + raise NotImplementedError("Either input or output is not setup.") + + LeBailFit( + Function = 'Calculation', + InputWorkspace = self.datawsname, + OutputWorkspace = self.outwsname, + InputParameterWorkspace = self.inprofilewsname, + OutputParameterWorkspace= self.outprofilewsname, + InputHKLWorkspace = self.inreflectionwsname, + OutputPeaksWorkspace = self.outreflectionwsname, + FitRegion = '%f, %f' % (startx, endx), + BackgroundType = self.bkgdtype, + UseInputPeakHeights = False, + PeakRadius = '8', + BackgroundParametersWorkspace = self.bkgdtablewsname + ) + + return + + + def refine(self, numsteps, parameternames, startx, endx): + """ Main execution body (doStep4) + """ + # Check validity + if (self._inputIsSetup and self.outputIsSetup) is False: + raise NotImplementedError("Either input or output is not setup.") + + # Update parameters' fit table + if numsteps > 0: + # Set up the default parameters to refine + + # Set up the parameters to refine + UpdatePeakParameterTableValue( + InputWorkspace = self.inprofilewsname, + Column = "FitOrTie", + NewStringValue = "tie") + UpdatePeakParameterTableValue( + InputWorkspace = self.inprofilewsname, + Column = "FitOrTie", + ParameterNames = parameternames, + NewStringValue = "fit") + + # Limit the range of MC + if parameternames.count("Width") > 0: + #self.cwl = 1.33 + UpdatePeakParameterTableValue( + InputWorkspace = self.inprofilewsname, + Column = "Min", + ParameterNames = ["Width"], + NewFloatValue = 0.50) #cwl*0.25) + + UpdatePeakParameterTableValue( + InputWorkspace = self.inprofilewsname, + Column = "Max", + ParameterNames = ["Width"], + NewFloatValue = 1.25) #cwl*4.0) + + # Generate Monte carlo table + wsname = "MCSetupParameterTable" + tablews = generateMCSetupTable(wsname) + + LeBailFit( + InputWorkspace = self.datawsname, + OutputWorkspace = self.outwsname, + InputParameterWorkspace = self.inprofilewsname, + OutputParameterWorkspace = self.outprofilewsname, + InputHKLWorkspace = self.inreflectionwsname, + OutputPeaksWorkspace = self.outreflectionwsname, + FitRegion = '%f, %f' % (self.startx, self.endx), + Function = 'MonteCarlo', + NumberMinimizeSteps = self.numsteps, + BackgroundType = self.bkgdtype, + BackgroundParametersWorkspace = self.bkgdtablewsname, + UseInputPeakHeights = False, + PeakRadius ='8', + Minimizer = 'Levenberg-Marquardt', + MCSetupWorkspace = str(wsname), + Damping = '5.0', + RandomSeed = 0, + AnnealingTemperature = 100.0, + DrunkenWalk = True) + # ENDIF (step) + + + return + From 84763d746139dababd7b037af833fb5fe9eeb850 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 31 Oct 2013 23:00:52 -0400 Subject: [PATCH 005/403] Fixed some bugs. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index 1e253e05dfa9..65be6710a073 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -59,7 +59,7 @@ def PyInit(self): self.declareProperty("FunctionOption", "Refine-Levenberg", StringListValidator(funcoptions), "Options of functionality") refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] - self.declareProperty("RefinementOption", "Refine-Levenberg", StringListValidator(funcoptions), + self.declareProperty("RefinementOption", "Refine-Levenberg", StringListValidator(refoptions), "Options of algorithm to refine. ") self.declareProperty(StringArrayProperty("Parameters2Refine", values=[], direction=Direction.Input), @@ -67,7 +67,7 @@ def PyInit(self): self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") - bkgdtypes = ["Polynomial", "Chebyshev"] + bkgdtypes = ["Polynomial", "Chebyshev", "FullprofPolynomial"] self.declareProperty("BackgroundType", "Polynomial", StringListValidator(bkgdtypes), "Type of background function.") @@ -81,7 +81,7 @@ def PyExec(self): self._processInputProperties() # Instantiaze sequential refinement - seqrefine = SeqRefineProfile("IDx890", globalfilename) + seqrefine = SeqRefineProfile("IDx890") # Execute if self.functionoption == "Setup": @@ -111,7 +111,7 @@ def _processInputProperties(self): self.startx = self.getProperty("StartX").value self.endx = self.getProperty("EndX").value - self.functionoption = slef.getProperty("FunctionOption").value + self.functionoption = self.getProperty("FunctionOption").value if self.functionoption == "Setup": self.bkgdtype = self.getProperty("BackgroundType").value self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value @@ -588,3 +588,5 @@ def refine(self, numsteps, parameternames, startx, endx): return +# Register algorithm with Mantid +AlgorithmFactory.subscribe(RefinePowderDiffProfileSeq) From 8c1319a7e90b8c6d47e980599322355dc9217502 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 5 Nov 2013 10:40:05 -0500 Subject: [PATCH 006/403] Checkpointing work (progress). Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 118 ++++++++++++------ 1 file changed, 80 insertions(+), 38 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index 65be6710a073..ca2e8c986dd3 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -13,6 +13,7 @@ # ###################################################################### +from mantid.api import * import mantid.simpleapi as api from mantid.api import * from mantid.kernel import * @@ -40,6 +41,9 @@ def PyInit(self): """ self.setWikiSummary("""Refine powder diffractomer profile parameters sequentially.""") + self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, PropertyMode.Optional), + "Name of data workspace containing the diffraction pattern in .prf file. ") + self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional), "Name of table workspace containing sequential refinement information.") @@ -81,7 +85,7 @@ def PyExec(self): self._processInputProperties() # Instantiaze sequential refinement - seqrefine = SeqRefineProfile("IDx890") + seqrefine = SeqRefineProfile("IDx890", self.log()) # Execute if self.functionoption == "Setup": @@ -89,7 +93,7 @@ def PyExec(self): if seqrefine.isSetup() is True: raise NotImplementedError("Impossible to have it set up already.") - seqrefine.initSetup(self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, + seqrefine.initSetup(self.dataws, self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, self.startx, self.endx) elif self.functionoption == "Refine": @@ -108,6 +112,9 @@ def PyExec(self): def _processInputProperties(self): """ Process input properties """ + self.dataws = self.getProperty("InputWorkspace").value + self.datawsname = str(self.dataws) + self.startx = self.getProperty("StartX").value self.endx = self.getProperty("EndX").value @@ -136,19 +143,27 @@ class SeqRefineProfile: 4. If no further instruction, only need to set up parameters to refine the input/starting values should be from the last """ - def __init__(self, ID): + def __init__(self, ID, glog): """ """ self._ID = str(ID) + self.glog = glog + self.glog.information("SeqRefineProfile is initialized with ID = %s" % (str(ID))) self._recordwsname = "Record%sTable" % (str(ID)) + self._isSetup = False + self._lastrowinvalid = False + return - def initSetup(self, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): + def initSetup(self, dataws, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): """ Set up the properties for LeBailFit as the first time including profilews, braggpeakws, and etc """ + # Data + self._datawsname = str(dataws) + # Profile self._profileWS = profilews self._braggpeakws = braggpeakws @@ -159,30 +174,38 @@ def initSetup(self, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): self._genRecordTable() # Check input parameters, i.e., verification/examine input parameters - runner = RefineProfileParameters() + runner = RefineProfileParameters(self.glog) runner.startx = startx runner.endx = endx - runner.inprofilewsname = self._profileWS - runner.inreflectionwsname = self._braggpeakws + # runner.inprofilewsname = self._profileWS + # runner.inreflectionwsname = self._braggpeakws - runner.bkgdtype = self._bkgdtype - runner.bkgdtablewsname = self._bkgdparws + # runner.bkgdtype = self._bkgdtype + # runner.bkgdtablewsname = self._bkgdparws - runner.outprofilewsname = self._profileWS - runner.outreflectionwsname = self._braggpeakws + # runner.outprofilewsname = self._profileWS + # runner.outreflectionwsname = self._braggpeakws + + outwsname = "InitTemp" + + runner.setInputs(self._datawsname, self._profileWS, self._braggpeakws, self._bkgdtype, self._bkgdparws) + # FIXME - Need to verify whether input and output background parameter ws name can be same + runner.setOutputs(outwsname, self._profileWS, self._braggpeakws, self._bkgdparws) self._recordPreRefineInfo(runner) - runner.calculate() + runner.calculate(runner.startx, runner.endx) self._recordPostRefineInfo(runner) + self._isSetup = True + return def refine(self, parametersToFit, numcycles, startx, endx): """ Refine parameters """ - runner = RefineProfileParameters(self._globalFilename) + runner = RefineProfileParameters(self.glog) # Locate refinement record table profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname = self._parseRecordTable() @@ -194,29 +217,38 @@ def refine(self, parametersToFit, numcycles, startx, endx): runner.startx = startx runner.endx = endx - runner.inprofilewsname = profilewsname - runner.inreflectionwsname = braggpeakwsname - - runner.bkgdtype = bkgdtype - runner.bkgdtablewsname = bkgdparamwsname + # runner.inprofilewsname = profilewsname + # runner.inreflectionwsname = braggpeakwsname + # runner.bkgdtype = bkgdtype + # runner.bkgdtablewsname = bkgdparamwsname + outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(runner.datawsname, profilewsname, braggpeakwsname) + # runner.outwsname = outwsname + # runner.outprofilewsname = outprofilewsname + # runner.outreflectionwsname = outbraggpeakwsname + + # Set up input and output + runner.setInputs(self._datawsname, profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname) + # FIXME - Need to verify whether input and output background parameter ws name can be same + runner.setOutputs(outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname) + # Refine self._recordPreRefineInfo(runner) - outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(runner.datawsname, profilewsname, braggpeakwsname) - runner.outwsname = outwsname - runner.outprofilewsname = outprofilewsname - runner.outreflectionwsname = outbraggpeakwsname - runner.refine() self._recordPostRefineInfo(runner) return + def isSetup(self): + """ Status whether refinement is set up. + """ + return self._isSetup + def _genRecordTable(self): """ Generate record table """ - tablews = CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname) + tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname) tablews.addColumn("int", "Step") tablews.addColumn("str", "OutProfile") @@ -284,12 +316,14 @@ def _recordPreRefineInfo(self, refiner): self._currstep = numrows-1 laststep = self._currstep-1 + # print "*** Record workspace has %d rows. current step = %d. " % (rectablews.rowCount(), self._currstep) + if len(refiner.paramToFit) > 0: rectablews.setCell(self._currstep, 5, str(refiner.paramToFit)) - rectablews.setCell(self._currstep, 9, refiner.inprofilewsname) - rectablews.setCell(self._currstep, 10, refiner.inreflectionwsname) - rectablews.setCell(self._currstep, 11, refiner.bkgdtype) - rectablews.setCell(self._currstep, 12, refiner.bkgdtablewsname) + rectablews.setCell(self._currstep, 9, str(refiner.inprofilewsname)) + rectablews.setCell(self._currstep, 10, str(refiner.inreflectionwsname)) + rectablews.setCell(self._currstep, 11, str(refiner.bkgdtype)) + rectablews.setCell(self._currstep, 12, str(refiner.bkgdtablewsname)) return @@ -297,7 +331,10 @@ def _recordPostRefineInfo(self, refiner): """ Record post-refinement information, i.e., refinement result """ # Parse profile table workspace - outprofilews = mtd[refiner.outprofilewsname] + # FIXME - do I need to call AnalysisDataService? + # print "****** outprofilews type = ", type(refiner.outprofilewsname) + outprofilews = AnalysisDataService.retrieve(str(refiner.outprofilewsname)) + # outprofilews = api.mtd[refiner.outprofilewsname] # FIXME - Use Name[0], Value[1] as default numpars = outprofilews.rowCount() rwp = None @@ -312,10 +349,10 @@ def _recordPostRefineInfo(self, refiner): numrows = rectablews.rowCount() # currstep = numrows-1 - rectablews.setCell(self._currstep, 1, refiner.outprofilewsname) - rectablews.setCell(self._currstep, 2, refiner.outreflectionwsname) - rectablews.setCell(self._currstep, 3, refiner.bkgdtype) - rectablews.setCell(self._currstep, 4, refiner.bkgdtablewsname) + rectablews.setCell(self._currstep, 1, str(refiner.outprofilewsname)) + rectablews.setCell(self._currstep, 2, str(refiner.outreflectionwsname)) + rectablews.setCell(self._currstep, 3, str(refiner.bkgdtype)) + rectablews.setCell(self._currstep, 4, str(refiner.bkgdtablewsname)) if rwp is not None: rectablews.setCell(self._currstep, 6, rwp) @@ -421,7 +458,7 @@ def resetParametersGroups(tablews): class RefineProfileParameters: """ Class to refine profile parameters ONE step """ - def __init__(self): + def __init__(self, glog): """ Initialization """ # bankid, calibDict = importCalibrationInformation(globalsfname) @@ -461,6 +498,8 @@ def __init__(self): # Output self.outwsname = None + self.glog = glog + self.numsteps = 0 # Refine @@ -501,10 +540,13 @@ def setOutputs(self, outwsname, profilewsname, braggpeakwsname, bkgdparwsname): def calculate(self, startx, endx): """ Do Le bail calculation """ - if (self._inputIsSetup and self.outputIsSetup) is False: - raise NotImplementedError("Either input or output is not setup.") + if (self._inputIsSetup and self._outputIsSetup) is False: + raise NotImplementedError("Either input or output is not setup: inputIsStepUp = %s, outputIsSetup = %s" % + (str(self._inputIsSetup), str(self._outputIsSetup))) + + self.glog.information("Calculate: DataWorksapce = %s" % (str(self.datawsname))) - LeBailFit( + api.LeBailFit( Function = 'Calculation', InputWorkspace = self.datawsname, OutputWorkspace = self.outwsname, @@ -526,7 +568,7 @@ def refine(self, numsteps, parameternames, startx, endx): """ Main execution body (doStep4) """ # Check validity - if (self._inputIsSetup and self.outputIsSetup) is False: + if (self._inputIsSetup and self._outputIsSetup) is False: raise NotImplementedError("Either input or output is not setup.") # Update parameters' fit table From 50bbba148a8931d08af7ad3de7b57961962957c2 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Tue, 12 Nov 2013 11:07:24 +0000 Subject: [PATCH 007/403] Refs #8346 Change workspace averaging to only use unique names. --- .../OSIRISDiffractionReduction.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py index b266dfa7c87b..48e38e9a55d8 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py @@ -72,17 +72,23 @@ def averageWsList(wsList): assert len(wsList) > 0, "getAverageWs: Trying to take an average of nothing." if len(wsList) == 1: return wsList[0] + + #create set of unique workspace names + #so we don't count the same run twice + uniqueWorkspaces = list(set(wsList)) + numWorkspaces = len(uniqueWorkspaces) # Generate the final name of the averaged workspace. avName = "avg" - for name in wsList: + for name in uniqueWorkspaces: avName += "_" + name # Compute the average and put into "__temp_avg". - __temp_avg = mtd[wsList[0]] + mtd[wsList[1]] - for i in range(2, len(wsList) ): - __temp_avg += mtd[wsList[i]] - __temp_avg /= len(wsList) + __temp_avg = mtd[uniqueWorkspaces[0]] + for i in range(1, numWorkspaces): + __temp_avg += mtd[uniqueWorkspaces[i]] + + __temp_avg /= numWorkspaces # Rename the average ws and return it. RenameWorkspace(InputWorkspace=__temp_avg, OutputWorkspace=avName) @@ -240,6 +246,7 @@ def execDiffOnly(self, sampleRuns): # Create scalar data to cope with where merge has combined overlapping data. intersections = getIntersectionsOfRanges(self._samMap.getMap().keys()) + dataX = result.dataX(0) dataY = []; dataE = [] for i in range(0, len(dataX)-1): @@ -248,7 +255,7 @@ def execDiffOnly(self, sampleRuns): dataY.append(2); dataE.append(2) else: dataY.append(1); dataE.append(1) - + # apply scalar data to result workspace for i in range(0, result.getNumberHistograms()): resultY = result.dataY(i) From d1a17c4d6f9af60b801e820dbf5d89eb656a5843 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 15 Nov 2013 10:25:31 +0000 Subject: [PATCH 008/403] Refs #8346 Implement better way of filtering of runs. --- .../OSIRISDiffractionReduction.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py index 48e38e9a55d8..0cafeaf3fbc0 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py @@ -50,9 +50,7 @@ def addWs(self, wsname): ", which has a time regime of " + str(timeRegime)) # Add the workspace to the map, alongside its DRange. - if dRange in self._map: - self._map[dRange].append(wsname) - else: + if dRange not in self._map: self._map[dRange] = [wsname] def setItem(self, dRange, wsname): @@ -72,21 +70,18 @@ def averageWsList(wsList): assert len(wsList) > 0, "getAverageWs: Trying to take an average of nothing." if len(wsList) == 1: return wsList[0] - - #create set of unique workspace names - #so we don't count the same run twice - uniqueWorkspaces = list(set(wsList)) - numWorkspaces = len(uniqueWorkspaces) # Generate the final name of the averaged workspace. avName = "avg" - for name in uniqueWorkspaces: + for name in wsList: avName += "_" + name + numWorkspaces = len(wsList) + # Compute the average and put into "__temp_avg". - __temp_avg = mtd[uniqueWorkspaces[0]] + __temp_avg = mtd[wsList[0]] for i in range(1, numWorkspaces): - __temp_avg += mtd[uniqueWorkspaces[i]] + __temp_avg += mtd[wsList[i]] __temp_avg /= numWorkspaces From 7a38ac156c903e9f0a57b7e9ee6c73dd9309c4ff Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 18 Nov 2013 10:48:27 -0500 Subject: [PATCH 009/403] Added 2 more algorithm properties. Refs #8472. --- .../CurveFitting/src/ProcessBackground.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp index eb778d2460b4..a31b1fecc68f 100644 --- a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp @@ -109,6 +109,7 @@ DECLARE_ALGORITHM(ProcessBackground) std::vector bkgdtype; bkgdtype.push_back("Polynomial"); bkgdtype.push_back("Chebyshev"); + bkgdtype.push_back("FullprofPolynomial"); auto bkgdvalidator = boost::make_shared(bkgdtype); declareProperty("BackgroundType", "Polynomial", bkgdvalidator, "Type of the background. Options include Polynomial and Chebyshev."); @@ -177,6 +178,21 @@ DECLARE_ALGORITHM(ProcessBackground) setPropertySettings("UserBackgroundWorkspace", new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); + // Optional output workspace + // TODO - Implement more upon this option! + declareProperty(new WorkspaceProperty("OutputBackgroundParameterTable", "", Direction::Output, + PropertyMode::Optional), + "Output .... ... ."); + setPropertySettings("OutputBackgroundParameterTable", + new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); + + // TODO - Develop from this new option + // Output background type. + declareProperty("OutputBackgroundType", "Polynomial", bkgdvalidator, + "Type of background to fit with selected ... ."); + setPropertySettings("OutputBackgroundType", + new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); + // Peak table workspac for "RemovePeaks" declareProperty(new WorkspaceProperty("BraggPeakTableWorkspace", "", Direction::Input, From 4d2ba844a01749f297442f96f6f6d43975b885d2 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 18 Nov 2013 16:58:03 +0000 Subject: [PATCH 010/403] Refs #6473. New class for the dialog. --- .../MantidQt/MantidWidgets/CMakeLists.txt | 14 +++--- .../MuonSequentialFitDialog.h | 50 +++++++++++++++++++ .../src/MuonSequentialFitDialog.cpp | 22 ++++++++ 3 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h create mode 100644 Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp diff --git a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt index 00503ac7eb0e..7aef3b27344d 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt +++ b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt @@ -1,22 +1,23 @@ set ( SRC_FILES src/AlgorithmSelectorWidget.cpp + src/CatalogHelper.cpp + src/CatalogSearch.cpp src/CheckboxHeader.cpp src/DataSelector.cpp src/DiagResults.cpp - src/FindReplaceDialog.cpp src/FindDialog.cpp + src/FindReplaceDialog.cpp src/FitPropertyBrowser.cpp src/FunctionBrowser.cpp - src/CatalogSearch.cpp - src/CatalogHelper.cpp src/InstrumentSelector.cpp - src/MessageDisplay.cpp src/MWDiag.cpp src/MWRunFiles.cpp + src/MessageDisplay.cpp src/MultifitSetupDialog.cpp src/MuonFitPropertyBrowser.cpp + src/MuonSequentialFitDialog.cpp + src/ProcessingAlgoWidget.cpp src/PropertyHandler.cpp - src/ProcessingAlgoWidget.cpp src/RangeSelector.cpp src/RenameParDialog.cpp src/SafeQwtPlot.cpp @@ -46,6 +47,7 @@ set ( MOC_FILES inc/MantidQtMantidWidgets/MessageDisplay.h inc/MantidQtMantidWidgets/MultifitSetupDialog.h inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h + inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h inc/MantidQtMantidWidgets/MWDiag.h inc/MantidQtMantidWidgets/MWRunFiles.h inc/MantidQtMantidWidgets/PropertyHandler.h @@ -65,7 +67,7 @@ set ( MOC_FILES # Add the include files are NOT already in MOC_FILES set ( INC_FILES - ${MOC_FILES} + ${MOC_FILES} inc/MantidQtMantidWidgets/WidgetDllOption.h ) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h new file mode 100644 index 000000000000..dfc8898aaf35 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -0,0 +1,50 @@ +#ifndef MANTID_MANTIDWIDGETS_MUONSEQUENTIALFITDIALOG_H_ +#define MANTID_MANTIDWIDGETS_MUONSEQUENTIALFITDIALOG_H_ + +#include "MantidKernel/System.h" + +#include + +namespace Mantid +{ +namespace MantidWidgets +{ + + /** MuonSequentialFitDialog : TODO: DESCRIPTION + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport MuonSequentialFitDialog : public QDialog + { + + Q_OBJECT + + public: + MuonSequentialFitDialog(QWidget* parent); + virtual ~MuonSequentialFitDialog(); + + }; + + +} // namespace MantidWidgets +} // namespace Mantid + +#endif /* MANTID_MANTIDWIDGETS_MUONSEQUENTIALFITDIALOG_H_ */ diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp new file mode 100644 index 000000000000..ea7279054f73 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -0,0 +1,22 @@ +#include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" + +namespace Mantid +{ +namespace MantidWidgets +{ + + /** + * Constructor + */ + MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : + QDialog(parent) + {} + + /** + * Destructor + */ + MuonSequentialFitDialog::~MuonSequentialFitDialog() + {} + +} // namespace MantidWidgets +} // namespace Mantid From ff553b9d50df1dc4608f082621137d4a3b7358ad Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 19 Nov 2013 09:50:57 +0000 Subject: [PATCH 011/403] Refs #6473. Enabled Sequential fit option for Muon Analysis. The new dialog is shown when it is clicked. --- .../FitPropertyBrowser.h | 2 +- .../MuonFitPropertyBrowser.h | 6 ++--- .../MuonSequentialFitDialog.h | 2 +- .../src/MuonFitPropertyBrowser.cpp | 23 ++++++++----------- .../src/MuonSequentialFitDialog.cpp | 2 +- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h index ac67db1dbc87..648f2aa8e44f 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h @@ -211,7 +211,7 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS FitPropertyBrowser: public QDockWidget, public slots: virtual void fit(){ doFit(500); } - void sequentialFit(); + virtual void sequentialFit(); void undoFit(); void clear(); void clearBrowser(); diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h index 1745a05c6460..13e7bb4e6165 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h @@ -47,6 +47,8 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS MuonFitPropertyBrowser: public MantidQt: public slots: /// Perform the fit algorithm virtual void fit(); + /// Open sequential fit dialog + virtual void sequentialFit(); protected: @@ -60,8 +62,6 @@ private slots: private: /// Get the registered function names virtual void populateFunctionNames(); - /// Enable/disable the Fit button; - virtual void setFitEnabled(bool yes); /// Check if the workspace can be used in the fit virtual bool isWorkspaceValid(Mantid::API::Workspace_sptr)const; @@ -71,4 +71,4 @@ private slots: } // API -#endif /*MUONFITPROPERTYBROWSER_H_*/ \ No newline at end of file +#endif /*MUONFITPROPERTYBROWSER_H_*/ diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index dfc8898aaf35..e15e481e92e0 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -5,7 +5,7 @@ #include -namespace Mantid +namespace MantidQt { namespace MantidWidgets { diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp index b827130e6d43..1229c15fcb6d 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp @@ -1,6 +1,6 @@ #include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" +#include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" #include "MantidQtMantidWidgets/PropertyHandler.h" -#include "MantidQtMantidWidgets/SequentialFitDialog.h" #include "MantidAPI/FunctionFactory.h" // Suppress a warning coming out of code that isn't ours @@ -35,6 +35,7 @@ #include #include +#include namespace MantidQt @@ -42,7 +43,6 @@ namespace MantidQt namespace MantidWidgets { - /** * Constructor * @param parent :: The parent widget - must be an ApplicationWindow @@ -311,6 +311,14 @@ void MuonFitPropertyBrowser::fit() } } +/** + * Show sequential fit dialog. + */ +void MuonFitPropertyBrowser::sequentialFit() +{ + MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(this); + dialog->show(); +} /** * Connect to the AnalysisDataServis when shown @@ -322,17 +330,6 @@ void MuonFitPropertyBrowser::showEvent(QShowEvent* e) populateWorkspaceNames(); } - -/** -* Enable/disable the Fit button. -*/ -void MuonFitPropertyBrowser::setFitEnabled(bool yes) -{ - m_fitActionFit->setEnabled(yes); - m_fitActionSeqFit->setEnabled(false); -} - - /** Check if the workspace can be used in the fit. The accepted types are * MatrixWorkspaces same size and that it isn't the generated raw file. * @param ws :: The workspace diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index ea7279054f73..2532a6828f40 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -1,6 +1,6 @@ #include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" -namespace Mantid +namespace MantidQt { namespace MantidWidgets { From 3fddfa42858a4260db3bb7c1e24cc776bac41609 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 19 Nov 2013 10:22:44 +0000 Subject: [PATCH 012/403] Refs #6473. Initial UI file for the dialog. --- .../MantidQt/MantidWidgets/CMakeLists.txt | 13 +++---- .../MuonSequentialFitDialog.h | 5 +++ .../MuonSequentialFitDialog.ui | 34 +++++++++++++++++++ .../src/MuonSequentialFitDialog.cpp | 4 ++- 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui diff --git a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt index 7aef3b27344d..80b24a037d47 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt +++ b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt @@ -33,9 +33,9 @@ set ( SRC_FILES # Header files with Q_OBJECT that qmake will "moc" set ( MOC_FILES - inc/MantidQtMantidWidgets/AlgorithmSelectorWidget.h - inc/MantidQtMantidWidgets/CheckboxHeader.h - inc/MantidQtMantidWidgets/DataSelector.h + inc/MantidQtMantidWidgets/AlgorithmSelectorWidget.h + inc/MantidQtMantidWidgets/CheckboxHeader.h + inc/MantidQtMantidWidgets/DataSelector.h inc/MantidQtMantidWidgets/DiagResults.h inc/MantidQtMantidWidgets/FindReplaceDialog.h inc/MantidQtMantidWidgets/FindDialog.h @@ -55,7 +55,7 @@ set ( MOC_FILES inc/MantidQtMantidWidgets/pythonCalc.h inc/MantidQtMantidWidgets/RangeSelector.h inc/MantidQtMantidWidgets/RenameParDialog.h - inc/MantidQtMantidWidgets/SafeQwtPlot.h + inc/MantidQtMantidWidgets/SafeQwtPlot.h inc/MantidQtMantidWidgets/SaveWorkspaces.h inc/MantidQtMantidWidgets/ScriptEditor.h inc/MantidQtMantidWidgets/SelectFunctionDialog.h @@ -73,11 +73,12 @@ set ( INC_FILES # QtDesigner UI files to process set ( UI_FILES - inc/MantidQtMantidWidgets/DataSelector.ui + inc/MantidQtMantidWidgets/DataSelector.ui inc/MantidQtMantidWidgets/CatalogSearch.ui - inc/MantidQtMantidWidgets/MultifitSetupDialog.ui inc/MantidQtMantidWidgets/MWDiag.ui inc/MantidQtMantidWidgets/MWRunFiles.ui + inc/MantidQtMantidWidgets/MultifitSetupDialog.ui + inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui inc/MantidQtMantidWidgets/ProcessingAlgoWidget.ui inc/MantidQtMantidWidgets/RenameParDialog.ui inc/MantidQtMantidWidgets/SelectFunctionDialog.ui diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index e15e481e92e0..7428e1770678 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -3,6 +3,8 @@ #include "MantidKernel/System.h" +#include "ui_MuonSequentialFitDialog.h" + #include namespace MantidQt @@ -40,6 +42,9 @@ namespace MantidWidgets public: MuonSequentialFitDialog(QWidget* parent); virtual ~MuonSequentialFitDialog(); + + private: + Ui::MuonSequentialFitDialog ui; }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui new file mode 100644 index 000000000000..49bf5729866b --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui @@ -0,0 +1,34 @@ + + + MuonSequentialFitDialog + + + + 0 + 0 + 500 + 500 + + + + + 500 + 500 + + + + Muon Analysis - Sequential Fitting + + + + + + Hi! I am a new form. + + + + + + + + diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 2532a6828f40..6cefccd78500 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -10,7 +10,9 @@ namespace MantidWidgets */ MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : QDialog(parent) - {} + { + ui.setupUi(this); + } /** * Destructor From 7ab9e199c1f446f1200fbb84da149b00ab507662 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 19 Nov 2013 13:48:02 +0000 Subject: [PATCH 013/403] Refs #6473. Hide label for MWRunFiles widget if it is empty. --- Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp index 87157889de71..c9992b1262e4 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp @@ -276,6 +276,7 @@ QString MWRunFiles::getLabelText() const void MWRunFiles::setLabelText(const QString & text) { m_uiForm.textLabel->setText(text); + m_uiForm.textLabel->setVisible( ! text.isEmpty() ); } /** Set the minimum width on the label widget From eaab229f28e0a15c629d3e6f0db8c6496516fea2 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 19 Nov 2013 15:03:32 +0000 Subject: [PATCH 014/403] Refs #6473. Basic elements for the UI form. --- .../MuonSequentialFitDialog.ui | 146 +++++++++++++++++- .../src/MuonFitPropertyBrowser.cpp | 1 + 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui index 49bf5729866b..03ca30c63ff0 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui @@ -21,14 +21,154 @@ - - - Hi! I am a new form. + + + 0 + + 6 + + + + + + 0 + 0 + + + + Runs: + + + + + + + + 0 + 0 + + + + Label: + + + + + + + + + + + + + true + + + true + + + + + + + + + + + Parameters from previous fit + + + true + + + + + + + Initial parameters for every fit + + + + + + + + + + + false + + + 0 + + + true + + + false + + + + + + + false + + + Stop + + + false + + + false + + + + + + + Start + + + + + + + + + Diagnosis + + + false + + + + 6 + + + 0 + + + 0 + + + + + + + + MantidQt::MantidWidgets::MWRunFiles + QWidget +
MantidQtMantidWidgets/MWRunFiles.h
+
+
diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp index 1229c15fcb6d..f4bb5de81468 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp @@ -317,6 +317,7 @@ void MuonFitPropertyBrowser::fit() void MuonFitPropertyBrowser::sequentialFit() { MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(this); + dialog->setModal(true); dialog->show(); } From ab7d66f2efe9abe5fb582dd66d8dcaac307b1aa6 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 11:15:04 +0000 Subject: [PATCH 015/403] Refs #6473. Validation of label. --- .../MuonSequentialFitDialog.h | 14 ++- .../MuonSequentialFitDialog.ui | 85 ++++++++++++++++--- .../src/MuonSequentialFitDialog.cpp | 37 +++++++- 3 files changed, 119 insertions(+), 17 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 7428e1770678..79ea8bd07e68 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -2,6 +2,7 @@ #define MANTID_MANTIDWIDGETS_MUONSEQUENTIALFITDIALOG_H_ #include "MantidKernel/System.h" +#include "MantidKernel/Logger.h" #include "ui_MuonSequentialFitDialog.h" @@ -44,8 +45,19 @@ namespace MantidWidgets virtual ~MuonSequentialFitDialog(); private: + /// UI form Ui::MuonSequentialFitDialog ui; - + + /// Checks if specified name is valid as a name for label. + static std::string isValidLabel(const std::string& label); + + /// Instance used to print log messages + static Mantid::Kernel::Logger& g_log; + + private slots: + + /// Updates visibility/tooltip of label error asterisk + void validateLabel(const QString& label); }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui index 03ca30c63ff0..07d62e5ad6f2 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui @@ -28,6 +28,19 @@ 6 + + + + + + + true + + + true + + + @@ -55,20 +68,64 @@ - - - - - - - - - true - - - true - - + + + 6 + + + + + + + + + 0 + 0 + + + + + + + + + 170 + 0 + 0 + + + + + + + + + 170 + 0 + 0 + + + + + + + + + 161 + 160 + 159 + + + + + + + + * + + + + diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 6cefccd78500..15aa7c775f36 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -1,19 +1,52 @@ #include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" +#include "MantidAPI/AnalysisDataService.h" namespace MantidQt { namespace MantidWidgets { + using namespace Mantid::Kernel; + using namespace Mantid::API; + + Logger& MuonSequentialFitDialog::g_log(Logger::get("MuonSequentialFitDialog")); /** * Constructor */ MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : - QDialog(parent) + QDialog(parent) { ui.setupUi(this); + + connect( ui.labelInput, SIGNAL( textChanged(const QString&) ), + this, SLOT( validateLabel(const QString&) ) ); + } + + /** + * Checks if specified name is valid as a name for label. + * @param label :: The name to check + * @return Empty string if valid, otherwise a string describing why is invalid + */ + std::string MuonSequentialFitDialog::isValidLabel(const std::string& label) + { + if ( label.empty() ) + return "Can not be empty"; + else + return AnalysisDataService::Instance().isValid(label); } - + + /** + * Updates visibility/tooltip of label error asterisk. + * @param label :: New label as specified by user + */ + void MuonSequentialFitDialog::validateLabel(const QString& label) + { + std::string error = isValidLabel( label.toStdString() ); + + ui.labelError->setVisible( ! error.empty() ); + ui.labelError->setToolTip( QString::fromStdString(error) ); + } + /** * Destructor */ From 6bcf617d75bf2bcae594f20a2b550b514223f0f6 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 11:16:02 +0000 Subject: [PATCH 016/403] Refs #6473. Single button for start/stop functinality. Can just change the text when stopped/running. --- .../MuonSequentialFitDialog.ui | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui index 07d62e5ad6f2..916aca35a637 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui @@ -151,7 +151,7 @@ - + @@ -169,28 +169,18 @@ - - - false - + - Stop + Start - - false + + true - + false - - - - Start - - - From eb20d269bb30dd2d2976d2754cc792abc80cde38 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 11:57:18 +0000 Subject: [PATCH 017/403] Refs #6473. Enabling/disabling start button on input change. --- .../MuonSequentialFitDialog.h | 9 +++- .../src/MuonSequentialFitDialog.cpp | 41 ++++++++++++++++++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 79ea8bd07e68..a8de1c12ce2e 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -48,6 +48,9 @@ namespace MantidWidgets /// UI form Ui::MuonSequentialFitDialog ui; + /// Check if all the input field are valid + bool isInputValid(); + /// Checks if specified name is valid as a name for label. static std::string isValidLabel(const std::string& label); @@ -55,9 +58,11 @@ namespace MantidWidgets static Mantid::Kernel::Logger& g_log; private slots: - /// Updates visibility/tooltip of label error asterisk - void validateLabel(const QString& label); + void updateLabelError(const QString& label); + + /// Enables/disables start button depending on wether we are allowed to start. + void updateStartButton(); }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 15aa7c775f36..7212c292d2ca 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -18,8 +18,21 @@ namespace MantidWidgets { ui.setupUi(this); + // TODO: set initial values + + // After initial values are set, update depending elements accordingly. We don't rely on + // slot/signal update, as element might be left with default values which means these will + // never be called on initialication. + updateLabelError( ui.labelInput->text() ); + updateStartButton(); + + connect( ui.labelInput, SIGNAL( textChanged(const QString&) ), + this, SLOT( updateLabelError(const QString&) ) ); + connect( ui.labelInput, SIGNAL( textChanged(const QString&) ), - this, SLOT( validateLabel(const QString&) ) ); + this, SLOT( updateStartButton() ) ); + connect( ui.runs, SIGNAL( fileFindingFinished() ), + this, SLOT( updateStartButton() ) ); } /** @@ -39,7 +52,7 @@ namespace MantidWidgets * Updates visibility/tooltip of label error asterisk. * @param label :: New label as specified by user */ - void MuonSequentialFitDialog::validateLabel(const QString& label) + void MuonSequentialFitDialog::updateLabelError(const QString& label) { std::string error = isValidLabel( label.toStdString() ); @@ -47,6 +60,30 @@ namespace MantidWidgets ui.labelError->setToolTip( QString::fromStdString(error) ); } + /** + * Check if all the input field are valid. + * @return True if everything valid, false otherwise + */ + bool MuonSequentialFitDialog::isInputValid() + { + if ( ! ui.runs->isValid() ) + return false; + + std::string label = ui.labelInput->text().toStdString(); + if ( ! isValidLabel(label).empty() ) + return false; + + return true; + } + + /** + * Enables/disables start button depending on wether we are allowed to start. + */ + void MuonSequentialFitDialog::updateStartButton() + { + ui.controlButton->setEnabled( isInputValid() ); + } + /** * Destructor */ From cfce459cc846daebc889462ddb796c7beb34d129 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 12:11:01 +0000 Subject: [PATCH 018/403] Refs #6473. Renamed member variable according to rules. --- .../MuonSequentialFitDialog.h | 10 ++++++++-- .../src/MuonSequentialFitDialog.cpp | 20 +++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index a8de1c12ce2e..6731b083fa43 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -45,12 +45,18 @@ namespace MantidWidgets virtual ~MuonSequentialFitDialog(); private: - /// UI form - Ui::MuonSequentialFitDialog ui; + // -- FUNCTIONS ----------------------------------------------------------- /// Check if all the input field are valid bool isInputValid(); + // -- VARIABLES ----------------------------------------------------------- + + /// UI form + Ui::MuonSequentialFitDialog m_ui; + + // -- STATIC MEMBERS ------------------------------------------------------ + /// Checks if specified name is valid as a name for label. static std::string isValidLabel(const std::string& label); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 7212c292d2ca..4a2129c6ea79 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -16,22 +16,22 @@ namespace MantidWidgets MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : QDialog(parent) { - ui.setupUi(this); + m_ui.setupUi(this); // TODO: set initial values // After initial values are set, update depending elements accordingly. We don't rely on // slot/signal update, as element might be left with default values which means these will // never be called on initialication. - updateLabelError( ui.labelInput->text() ); + updateLabelError( m_ui.labelInput->text() ); updateStartButton(); - connect( ui.labelInput, SIGNAL( textChanged(const QString&) ), + connect( m_ui.labelInput, SIGNAL( textChanged(const QString&) ), this, SLOT( updateLabelError(const QString&) ) ); - connect( ui.labelInput, SIGNAL( textChanged(const QString&) ), + connect( m_ui.labelInput, SIGNAL( textChanged(const QString&) ), this, SLOT( updateStartButton() ) ); - connect( ui.runs, SIGNAL( fileFindingFinished() ), + connect( m_ui.runs, SIGNAL( fileFindingFinished() ), this, SLOT( updateStartButton() ) ); } @@ -56,8 +56,8 @@ namespace MantidWidgets { std::string error = isValidLabel( label.toStdString() ); - ui.labelError->setVisible( ! error.empty() ); - ui.labelError->setToolTip( QString::fromStdString(error) ); + m_ui.labelError->setVisible( ! error.empty() ); + m_ui.labelError->setToolTip( QString::fromStdString(error) ); } /** @@ -66,10 +66,10 @@ namespace MantidWidgets */ bool MuonSequentialFitDialog::isInputValid() { - if ( ! ui.runs->isValid() ) + if ( ! m_ui.runs->isValid() ) return false; - std::string label = ui.labelInput->text().toStdString(); + std::string label = m_ui.labelInput->text().toStdString(); if ( ! isValidLabel(label).empty() ) return false; @@ -81,7 +81,7 @@ namespace MantidWidgets */ void MuonSequentialFitDialog::updateStartButton() { - ui.controlButton->setEnabled( isInputValid() ); + m_ui.controlButton->setEnabled( isInputValid() ); } /** From f7212082d75327c5c53e5150962802974150c737 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 14:04:01 +0000 Subject: [PATCH 019/403] Refs #6473. Better function name. --- .../inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h | 5 +++-- .../MantidWidgets/src/MuonSequentialFitDialog.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 6731b083fa43..e920d1c7be39 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -67,8 +67,9 @@ namespace MantidWidgets /// Updates visibility/tooltip of label error asterisk void updateLabelError(const QString& label); - /// Enables/disables start button depending on wether we are allowed to start. - void updateStartButton(); + /// Enables/disables start button depending on wether we are allowed to start + void updateControlButtonState(); + }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 4a2129c6ea79..24e44434d944 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -24,15 +24,15 @@ namespace MantidWidgets // slot/signal update, as element might be left with default values which means these will // never be called on initialication. updateLabelError( m_ui.labelInput->text() ); - updateStartButton(); + updateControlButtonState(); connect( m_ui.labelInput, SIGNAL( textChanged(const QString&) ), this, SLOT( updateLabelError(const QString&) ) ); connect( m_ui.labelInput, SIGNAL( textChanged(const QString&) ), - this, SLOT( updateStartButton() ) ); + this, SLOT( updateControlButtonState() ) ); connect( m_ui.runs, SIGNAL( fileFindingFinished() ), - this, SLOT( updateStartButton() ) ); + this, SLOT( updateControlButtonState() ) ); } /** @@ -79,7 +79,7 @@ namespace MantidWidgets /** * Enables/disables start button depending on wether we are allowed to start. */ - void MuonSequentialFitDialog::updateStartButton() + void MuonSequentialFitDialog::updateControlButtonState() { m_ui.controlButton->setEnabled( isInputValid() ); } From 97d39ab48adc83ab9b33078023d6386d4670f216 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 14:04:38 +0000 Subject: [PATCH 020/403] Refs #6473. Control button logic. --- .../MuonSequentialFitDialog.h | 13 ++++++ .../src/MuonSequentialFitDialog.cpp | 40 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index e920d1c7be39..3c188706d007 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -45,11 +45,19 @@ namespace MantidWidgets virtual ~MuonSequentialFitDialog(); private: + enum ControlButtonType { + Start, + Stop + }; + // -- FUNCTIONS ----------------------------------------------------------- /// Check if all the input field are valid bool isInputValid(); + /// Set the type of the control button + void setControlButtonType(ControlButtonType type); + // -- VARIABLES ----------------------------------------------------------- /// UI form @@ -70,6 +78,11 @@ namespace MantidWidgets /// Enables/disables start button depending on wether we are allowed to start void updateControlButtonState(); + /// Start fitting process + void startFit(); + + /// Stop fitting process + void stopFit(); }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 24e44434d944..ed86f79038c8 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -14,11 +14,12 @@ namespace MantidWidgets * Constructor */ MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : - QDialog(parent) + QDialog(parent) { m_ui.setupUi(this); // TODO: set initial values + setControlButtonType(Start); // After initial values are set, update depending elements accordingly. We don't rely on // slot/signal update, as element might be left with default values which means these will @@ -84,6 +85,43 @@ namespace MantidWidgets m_ui.controlButton->setEnabled( isInputValid() ); } + /** + * Set the type of the control button. It is Start button when fitting has not been started, + * and Stop button when fitting is running. + * @param type :: New type of the button + */ + void MuonSequentialFitDialog::setControlButtonType(ControlButtonType type) + { + // Disconnect everything connected to pressed() signal of the button + disconnect( m_ui.controlButton, SIGNAL( pressed() ), 0, 0); + + // Connect to appropriate slot + auto buttonSlot = (type == Start) ? SLOT( startFit() ) : SLOT( stopFit() ); + connect( m_ui.controlButton, SIGNAL( pressed() ), this, buttonSlot ); + + // Set appropriate text + QString buttonText = (type == Start) ? "Start" : "Stop"; + m_ui.controlButton->setText(buttonText); + } + + /** + * Start fitting process. + */ + void MuonSequentialFitDialog::startFit() + { + g_log.notice("Seq. fitting started"); + setControlButtonType(Stop); + } + + /** + * Stop fitting process. + */ + void MuonSequentialFitDialog::stopFit() + { + g_log.notice("Seq. fitting stopped"); + setControlButtonType(Start); + } + /** * Destructor */ From e8786ba5b5ae3221ac0d1ad614f26b81e7a7926b Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 14:27:02 +0000 Subject: [PATCH 021/403] Refs #6473. Improved inputs alignment. --- .../MuonSequentialFitDialog.ui | 83 +++++++++++++++---- 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui index 916aca35a637..ce0433dfafbd 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.ui @@ -6,13 +6,19 @@ 0 0 - 500 + 550 500 + + + 0 + 0 + + - 500 + 550 500 @@ -52,6 +58,9 @@ Runs: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -65,6 +74,9 @@ Label: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -127,26 +139,60 @@ - - - - - - + + + + + 0 + 0 + + - Parameters from previous fit + Parameters: - - true + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - Initial parameters for every fit - - + + + + + + + 0 + 0 + + + + Values from previous fit + + + true + + + paramTypeGroup + + + + + + + + 0 + 0 + + + + Initial values for every fit + + + paramTypeGroup + + + + @@ -218,4 +264,7 @@ + + + From afbef9ee13afe17af31716d18835447f518a4182 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 14:27:34 +0000 Subject: [PATCH 022/403] Refs #6473. Disabling input widgets when running. --- .../MuonSequentialFitDialog.h | 3 +++ .../MantidWidgets/src/MuonSequentialFitDialog.cpp | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 3c188706d007..a3aae88288a2 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -58,6 +58,9 @@ namespace MantidWidgets /// Set the type of the control button void setControlButtonType(ControlButtonType type); + /// Update enabled state off all the input widgets (except for control ones) + void setInputEnabled(bool enabled); + // -- VARIABLES ----------------------------------------------------------- /// UI form diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index ed86f79038c8..59def9c4d0e1 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -104,6 +104,19 @@ namespace MantidWidgets m_ui.controlButton->setText(buttonText); } + /** * Update enabled state off all the input widgets (except for control ones). + * @param enabled :: True if widgets should be enabled, false otherwise + */ + void MuonSequentialFitDialog::setInputEnabled(bool enabled) + { + m_ui.runs->setEnabled(enabled); + m_ui.labelInput->setEnabled(enabled); + + foreach(QAbstractButton* button, m_ui.paramTypeGroup->buttons()) + button->setEnabled(enabled); + + } + /** * Start fitting process. */ @@ -111,6 +124,7 @@ namespace MantidWidgets { g_log.notice("Seq. fitting started"); setControlButtonType(Stop); + setInputEnabled(false); } /** @@ -120,6 +134,7 @@ namespace MantidWidgets { g_log.notice("Seq. fitting stopped"); setControlButtonType(Start); + setInputEnabled(true); } /** From 16514f470880f01937eca6a9ae5803df5bde387e Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 20 Nov 2013 14:57:17 +0000 Subject: [PATCH 023/403] Minor cleanup of creation of simulated convolved MD workspace. Refs #8416 --- .../SimulateResolutionConvolvedModel.h | 2 - .../SimulateResolutionConvolvedModel.cpp | 48 ++----------------- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/SimulateResolutionConvolvedModel.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/SimulateResolutionConvolvedModel.h index 6d4701f1a14c..65a2ee3bbf81 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/SimulateResolutionConvolvedModel.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/SimulateResolutionConvolvedModel.h @@ -56,8 +56,6 @@ namespace Mantid void createDomains(); /// Generate the output MD workspace that is a result of the simulation void createOutputWorkspace(); - /// Add the simulated events - void addSimulatedEvents(); /// The input workspace API::IMDEventWorkspace_sptr m_inputWS; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp index d3545c3f12d0..feec7cde3c4c 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp @@ -165,6 +165,9 @@ namespace Mantid m_outputWS = boost::shared_ptr(new QOmegaWorkspace); // Bins extents and meta data + // Set sensible defaults for splitting behaviour + BoxController_sptr bc = m_outputWS->getBoxController(); + bc->setSplitThreshold(3000); for(size_t i = 0;i < 4; ++i) { boost::shared_ptr inputDim = m_inputWS->getDimension(i); @@ -173,61 +176,18 @@ namespace Mantid builder.setId(inputDim->getDimensionId()); builder.setUnits(inputDim->getUnits()); builder.setNumBins(inputDim->getNBins()); + bc->setSplitInto(i, inputDim->getNBins()); builder.setMin(inputDim->getMinimum()); builder.setMax(inputDim->getMaximum()); m_outputWS->addDimension(builder.create()); } - // Run information m_outputWS->copyExperimentInfos(*m_inputWS); - // Set sensible defaults for splitting behaviour - BoxController_sptr bc = m_outputWS->getBoxController(); - bc->setSplitInto(3); - bc->setSplitThreshold(3000); m_outputWS->initialize(); m_outputWS->splitBox(); // Make grid box } - /** - * Adds simulated events to the output workspace - */ - void SimulateResolutionConvolvedModel::addSimulatedEvents() - { - auto inputIter = m_inputWS->createIterator(); - size_t resultValueIndex(0); - const float errorSq = 0.0; - do - { - const size_t numEvents = inputIter->getNumEvents(); - const float signal = static_cast(m_calculatedValues->getCalculated(resultValueIndex)); - for(size_t i = 0; i < numEvents; ++i) - { - coord_t centers[4] = { inputIter->getInnerPosition(i,0), inputIter->getInnerPosition(i,1), - inputIter->getInnerPosition(i,2), inputIter->getInnerPosition(i,3) }; - m_outputWS->addEvent(MDEvent<4>(signal, errorSq, - inputIter->getInnerRunIndex(i), - inputIter->getInnerDetectorID(i), - centers)); - } - ++resultValueIndex; - } - while(inputIter->next()); - delete inputIter; - - API::MemoryManager::Instance().releaseFreeMemory(); - // This splits up all the boxes according to split thresholds and sizes. - auto threadScheduler = new Kernel::ThreadSchedulerFIFO(); - Kernel::ThreadPool threadPool(threadScheduler); - m_outputWS->splitAllIfNeeded(threadScheduler); - threadPool.joinAll(); - m_outputWS->refreshCache(); - - // Flush memory - API::MemoryManager::Instance().releaseFreeMemory(); - } - - } // namespace MDAlgorithms } // namespace Mantid From c56a28d8d57d9151af92615fbb831a59ca3bb968 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 20 Nov 2013 14:58:54 +0000 Subject: [PATCH 024/403] Foreground model now assumes input Q is in the lab frame, not sample. Refs #8416 --- .../MDAlgorithms/src/Quantification/Models/Strontium122.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp index 229a8f16bd9a..fce19c33f704 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp @@ -89,7 +89,7 @@ namespace Mantid // qhkl = (1/2pi)(RB)^-1(qxyz) const Geometry::OrientedLattice & lattice = exptSetup.sample().getOrientedLattice(); const Kernel::DblMatrix & gr = exptSetup.run().getGoniometerMatrix(); - const Kernel::DblMatrix & bmat = lattice.getB(); + const Kernel::DblMatrix & bmat = lattice.getUB(); // Avoid doing inversion with Matrix class as it forces memory allocations // M^-1 = (1/|M|)*M^T From 4d8680733ce65d0d034f6ac6d3d79a8f732879ee Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 20 Nov 2013 15:13:21 +0000 Subject: [PATCH 025/403] Refs #6473. Initializing the diagnosis table. Columns for all the parameters are added. --- .../MuonSequentialFitDialog.h | 10 +++++- .../src/MuonSequentialFitDialog.cpp | 32 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index a3aae88288a2..01ec2019017b 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -6,6 +6,8 @@ #include "ui_MuonSequentialFitDialog.h" +#include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" + #include namespace MantidQt @@ -41,7 +43,7 @@ namespace MantidWidgets Q_OBJECT public: - MuonSequentialFitDialog(QWidget* parent); + MuonSequentialFitDialog(MuonFitPropertyBrowser* parent); virtual ~MuonSequentialFitDialog(); private: @@ -61,11 +63,17 @@ namespace MantidWidgets /// Update enabled state off all the input widgets (except for control ones) void setInputEnabled(bool enabled); + /// Initialize diagnosis table + void initDiagnosisTable(); + // -- VARIABLES ----------------------------------------------------------- /// UI form Ui::MuonSequentialFitDialog m_ui; + /// Fit properties browser used to start the dialog + MuonFitPropertyBrowser* m_fitPropBrowser; + // -- STATIC MEMBERS ------------------------------------------------------ /// Checks if specified name is valid as a name for label. diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 59def9c4d0e1..b616ed96a55b 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -1,4 +1,6 @@ #include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" +#include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" + #include "MantidAPI/AnalysisDataService.h" namespace MantidQt @@ -13,14 +15,16 @@ namespace MantidWidgets /** * Constructor */ - MuonSequentialFitDialog::MuonSequentialFitDialog(QWidget* parent) : - QDialog(parent) + MuonSequentialFitDialog::MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser) : + QDialog(fitPropBrowser), m_fitPropBrowser(fitPropBrowser) { m_ui.setupUi(this); // TODO: set initial values setControlButtonType(Start); + initDiagnosisTable(); + // After initial values are set, update depending elements accordingly. We don't rely on // slot/signal update, as element might be left with default values which means these will // never be called on initialication. @@ -49,6 +53,30 @@ namespace MantidWidgets return AnalysisDataService::Instance().isValid(label); } + /** + * Initialize diagnosis table. + */ + void MuonSequentialFitDialog::initDiagnosisTable() + { + QStringList headerLabels; + + // Add two static columns + headerLabels << "Run" << "Fit quality"; + + // Add remaining columns - one for every fit function parameter + CompositeFunction_const_sptr fitFunc = m_fitPropBrowser->compositeFunction(); + + for(size_t i = 0; i < fitFunc->nParams(); i++) + headerLabels << QString::fromStdString( fitFunc->parameterName(i) ); + + m_ui.diagnosisTable->setColumnCount( headerLabels.size() ); + m_ui.diagnosisTable->setHorizontalHeaderLabels(headerLabels); + + // Make the table fill all the available space + QHeaderView* header = m_ui.diagnosisTable->horizontalHeader(); + header->setResizeMode(QHeaderView::Stretch); + } + /** * Updates visibility/tooltip of label error asterisk. * @param label :: New label as specified by user From 172f80565bdd1ba4d0a0ff1826a1a93753cc0d13 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 21 Nov 2013 15:29:49 -0500 Subject: [PATCH 026/403] Made the new feature work. Refs #8472. --- .../MantidCurveFitting/ProcessBackground.h | 8 +- .../CurveFitting/src/ProcessBackground.cpp | 164 ++++++++++++++++-- 2 files changed, 158 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ProcessBackground.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ProcessBackground.h index d913150a75df..765054cfe07b 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ProcessBackground.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ProcessBackground.h @@ -101,7 +101,7 @@ class DLLExport ProcessBackground : public API::Algorithm DataObjects::Workspace2D_sptr autoBackgroundSelection(DataObjects::Workspace2D_sptr bkgdWS); /// Create a background function from input properties - BackgroundFunction_sptr createBackgroundFunction(); + BackgroundFunction_sptr createBackgroundFunction(const std::string backgroundtype); /// Filter non-background data points out and create a background workspace DataObjects::Workspace2D_sptr filterForBackground(BackgroundFunction_sptr bkgdfunction); @@ -114,6 +114,10 @@ class DLLExport ProcessBackground : public API::Algorithm double m_lowerBound; double m_upperBound; + std::string m_bkgdType; + + bool m_doFitBackground; + // double mTolerance; /// Number of FWHM of range of peak to be removed. @@ -127,6 +131,8 @@ class DLLExport ProcessBackground : public API::Algorithm /// Add a certain region from a reference workspace void addRegion(); + + void fitBackgroundFunction(std::string bkgdfunctiontype); }; diff --git a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp index a31b1fecc68f..b14940a659e5 100644 --- a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp @@ -179,20 +179,23 @@ DECLARE_ALGORITHM(ProcessBackground) new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); // Optional output workspace - // TODO - Implement more upon this option! - declareProperty(new WorkspaceProperty("OutputBackgroundParameterTable", "", Direction::Output, - PropertyMode::Optional), - "Output .... ... ."); + declareProperty(new WorkspaceProperty("OutputBackgroundParameterTable", "", Direction::Output, + PropertyMode::Optional), + "Output parameter table workspace containing the background fitting result. "); setPropertySettings("OutputBackgroundParameterTable", new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); - // TODO - Develop from this new option // Output background type. declareProperty("OutputBackgroundType", "Polynomial", bkgdvalidator, - "Type of background to fit with selected ... ."); + "Type of background to fit with selected background points."); setPropertySettings("OutputBackgroundType", new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); + // Output background type. + declareProperty("OutputBackgroundOrder", 6, + "Order of background to fit with selected background points."); + setPropertySettings("OutputBackgroundOrder", + new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); // Peak table workspac for "RemovePeaks" declareProperty(new WorkspaceProperty("BraggPeakTableWorkspace", "", Direction::Input, @@ -222,6 +225,8 @@ DECLARE_ALGORITHM(ProcessBackground) throw std::invalid_argument("Input Workspace cannot be obtained."); } + m_bkgdType = getPropertyValue("BackgroundType"); + int intemp = getProperty("WorkspaceIndex"); if (intemp < 0) throw std::invalid_argument("WorkspaceIndex is not allowed to be less than 0. "); @@ -252,6 +257,17 @@ DECLARE_ALGORITHM(ProcessBackground) } else if (option.compare("SelectBackgroundPoints") == 0) { + string outbkgdparwsname = getPropertyValue("OutputBackgroundParameterTable"); + if (outbkgdparwsname.size() > 0) + { + // Will fit the selected background + m_doFitBackground = true; + } + else + { + m_doFitBackground = false; + } + string smode = getProperty("SelectionMode"); if (smode == "FitGivenDataPoints") { @@ -265,6 +281,14 @@ DECLARE_ALGORITHM(ProcessBackground) { throw runtime_error("N/A is not supported."); } + + if (m_doFitBackground) + { + // Fit the selected background + string bkgdfunctype = getPropertyValue("OutputBackgroundType"); + fitBackgroundFunction(bkgdfunctype); + } + } else { @@ -648,7 +672,7 @@ DECLARE_ALGORITHM(ProcessBackground) void ProcessBackground::execSelectBkgdPoints2() { // Process properties - BackgroundFunction_sptr bkgdfunc = createBackgroundFunction(); + BackgroundFunction_sptr bkgdfunc = createBackgroundFunction(m_bkgdType); TableWorkspace_sptr bkgdtablews = getProperty("BackgroundTableWorkspace"); // Set up background function from table @@ -686,7 +710,7 @@ DECLARE_ALGORITHM(ProcessBackground) DataObjects::Workspace2D_sptr ProcessBackground::autoBackgroundSelection(Workspace2D_sptr bkgdWS) { // Get background type and create bakground function - BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(); + BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(m_bkgdType); int bkgdorder = getProperty("BackgroundOrder"); bkgdfunction->setAttributeValue("n", bkgdorder); @@ -759,10 +783,8 @@ DECLARE_ALGORITHM(ProcessBackground) //---------------------------------------------------------------------------------------------- /** Create a background function from input properties */ - BackgroundFunction_sptr ProcessBackground::createBackgroundFunction() + BackgroundFunction_sptr ProcessBackground::createBackgroundFunction(const string backgroundtype) { - std::string backgroundtype = getProperty("BackgroundType"); - CurveFitting::BackgroundFunction_sptr bkgdfunction; if (backgroundtype.compare("Polynomial") == 0) @@ -858,12 +880,19 @@ DECLARE_ALGORITHM(ProcessBackground) << " total data points. " << "\n"; // Build new workspace + size_t nspec; + if (m_doFitBackground) + nspec = 3; + else + nspec = 1; + Workspace2D_sptr outws = boost::dynamic_pointer_cast - (API::WorkspaceFactory::Instance().create("Workspace2D", 1, vecx.size(), vecy.size())); + (API::WorkspaceFactory::Instance().create("Workspace2D", nspec, vecx.size(), vecy.size())); for (size_t i = 0; i < vecx.size(); ++i) { - outws->dataX(0)[i] = vecx[i]; + for(size_t j = 0; j < nspec; ++j) + outws->dataX(j)[i] = vecx[i]; outws->dataY(0)[i] = vecy[i]; outws->dataE(0)[i] = vece[i]; } @@ -1060,6 +1089,115 @@ DECLARE_ALGORITHM(ProcessBackground) return count; } + //---------------------------------------------------------------------------------------------- + /** Fit background function + */ + void ProcessBackground::fitBackgroundFunction(std::string bkgdfunctiontype) + { + // Get background type and create bakground function + BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(bkgdfunctiontype); + + int bkgdorder = getProperty("OutputBackgroundOrder"); + bkgdfunction->setAttributeValue("n", bkgdorder); + + if (bkgdfunctiontype == "Chebyshev") + { + double xmin = m_outputWS->readX(0).front(); + double xmax = m_outputWS->readX(0).back(); + g_log.information() << "Chebyshev Fit range: " << xmin << ", " << xmax << "\n"; + bkgdfunction->setAttributeValue("StartX", xmin); + bkgdfunction->setAttributeValue("EndX", xmax); + } + + g_log.information() << "Fit selected background " << bkgdfunctiontype + << " to data workspace with " << m_outputWS->getNumberHistograms() << " spectra." + << "\n"; + + // Fit input (a few) background pionts to get initial guess + API::IAlgorithm_sptr fit; + try + { + fit = this->createChildAlgorithm("Fit", 0.9, 1.0, true); + } + catch (Exception::NotFoundError &) + { + g_log.error() << "Requires CurveFitting library." << std::endl; + throw; + } + + g_log.information() << "Fitting background function: " << bkgdfunction->asString() << "\n"; + + double startx = m_lowerBound; + double endx = m_upperBound; + fit->setProperty("Function", boost::dynamic_pointer_cast(bkgdfunction)); + fit->setProperty("InputWorkspace", m_outputWS); + fit->setProperty("WorkspaceIndex", 0); + fit->setProperty("MaxIterations", 500); + fit->setProperty("StartX", startx); + fit->setProperty("EndX", endx); + fit->setProperty("Minimizer", "Levenberg-MarquardtMD"); + fit->setProperty("CostFunction", "Least squares"); + + fit->executeAsChildAlg(); + + // Get fit status and chi^2 + std::string fitStatus = fit->getProperty("OutputStatus"); + bool allowedfailure = (fitStatus.find("cannot") < fitStatus.size()) && + (fitStatus.find("tolerance") < fitStatus.size()); + if (fitStatus.compare("success") != 0 && !allowedfailure) + { + g_log.error() << "ProcessBackground: Fit Status = " << fitStatus + << ". Not to update fit result" << std::endl; + throw std::runtime_error("Bad Fit"); + } + + const double chi2 = fit->getProperty("OutputChi2overDoF"); + g_log.information() << "Fit background: Fit Status = " << fitStatus << ", chi2 = " + << chi2 << "\n"; + + // Get out the parameter names + API::IFunction_sptr funcout = fit->getProperty("Function"); + TableWorkspace_sptr outbkgdparws = boost::make_shared(); + outbkgdparws->addColumn("str", "Name"); + outbkgdparws->addColumn("double", "Value"); + + TableRow typerow = outbkgdparws->appendRow(); + typerow << bkgdfunctiontype << 0.; + + vector parnames = funcout->getParameterNames(); + size_t nparam = funcout->nParams(); + for (size_t i = 0; i < nparam; ++i) + { + TableRow newrow = outbkgdparws->appendRow(); + newrow << parnames[i] << funcout->getParameter(i); + } + + TableRow chi2row = outbkgdparws->appendRow(); + chi2row << "Chi-square" << chi2; + + g_log.information() << "Set table workspace (#row = " << outbkgdparws->rowCount() + << ") to OutputBackgroundParameterTable. " << "\n"; + setProperty("OutputBackgroundParameterTable", outbkgdparws); + + // Set output workspace + const MantidVec& vecX = m_outputWS->readX(0); + const MantidVec& vecY = m_outputWS->readY(0); + FunctionDomain1DVector domain(vecX); + FunctionValues values(domain); + + funcout->function(domain, values); + + MantidVec& dataModel = m_outputWS->dataY(1); + MantidVec& dataDiff = m_outputWS->dataY(2); + for (size_t i = 0; i < dataModel.size(); ++i) + { + dataModel[i] = values[i]; + dataDiff[i] = vecY[i] - dataModel[i]; + } + + return; + } + } // namespace CurveFitting } // namespace Mantid From 1b78d72d8a171f11b8ffe0b49c09ce70fa52f552 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 21 Nov 2013 15:30:13 -0500 Subject: [PATCH 027/403] Expanded unit test for new feature. Refs #8472. --- .../CurveFitting/test/ProcessBackgroundTest.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h index 9726c5c19319..01515710aa60 100644 --- a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h @@ -27,7 +27,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite /** Test option delete region */ - void test_DeleteRegion() + void Ptest_DeleteRegion() { // 1. Create Workspace2D DataObjects::Workspace2D_sptr inpws @@ -70,7 +70,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite /** Test option "Add Region" */ - void test_AddRegion() + void Ptest_AddRegion() { // 1. Create Workspace2D DataObjects::Workspace2D_sptr inpws @@ -174,7 +174,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite //---------------------------------------------------------------------------------------------- /** Test automatic background selection */ - void test_SimpleBackgroundGeneration() + void Ptest_SimpleBackgroundGeneration() { // 1. Prepare for data @@ -245,7 +245,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite DataObjects::Workspace2D_sptr dataws = boost::dynamic_pointer_cast (API::WorkspaceFactory::Instance().create("Workspace2D", 1, 1000, 1000)); - for (size_t i = 0; i < 10; ++i) + for (size_t i = 0; i < 1000; ++i) { dataws->dataX(0)[i] = double(i); dataws->dataY(0)[i] = double(i)*double(i)+sin(double(i)/180.*3.14); @@ -277,6 +277,10 @@ class ProcessBackgroundTest : public CxxTest::TestSuite alg.setProperty("SelectionMode", "UserFunction"); alg.setProperty("BackgroundTableWorkspace", functablews); + alg.setProperty("OutputBackgroundParameterTable", "OutBackgroundParameters"); + alg.setProperty("OutputBackgroundType", "Chebyshev"); + alg.setProperty("OutputBackgroundOrder", 6); + alg.setProperty("NoiseTolerance", 0.25); TS_ASSERT_THROWS_NOTHING(alg.execute()); @@ -290,8 +294,13 @@ class ProcessBackgroundTest : public CxxTest::TestSuite if (bkgdws) { TS_ASSERT(bkgdws->readX(0).size() > 10); + TS_ASSERT_EQUALS(bkgdws->getNumberHistograms(), 3); } + TableWorkspace_sptr bkgdparws = boost::dynamic_pointer_cast( + API::AnalysisDataService::Instance().retrieve("OutBackgroundParameters")); + TS_ASSERT(bkgdparws); + AnalysisDataService::Instance().remove("DiffractionData2"); AnalysisDataService::Instance().remove("SelectedBackgroundPoints2"); AnalysisDataService::Instance().remove("BackgroundParameters"); From 95e6bdf77aaddb0ff722ff692885df4e1f61e009 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 21 Nov 2013 16:56:23 -0500 Subject: [PATCH 028/403] Renamed a property b/c python. Refs #8472. --- .../Framework/CurveFitting/src/ProcessBackground.cpp | 8 ++++---- .../Framework/CurveFitting/test/ProcessBackgroundTest.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp index b14940a659e5..dc47b339dbc1 100644 --- a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp @@ -179,10 +179,10 @@ DECLARE_ALGORITHM(ProcessBackground) new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); // Optional output workspace - declareProperty(new WorkspaceProperty("OutputBackgroundParameterTable", "", Direction::Output, + declareProperty(new WorkspaceProperty("OutputBackgroundParameterWorkspace", "", Direction::Output, PropertyMode::Optional), "Output parameter table workspace containing the background fitting result. "); - setPropertySettings("OutputBackgroundParameterTable", + setPropertySettings("OutputBackgroundParameterWorkspace", new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); // Output background type. @@ -257,7 +257,7 @@ DECLARE_ALGORITHM(ProcessBackground) } else if (option.compare("SelectBackgroundPoints") == 0) { - string outbkgdparwsname = getPropertyValue("OutputBackgroundParameterTable"); + string outbkgdparwsname = getPropertyValue("OutputBackgroundParameterWorkspace"); if (outbkgdparwsname.size() > 0) { // Will fit the selected background @@ -1177,7 +1177,7 @@ DECLARE_ALGORITHM(ProcessBackground) g_log.information() << "Set table workspace (#row = " << outbkgdparws->rowCount() << ") to OutputBackgroundParameterTable. " << "\n"; - setProperty("OutputBackgroundParameterTable", outbkgdparws); + setProperty("OutputBackgroundParameterWorkspace", outbkgdparws); // Set output workspace const MantidVec& vecX = m_outputWS->readX(0); diff --git a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h index 01515710aa60..b928cc2b98e1 100644 --- a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h @@ -277,7 +277,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite alg.setProperty("SelectionMode", "UserFunction"); alg.setProperty("BackgroundTableWorkspace", functablews); - alg.setProperty("OutputBackgroundParameterTable", "OutBackgroundParameters"); + alg.setProperty("OutputBackgroundParameterWorkspace", "OutBackgroundParameters"); alg.setProperty("OutputBackgroundType", "Chebyshev"); alg.setProperty("OutputBackgroundOrder", 6); From 64a359f0f2f4a267df8c354fb790b9ffa35fdf14 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 22 Nov 2013 11:22:05 -0500 Subject: [PATCH 029/403] Removed background option FullprofPolynomial. Refs #8472. --- .../Framework/CurveFitting/src/ProcessBackground.cpp | 8 ++++++-- .../CurveFitting/test/ProcessBackgroundTest.h | 12 +++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp index dc47b339dbc1..18d7a95bd3c6 100644 --- a/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/ProcessBackground.cpp @@ -109,7 +109,7 @@ DECLARE_ALGORITHM(ProcessBackground) std::vector bkgdtype; bkgdtype.push_back("Polynomial"); bkgdtype.push_back("Chebyshev"); - bkgdtype.push_back("FullprofPolynomial"); + // bkgdtype.push_back("FullprofPolynomial"); auto bkgdvalidator = boost::make_shared(bkgdtype); declareProperty("BackgroundType", "Polynomial", bkgdvalidator, "Type of the background. Options include Polynomial and Chebyshev."); @@ -186,7 +186,11 @@ DECLARE_ALGORITHM(ProcessBackground) new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); // Output background type. - declareProperty("OutputBackgroundType", "Polynomial", bkgdvalidator, + std::vector outbkgdtype; + outbkgdtype.push_back("Polynomial"); + outbkgdtype.push_back("Chebyshev"); + auto outbkgdvalidator = boost::make_shared(bkgdtype); + declareProperty("OutputBackgroundType", "Polynomial", outbkgdvalidator, "Type of background to fit with selected background points."); setPropertySettings("OutputBackgroundType", new VisibleWhenProperty("Options", IS_EQUAL_TO, "SelectBackgroundPoints")); diff --git a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h index b928cc2b98e1..94b58c3fd4b2 100644 --- a/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/ProcessBackgroundTest.h @@ -27,7 +27,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite /** Test option delete region */ - void Ptest_DeleteRegion() + void test_DeleteRegion() { // 1. Create Workspace2D DataObjects::Workspace2D_sptr inpws @@ -70,7 +70,7 @@ class ProcessBackgroundTest : public CxxTest::TestSuite /** Test option "Add Region" */ - void Ptest_AddRegion() + void test_AddRegion() { // 1. Create Workspace2D DataObjects::Workspace2D_sptr inpws @@ -174,14 +174,8 @@ class ProcessBackgroundTest : public CxxTest::TestSuite //---------------------------------------------------------------------------------------------- /** Test automatic background selection */ - void Ptest_SimpleBackgroundGeneration() + void test_SimpleBackgroundGeneration() { - - // 1. Prepare for data - /* - std::string datafile("/home/wzz/Mantid/Code/debug/MyTestData/4862b7.inp"); - DataObjects::Workspace2D_sptr dataws = createWorkspace2D(datafile); - */ // 1. Create Workspace2D DataObjects::Workspace2D_sptr dataws = boost::dynamic_pointer_cast From 16c6206f7f05d91dfaa418486f142695cd618472 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 22 Nov 2013 12:05:23 -0500 Subject: [PATCH 030/403] Finished the implementation. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 467 ++++++++++++++---- 1 file changed, 376 insertions(+), 91 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index ca2e8c986dd3..c2f4aeca068f 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -44,6 +44,8 @@ def PyInit(self): self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, PropertyMode.Optional), "Name of data workspace containing the diffraction pattern in .prf file. ") + self.declareProperty("WorkspaceIndex", 0, "Spectrum (workspace index starting from 0) of the data to refine against in input workspace.") + self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional), "Name of table workspace containing sequential refinement information.") @@ -59,11 +61,11 @@ def PyInit(self): self.declareProperty("StartX", -0., "Start X (TOF) to refine diffraction pattern.") self.declareProperty("EndX", -0., "End X (TOF) to refine diffraction pattern.") - funcoptions = ["Setup", "Refine"] - self.declareProperty("FunctionOption", "Refine-Levenberg", StringListValidator(funcoptions), "Options of functionality") + funcoptions = ["Setup", "Refine", "Save", "Load"] + self.declareProperty("FunctionOption", "Refine", StringListValidator(funcoptions), "Options of functionality") refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] - self.declareProperty("RefinementOption", "Refine-Levenberg", StringListValidator(refoptions), + self.declareProperty("RefinementOption", "Random Walk", StringListValidator(refoptions), "Options of algorithm to refine. ") self.declareProperty(StringArrayProperty("Parameters2Refine", values=[], direction=Direction.Input), @@ -71,9 +73,22 @@ def PyInit(self): self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") - bkgdtypes = ["Polynomial", "Chebyshev", "FullprofPolynomial"] - self.declareProperty("BackgroundType", "Polynomial", StringListValidator(bkgdtypes), - "Type of background function.") + peaktypes = ["", "Neutron Back-to-back exponential convoluted with psuedo-voigt", + "Thermal neutron Back-to-back exponential convoluted with psuedo-voigt"] + self.declareProperty("ProfileType", "", StringListValidator(peaktypes), "Type of peak profile function.") + + bkgdtypes = ["", "Polynomial", "Chebyshev", "FullprofPolynomial"] + self.declareProperty("BackgroundType", "", StringListValidator(bkgdtypes), "Type of background function.") + + self.declareProperty("FromStep", -1, "If non-negative, the previous code is not set from last step, but the step specified.") + + # Property for save project + self.declareProperty(FileProperty("OutputProjectFilename","", FileAction.OptionalSave, ['.nxs']), + "Name of sequential project file.") + + # Property for save project + self.declareProperty(FileProperty("InputProjectFilename","", FileAction.OptionalLoad, ['.nxs']), + "Name of sequential project file.") return @@ -93,14 +108,25 @@ def PyExec(self): if seqrefine.isSetup() is True: raise NotImplementedError("Impossible to have it set up already.") - seqrefine.initSetup(self.dataws, self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, + seqrefine.initSetup(self.dataws, self.wsindex, self.peaktype, self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, self.startx, self.endx) elif self.functionoption == "Refine": # Refine if seqrefine.isSetup() is False: raise NotImplementedError("Exception because sequential refinement is not set up.") - seqrefine.refine(self.paramstofit, self.numcycles, self.startx, self.endx) + seqrefine.refine(self.dataws, self.wsindex, self.paramstofit, self.numcycles, self.startx, self.endx, self._lastStep) + + elif self.functionoption == "Save": + # Save the current state to a project file + seqrefine.saveProject(str(self.dataws), self.wsindex, self.outprojectfilename) + + elif self.functionoption == "Load": + # Set up from an exiting project file + if seqrefine.isSetup() is True: + raise NotImplementedError("Impossible to have it set up already.") + + seqrefine.loadProject(self.inprojectfilename) else: # None-support @@ -112,27 +138,55 @@ def PyExec(self): def _processInputProperties(self): """ Process input properties """ + # Input data workspace and related self.dataws = self.getProperty("InputWorkspace").value - self.datawsname = str(self.dataws) + self.wsindex = self.getProperty("WorkspaceIndex").value self.startx = self.getProperty("StartX").value self.endx = self.getProperty("EndX").value + self._lastStep = self.getProperty("FromStep").value + self.functionoption = self.getProperty("FunctionOption").value if self.functionoption == "Setup": + ptype = self.getProperty("ProfileType").value + if ptype == "Neutron Back-to-back exponential convoluted with psuedo-voigt": + self.peaktype = "NeutronBk2BkExpConvPVoigt" + elif ptype == "Thermal neutron Back-to-back exponential convoluted with psuedo-voigt": + self.peaktype = "ThermalNeutronBk2BkExpConvPVoigt" + else: + raise NotImplementedError("Peak profile is not supported.") + self.bkgdtype = self.getProperty("BackgroundType").value self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value self.profilews = self.getProperty("InputProfileWorkspace").value self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value - elif self.functionoptions == "Refine": + elif self.functionoption == "Refine": self.paramstofit = self.getProperty("Parameters2Refine").value - self.numcycles = self.Property("NumRefineCycle").value + self.numcycles = self.getProperty("NumRefineCycles").value + + elif self.functionoption == "Save": + self.outprojectfilename = self.getProperty("OutputProjectFilename").value + elif self.functionoption == "Load": + self.inprojectfilename = self.getProperty("InputProjectFilename").value + + else: + raise NotImplementedError("Unsupported function mode %s. " % (self.functionoption)) + + if self.functionoption != "Load": + self.datawsname = str(self.dataws) + if self.wsindex < 0 or self.wsindex >= self.dataws.getNumberHistograms(): + raise NotImplementedError("Input workspace index %d is out of range (0, %d)." % + (self.wsindex, self.dataws.getNumberHistograms())) return #-------------------------------------------------------------------- +# +#-------------------------------------------------------------------- + class SeqRefineProfile: """ A class to do sequential refinement on peak profile @@ -146,25 +200,50 @@ class SeqRefineProfile: def __init__(self, ID, glog): """ """ - self._ID = str(ID) + # Set up log self.glog = glog + + # Set up ID + self._ID = str(ID) self.glog.information("SeqRefineProfile is initialized with ID = %s" % (str(ID))) - + + # Standard record table and check its existence self._recordwsname = "Record%sTable" % (str(ID)) + self.glog.notice("Using record table %s" % (self._recordwsname)) + + if AnalysisDataService.doesExist(self._recordwsname): + # Record workspace exists: has been set up + self._isSetup = True + else: + # Record workspace does not exist: first time or need to load from file + self._isSetup = False - self._isSetup = False - self._lastrowinvalid = False + self._recordWSLastRowInvalid = False + + # Result workspace group + self._wsgroupName = self._ID + "_Group" + if AnalysisDataService.doesExist(self._wsgroupName): + self._wsgroupCreated = True + else: + self._wsgroupCreated = False return - def initSetup(self, dataws, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): - """ Set up the properties for LeBailFit as the first time + + def initSetup(self, dataws, wsindex, peaktype, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): + """ Set up the properties for LeBailFit as the first time including + do a Le bail calculation based on the input parameters including profilews, braggpeakws, and etc """ - # Data + # Data and data range self._datawsname = str(dataws) + if startx <= 0.: + startx = dataws.readX(wsindex)[0] + if endx <= 0.: + endx = dataws.readX(wsindex)[-1] # Profile + self._peakType = peaktype self._profileWS = profilews self._braggpeakws = braggpeakws self._bkgdtype = bkgdtype @@ -176,68 +255,122 @@ def initSetup(self, dataws, profilews, braggpeakws, bkgdtype, bkgdparws, startx, # Check input parameters, i.e., verification/examine input parameters runner = RefineProfileParameters(self.glog) - runner.startx = startx - runner.endx = endx + outwsname = self._datawsname+"_Init" - # runner.inprofilewsname = self._profileWS - # runner.inreflectionwsname = self._braggpeakws + runner.setInputs(self._datawsname, self._peakType, self._profileWS, self._braggpeakws, self._bkgdtype, self._bkgdparws) + # FIXME - Need to verify whether input and output background parameter ws name can be same + runner.setOutputs(outwsname, self._profileWS, self._braggpeakws, self._bkgdparws) + + self._recordPreRefineInfo(runner, -1) + runner.calculate(startx, endx) + self._recordPostRefineInfo(runner) - # runner.bkgdtype = self._bkgdtype - # runner.bkgdtablewsname = self._bkgdparws + # Group the newly generated workspace and do some record + api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, self._profileWS, self._braggpeakws, self._bkgdparws), + OutputWorkspace=self._wsgroupName) + self._wsgroupCreated = True - # runner.outprofilewsname = self._profileWS - # runner.outreflectionwsname = self._braggpeakws + # Repository - outwsname = "InitTemp" + # Replace 'Refine' of step 0 to ID (it is always empty) + self._recordws.setCell(0, 5, self._ID) + # Replace 'InputProfileWorkspace' by profile type (it is alwasy same as output) + self._recordws.setCell(0, 9, self._peakType) - runner.setInputs(self._datawsname, self._profileWS, self._braggpeakws, self._bkgdtype, self._bkgdparws) - # FIXME - Need to verify whether input and output background parameter ws name can be same - runner.setOutputs(outwsname, self._profileWS, self._braggpeakws, self._bkgdparws) + self._isSetup = True - self._recordPreRefineInfo(runner) - runner.calculate(runner.startx, runner.endx) - self._recordPostRefineInfo(runner) + return + + def loadProject(self, projectfilename): + """ Load the project from a saved project file + """ + # Load workspace group + api.LoadNexusProcessed(Filename=projectfilename, OutputWorkspace=self._wsgroupName) + self._wsgroup = AnalysisDataService.retrieve(self._wsgroupName) + + if self._wsgroup.__class__.__name__ != "WorkspaceGroup": + raise NotImplementedError("Input is not a workspace group but a %s" % (self._wsgroup.__class__.__name__)) + else: + self._wsgroupCreated = True + + # Parse README + wsnames = self._wsgroup.getNames() + readmewsname = None + for wsname in wsnames: + if wsname.startswith("READ"): + readmewsname = wsname + break + if readmewsname is None: + raise NotImplementedError("No README workspace is found in loaded workspace group.") + + readmews = AnalysisDataService.retrieve(readmewsname) + infodict = {} + numrows = readmews.rowCount() + self.glog.information("Found %d rows in workspace %s" % (numrows, str(readmews))) + for r in xrange(numrows): + functioncat = str(readmews.cell(r, 0)).strip() + functiontype = str(readmews.cell(r, 1)).strip() + infodict[functioncat] = functiontype.strip() + self.glog.information("README keys: %s" % (infodict.keys())) + self._peakType = infodict["Peak"] + self.datawsname = infodict["Data"] + self.wsindex = infodict["Spectrum"] + if self._ID != infodict["ID"]: + raise NotImplementedError("ID mismatch!") + + self._recordwsname = infodict["Record"] self._isSetup = True return - def refine(self, parametersToFit, numcycles, startx, endx): + def refine(self, dataws, wsindex, parametersToFit, numcycles, startx, endx, laststepindex): """ Refine parameters """ + # Range of fit + if startx <= 0.: + startx = dataws.readX(wsindex)[0] + if endx <= 0.: + endx = dataws.readX(wsindex)[-1] + + # Set up RefineProfileParameters object runner = RefineProfileParameters(self.glog) # Locate refinement record table - profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname = self._parseRecordTable() + profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname, laststep = self._parseRecordTable(laststepindex) # Set up runner and refine - runner.numsteps = numcycles - runner.paramToFit = parametersToFit - - runner.startx = startx - runner.endx = endx + runner.setupMonteCarloRefine(numcycles, parametersToFit) - # runner.inprofilewsname = profilewsname - # runner.inreflectionwsname = braggpeakwsname - # runner.bkgdtype = bkgdtype - # runner.bkgdtablewsname = bkgdparamwsname - - outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(runner.datawsname, profilewsname, braggpeakwsname) - # runner.outwsname = outwsname - # runner.outprofilewsname = outprofilewsname - # runner.outreflectionwsname = outbraggpeakwsname + outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(str(dataws), profilewsname, braggpeakwsname) # Set up input and output - runner.setInputs(self._datawsname, profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname) + runner.setInputs(str(dataws), self._peakType, profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname) # FIXME - Need to verify whether input and output background parameter ws name can be same runner.setOutputs(outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname) - # Refine - self._recordPreRefineInfo(runner) - - runner.refine() + + # Refine and record pre and post refinement information + self._recordPreRefineInfo(runner, laststep) + runner.refine(numcycles, parametersToFit, startx, endx) self._recordPostRefineInfo(runner) + # Group newly generated workspaces and add name to reposiotry + if self._wsgroupCreated is True: + api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname, self._wsgroupName), + OutputWorkspace=self._wsgroupName) + else: + wsgroup = AnalysisDataService.retrieve(self._wsgroupName) + hasbkgd = list(wsgroup.getNames()).count(bkgdparamwsname) + if hasbkgd == 1: + api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname), + OutputWorkspace=self._wsgroupName) + elif hasbkgd == 0: + api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname), + OutputWorkspace=self._wsgroupName) + else: + raise NotImplementedError("Impossible to have 1 workspace appeared twice in a workspace group.") + return def isSetup(self): @@ -245,6 +378,53 @@ def isSetup(self): """ return self._isSetup + + def saveProject(self, datawsname, wsindex, projectfname): + """ Save current to a project file + Note: MC setup table workspace is not generated in this class. So it won't be saved + """ + import os + + # FIXME - Find out a good way to remove existing files/directories + if os.path.exists(projectfname) is True: + import shutil + try: + os.remove(projectfname) + except RuntimeError: + shutil.rmtree(projectfname) + except IOError: + shutil.rmtree(projectfname) + except OSError: + shutil.rmtree(projectfname) + + api.SaveNexusProcessed(InputWorkspace=self._wsgroupName, Filename=projectfname, Append=False) + + # Add data workspace, tracking record table to workspaces + # api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (datawsname, self._recordwsname, self._wsgroupName), + # OutputWorkspace=self._wsgroupName) + self.glog.notice("Append record workspace %s" % (self._recordwsname)) + api.SaveNexusProcessed(InputWorkspace=self._recordwsname, Filename=projectfname, Append=True) + + self.glog.notice("Append data workspace %s" % (datawsname)) + api.SaveNexusProcessed(InputWorkspace=datawsname, Filename=projectfname, Append=True) + + # Create a new README table workspace for some other information + readmewsname = "READ_%s" % (self._ID) + readmews = api.CreateEmptyTableWorkspace(OutputWorkspace=readmewsname) + readmews.addColumn("str", "Function") + readmews.addColumn("str", "Type") + + readmews.addRow(["Peak", "Not Important"]) + readmews.addRow(["Background", "Not Important"]) + readmews.addRow(["ID", str(self._ID)]) + readmews.addRow(["Record", self._recordwsname]) + readmews.addRow(["Data", str(datawsname)]) + readmews.addRow(["Spectrum", str(wsindex)]) + + api.SaveNexusProcessed(InputWorkspace=readmewsname, Filename=projectfname, Append=True) + + return + def _genRecordTable(self): """ Generate record table """ @@ -264,57 +444,98 @@ def _genRecordTable(self): tablews.addColumn("str", "InBackgroud") tablews.addColumn("str", "InBckgroundParam") + self._recordws = tablews + return - def _parseRecordTable(self): + def _parseRecordTable(self, laststep): """ Parse record table and return the last refinement result Notice that 'last row' in record table might not be a valid row (incomplete). It might be caused by an exception raised in refinement or its setup. - Class variable _lastrowinvalid is used to indicate this + Class variable _recordWSLastRowInvalid is used to indicate this """ - rectablews = mtd[self._recordwsname] - numrows = rectablews.rowCount() + # Retrieve record workspace + self._recordws = AnalysisDataService.retrieve(str(self._recordwsname)) + numrows = self._recordws.rowCount() if numrows == 0: raise NotImplementedError("Empty record table workspace. ") - lastrow = numrows-1 - - while lastrow >= 0: - profilewsname = rectablews.cell(lastrow, 1) - reflectwsname = rectablews.cell(lastrow, 2) - bkgdtype = rectablews.cell(lastrow, 3) - bkgdparamwsname = rectablews.cell(lastrow, 4) - + # Find last valid row + lastvalidrow = -1 + lastrow = numrows-1 + self._recordwsLastRowValid = False + while self._recordwsLastRowValid is False and lastrow >= 0: + profilewsname = self._recordws.cell(lastrow, 1) if profilewsname == "": - print "Profile workspace name is emtpy in row %d!" % (lastrow) + self.glog.warning("Profile workspace name is emtpy in row %d!" % (lastrow)) lastrow -= 1 else: + self._recordwsLastRowValid = True + lastvalidrow = lastrow + # ENDWHILE + if lastvalidrow < 0: + raise NotImplementedError("XXX") + + # Find out last step row + lastrecordedstep = self._recordws.cell(lastvalidrow, 0) + self.glog.notice("Last recorded valid step is %d. " % (lastrecordedstep)) + + self._lastValidStep = lastrecordedstep + self._lastValidRowIndex = lastvalidrow + + if laststep > lastrecordedstep: + self.glog.warning("Last step %d is not recorded. Using step %d instead. " % + (laststep, lastrecordedstep)) + laststep = lastrecordedstep + elif laststep < 0: + self.glog.notice("Using default last valid step %d. " % (self._lastValidStep)) + laststep = self._lastValidStep + + profilewsname = "" + while lastvalidrow >= 0: + step = self._recordws.cell(lastvalidrow, 0) + if step != laststep: + lastvalidrow -= 1 + else: + profilewsname = self._recordws.cell(lastvalidrow, 1).strip() + reflectwsname = self._recordws.cell(lastvalidrow, 2).strip() + bkgdtype = self._recordws.cell(lastrow, 3).strip() + bkgdparamwsname = self._recordws.cell(lastrow, 4).strip() + if profilewsname == "": + raise NotImplementedError("Profile workspace name is emtpy in row %d. It is not supposed to happen." % + (lastvalidrow)) break # ENDWHILE - if profilewsname == "": - raise NotImplementedError("Profile workspace name is empty!") + raise NotImplementedError("Step %d is not found in record table. It is impossible. " % + (laststep)) - self._lastrowinvalid = False - if lastrow != numrows-1: - self._lastrowinvalid = True + # Current step + self._currstep = self._lastValidStep + 1 + self.glog.notice("Current step is %d" % (self._currstep)) - return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname) + # Set up for other informatin + # Peak type + self._peakType = self._recordws.cell(0, 9).strip() + # Background type + self._bkgdType = bkgdtype.strip() + return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname, laststep) - def _recordPreRefineInfo(self, refiner): + + def _recordPreRefineInfo(self, refiner, laststep): """ Record pre-refinement information """ rectablews = mtd[self._recordwsname] numrows = rectablews.rowCount() - if self._lastrowinvalid is False: + if self._recordWSLastRowInvalid is False: self._currstep = numrows - laststep = self._currstep-1 - rectablews.addRow([self._currstep, "", "", "", "", "", -1.0, laststep, -1.0, "profilews", "reflectionws", "Polynomial", "BkgdParm"]) + rectablews.addRow([self._currstep, "", "", "", "", "", -1.0, laststep, -1.0, "profilews", + "reflectionws", "Polynomial", "BkgdParm"]) else: self._currstep = numrows-1 - laststep = self._currstep-1 + laststep = self._lastValidStep # print "*** Record workspace has %d rows. current step = %d. " % (rectablews.rowCount(), self._currstep) @@ -331,7 +552,6 @@ def _recordPostRefineInfo(self, refiner): """ Record post-refinement information, i.e., refinement result """ # Parse profile table workspace - # FIXME - do I need to call AnalysisDataService? # print "****** outprofilews type = ", type(refiner.outprofilewsname) outprofilews = AnalysisDataService.retrieve(str(refiner.outprofilewsname)) # outprofilews = api.mtd[refiner.outprofilewsname] @@ -358,16 +578,15 @@ def _recordPostRefineInfo(self, refiner): return - def _genOutputWorkspace(self, dataws, profilewsname, braggpeakwsname): + def _genOutputWorkspace(self, datawsname, profilewsname, braggpeakwsname): """ """ - outwsname = "%s_%s_Step%d" % (dataws, self._ID, self._currstep) + outwsname = "%s_%s_Step%d" % (datawsname, self._ID, self._currstep) if profilewsname.count(self._ID) > 0: outprofilewsname = profilewsname.split(self._ID)[0] else: outprofilewsname = profilewsname - print "Input: ", profilewsname, "Output: ", type(outprofilewsname), "ID = ", self._ID, "Step = ", self._currstep outprofilewsname = "%s%s_Step%d" % (outprofilewsname, self._ID, self._currstep) if braggpeakwsname.count(str(self._ID)) > 0: @@ -380,7 +599,43 @@ def _genOutputWorkspace(self, dataws, profilewsname, braggpeakwsname): #-------------------------------------------------------------------- -def generateMCSetupTable(wsname): +def generateMCSetupTableProf9(wsname): + """ Generate a Le Bail fit Monte Carlo random walk setup table + """ + tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=str(wsname)) + + tablews.addColumn("str", "Name") + tablews.addColumn("double", "A0") + tablews.addColumn("double", "A1") + tablews.addColumn("int", "NonNegative") + tablews.addColumn("int", "Group") + + group = 0 + tablews.addRow(["Dtt1" , 5.0, 0.0, 0, group]) + tablews.addRow(["Dtt2" , 1.0, 0.0, 0, group]) + tablews.addRow(["Zero" , 5.0, 0.0, 0, group]) + + group = 1 + tablews.addRow(["Beta0" , 0.50, 1.0, 0, group]) + tablews.addRow(["Beta1" , 0.05, 1.0, 0, group]) + + group = 2 + tablews.addRow(["Alph0" , 0.05, 1.0, 0, group]) + tablews.addRow(["Alph1" , 0.02, 1.0, 0, group]) + + group = 3 + tablews.addRow(["Sig0", 2.0, 1.0, 1, group]) + tablews.addRow(["Sig1", 2.0, 1.0, 1, group]) + tablews.addRow(["Sig2", 2.0, 1.0, 1, group]) + + group = 4 + tablews.addRow(["Gam0", 2.0, 1.0, 0, group]) + tablews.addRow(["Gam1", 2.0, 1.0, 0, group]) + tablews.addRow(["Gam2", 2.0, 1.0, 0, group]) + + return tablews + +def generateMCSetupTableProf10(wsname): """ Generate a Le Bail fit Monte Carlo random walk setup table """ import mantid.simpleapi as api @@ -494,6 +749,8 @@ def __init__(self, glog): # # Other constants # latticesize = calibDict[bankid]["LatticeSize"] + self.peaktype = "NOSETUP" + # Output self.outwsname = None @@ -511,10 +768,11 @@ def __init__(self, glog): return - def setInputs(self, datawsname, profilewsname, braggpeakwsname, bkgdtype, bkgdparwsname): + def setInputs(self, datawsname, peaktype, profilewsname, braggpeakwsname, bkgdtype, bkgdparwsname): """ """ self.datawsname = datawsname + self.peaktype = peaktype self.inprofilewsname = profilewsname self.inreflectionwsname = braggpeakwsname self.bkgdtype = bkgdtype @@ -536,6 +794,17 @@ def setOutputs(self, outwsname, profilewsname, braggpeakwsname, bkgdparwsname): return + def setupMonteCarloRefine(self, numcycles, parametersToFit): + """ Set up refinement parameters + """ + if numcycles <= 0: + raise NotImplementedError("It is not allowed to set up a 0 or a negative number to MonteCarloRefine") + else: + self.numsteps = numcycles + + self.paramToFit = parametersToFit + + return def calculate(self, startx, endx): """ Do Le bail calculation @@ -544,7 +813,10 @@ def calculate(self, startx, endx): raise NotImplementedError("Either input or output is not setup: inputIsStepUp = %s, outputIsSetup = %s" % (str(self._inputIsSetup), str(self._outputIsSetup))) - self.glog.information("Calculate: DataWorksapce = %s" % (str(self.datawsname))) + self.glog.information("**** Calculate: DataWorksapce = %s" % (str(self.datawsname))) + self.glog.information("**** Fit range: %f, %f" % (startx, endx)) + self.glog.information("**** Profile workspace = %s, Reflection workspace = %s" % ( + self.inprofilewsname, self.inreflectionwsname)) api.LeBailFit( Function = 'Calculation', @@ -555,6 +827,7 @@ def calculate(self, startx, endx): InputHKLWorkspace = self.inreflectionwsname, OutputPeaksWorkspace = self.outreflectionwsname, FitRegion = '%f, %f' % (startx, endx), + PeakType = self.peaktype, BackgroundType = self.bkgdtype, UseInputPeakHeights = False, PeakRadius = '8', @@ -571,16 +844,22 @@ def refine(self, numsteps, parameternames, startx, endx): if (self._inputIsSetup and self._outputIsSetup) is False: raise NotImplementedError("Either input or output is not setup.") + self.glog.debug("[Refine] Input profile workspace = %s" % (self.inprofilewsname)) + # Update parameters' fit table if numsteps > 0: # Set up the default parameters to refine # Set up the parameters to refine - UpdatePeakParameterTableValue( + # FIXME - It is found that in the 'load' mode, a ID???_Group_2 might be generated by running + # UpdatePeakParameterTableValue(). It is not a real new table workspace, but a link + # to the 'inprofilewsname' + # There must be something wrong in AnalysisDataService. + api.UpdatePeakParameterTableValue( InputWorkspace = self.inprofilewsname, Column = "FitOrTie", NewStringValue = "tie") - UpdatePeakParameterTableValue( + api.UpdatePeakParameterTableValue( InputWorkspace = self.inprofilewsname, Column = "FitOrTie", ParameterNames = parameternames, @@ -603,18 +882,24 @@ def refine(self, numsteps, parameternames, startx, endx): # Generate Monte carlo table wsname = "MCSetupParameterTable" - tablews = generateMCSetupTable(wsname) + if self.peaktype == "NeutronBk2BkExpConvPVoigt": + tablews = generateMCSetupTableProf9(wsname) + elif self.peaktype == "ThermalNeutronBk2BkExpConvPVoigt": + tablews = generateMCSetupTableProf10(wsname) + else: + raise NotImplementedError("Peak type %s is not supported to set up MC table." % (self.peaktype)) - LeBailFit( + api.LeBailFit( InputWorkspace = self.datawsname, OutputWorkspace = self.outwsname, InputParameterWorkspace = self.inprofilewsname, OutputParameterWorkspace = self.outprofilewsname, InputHKLWorkspace = self.inreflectionwsname, OutputPeaksWorkspace = self.outreflectionwsname, - FitRegion = '%f, %f' % (self.startx, self.endx), + FitRegion = '%f, %f' % (startx, endx), Function = 'MonteCarlo', - NumberMinimizeSteps = self.numsteps, + NumberMinimizeSteps = numsteps, + PeakType = self.peaktype, BackgroundType = self.bkgdtype, BackgroundParametersWorkspace = self.bkgdtablewsname, UseInputPeakHeights = False, From 4f75e86c6035f8c4829f25d4ff9bd74d42472f4b Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Fri, 22 Nov 2013 15:31:42 -0500 Subject: [PATCH 031/403] Refs #8508 Little more than the header --- .../functions/DiffRotDiscreteCircle.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py b/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py new file mode 100644 index 000000000000..2aa8d53932bb --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py @@ -0,0 +1,65 @@ +'''*WIKI* + +This fitting function models the dynamics structure factor of a particle undergoing +discrete jumps on N-sites evenly distributed in a circle. The particle can only +jump to neighboring sites. This is the most common type of discrete rotational diffusion +in a circle. + +The fitting parameters are the inverse of the transition rate, \tau +and the circle radius r + + S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) + + \tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N}) + +If the energy units of energy are micro-eV, then tau is expressed in pico-seconds. If E-units are micro-eV then +tau is expressed in nano-seconds. +*WIKI* + +@author Jose Borreguero, NScD +@date November 22, 2013 + +Copyright © 2007-8 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + +This file is part of Mantid. + +Mantid is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +Mantid is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +File change history is stored at: +Code Documentation is available at: +''' + +from mantid.api import IFunction1D, FunctionFactory #, BoundaryConstraint +from mantid import logger +import numpy as np +import copy + +from pdb import set_trace as tr + +class DiffRotDiscreteCircleElastic(IFunction1D): + '''Elastic part of the structure factor + ''' + def __init__(self): + '''declare some constants''' + super(DiffRotDiscreteCircleElastic, self).__init__() + self._meV2ps = 4.136 + self._parmset = set(['height','tau','beta']) #valid syntaxfor python >= 2.6 + self._parm2index = {'height':0,'tau':1,'beta':2} #order in which they were defined + + def category(self): + return 'QENS' + + From 348bcc1434d45f792752b937c2aaabf30333e209 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 25 Nov 2013 14:10:52 -0500 Subject: [PATCH 032/403] Added property ProjectID. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index c2f4aeca068f..79fe77bb293e 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -90,6 +90,9 @@ def PyInit(self): self.declareProperty(FileProperty("InputProjectFilename","", FileAction.OptionalLoad, ['.nxs']), "Name of sequential project file.") + # Project ID + self.declareProperty("ProjectID", "", "Project ID.") + return @@ -100,7 +103,7 @@ def PyExec(self): self._processInputProperties() # Instantiaze sequential refinement - seqrefine = SeqRefineProfile("IDx890", self.log()) + seqrefine = SeqRefineProfile(self._projectID, self.log()) # Execute if self.functionoption == "Setup": @@ -147,8 +150,13 @@ def _processInputProperties(self): self._lastStep = self.getProperty("FromStep").value + self._projectID = self.getProperty("ProjectID").value + if len(self._projectID) == 0: + raise NotImplementedError("User must specify project ID.") + self.functionoption = self.getProperty("FunctionOption").value if self.functionoption == "Setup": + # Request on 'Setup' ptype = self.getProperty("ProfileType").value if ptype == "Neutron Back-to-back exponential convoluted with psuedo-voigt": self.peaktype = "NeutronBk2BkExpConvPVoigt" @@ -161,6 +169,7 @@ def _processInputProperties(self): self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value self.profilews = self.getProperty("InputProfileWorkspace").value self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value + elif self.functionoption == "Refine": self.paramstofit = self.getProperty("Parameters2Refine").value @@ -180,6 +189,7 @@ def _processInputProperties(self): if self.wsindex < 0 or self.wsindex >= self.dataws.getNumberHistograms(): raise NotImplementedError("Input workspace index %d is out of range (0, %d)." % (self.wsindex, self.dataws.getNumberHistograms())) + return From 721dd245a0e6b25feec3dbea637510b1c1f7313b Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 25 Nov 2013 21:02:12 -0500 Subject: [PATCH 033/403] Correted some typos. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index 79fe77bb293e..ddb86f80aae8 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -64,17 +64,18 @@ def PyInit(self): funcoptions = ["Setup", "Refine", "Save", "Load"] self.declareProperty("FunctionOption", "Refine", StringListValidator(funcoptions), "Options of functionality") - refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] + #refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] + refoptions = ["Random Walk"] self.declareProperty("RefinementOption", "Random Walk", StringListValidator(refoptions), "Options of algorithm to refine. ") - self.declareProperty(StringArrayProperty("Parameters2Refine", values=[], direction=Direction.Input), + self.declareProperty(StringArrayProperty("ParametersToRefine", values=[], direction=Direction.Input), "List of parameters to refine.") self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") - peaktypes = ["", "Neutron Back-to-back exponential convoluted with psuedo-voigt", - "Thermal neutron Back-to-back exponential convoluted with psuedo-voigt"] + peaktypes = ["", "Neutron Back-to-back exponential convoluted with pseudo-voigt", + "Thermal neutron Back-to-back exponential convoluted with pseudo-voigt"] self.declareProperty("ProfileType", "", StringListValidator(peaktypes), "Type of peak profile function.") bkgdtypes = ["", "Polynomial", "Chebyshev", "FullprofPolynomial"] @@ -158,9 +159,9 @@ def _processInputProperties(self): if self.functionoption == "Setup": # Request on 'Setup' ptype = self.getProperty("ProfileType").value - if ptype == "Neutron Back-to-back exponential convoluted with psuedo-voigt": + if ptype == "Neutron Back-to-back exponential convoluted with pseudo-voigt": self.peaktype = "NeutronBk2BkExpConvPVoigt" - elif ptype == "Thermal neutron Back-to-back exponential convoluted with psuedo-voigt": + elif ptype == "Thermal neutron Back-to-back exponential convoluted with pseudo-voigt": self.peaktype = "ThermalNeutronBk2BkExpConvPVoigt" else: raise NotImplementedError("Peak profile is not supported.") @@ -172,7 +173,7 @@ def _processInputProperties(self): elif self.functionoption == "Refine": - self.paramstofit = self.getProperty("Parameters2Refine").value + self.paramstofit = self.getProperty("ParametersToRefine").value self.numcycles = self.getProperty("NumRefineCycles").value elif self.functionoption == "Save": From 1547b26e4076754788a4804c914c0c1284608d71 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Tue, 26 Nov 2013 10:31:40 +0000 Subject: [PATCH 034/403] Refs #8512 Set FFTSmooth to use IgnoreXBins option. --- .../scripts/Inelastic/inelastic_indirect_reduction_steps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py b/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py index 0dcc9499f790..033d699c2566 100644 --- a/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py +++ b/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py @@ -521,7 +521,7 @@ def _unwrap_monitor(self, ws): unwrapped_ws, join = UnwrapMonitor(InputWorkspace=monitor, OutputWorkspace=monitor, LRef=l_ref) RemoveBins(InputWorkspace=monitor,OutputWorkspace= monitor,XMin= join-0.001,XMax= join+0.001, Interpolation='Linear') - FFTSmooth(InputWorkspace=monitor,OutputWorkspace=monitor,WorkspaceIndex=0) + FFTSmooth(InputWorkspace=monitor,OutputWorkspace=monitor,WorkspaceIndex=0, IgnoreXBins=True) def _get_reference_length(self, ws, index): workspace = mtd[ws] From 6043245dc35ed925309cad4bf9096915322d29da Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Tue, 26 Nov 2013 11:09:34 +0000 Subject: [PATCH 035/403] Add non-functioning workspace property re #8398 Signed-off-by: Karl Palmen --- .../MantidDataHandling/LoadFullprofResolution.h | 3 +++ .../DataHandling/src/LoadFullprofResolution.cpp | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h index bd5ee29c1986..64c9b2a259a1 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h @@ -85,6 +85,9 @@ namespace DataHandling /// Generate bank information workspace DataObjects::TableWorkspace_sptr genInfoTableWorkspace(std::vector banks); + /// Put parameters into a metrix workspace + void putParametersIntoWorkspace( const API::ITableWorkspace_sptr tws, API::MatrixWorkspace_sptr ws); + }; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index 7cd9dfa0128e..22d04b03ed29 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -76,6 +76,9 @@ namespace DataHandling // declareProperty("Bank", EMPTY_INT(), "ID of a specific bank to load. Default is all banks in .irf file."); + declareProperty(new WorkspaceProperty<>("Workspace","",Direction::InOut, PropertyMode::Optional), + "Optional: A matrix workspace with the instrument to which we add the parameters from the Fullprof .irf file."); + return; } @@ -87,6 +90,7 @@ namespace DataHandling // Get input string datafile = getProperty("Filename"); vector outputbankids = getProperty("Banks"); + MatrixWorkspace_sptr workspace = getProperty("Workspace"); // Import data vector lines; @@ -169,9 +173,14 @@ namespace DataHandling // Generate output table workspace API::ITableWorkspace_sptr outTabWs = genTableWorkspace(bankparammap); - // 6. Output + // 6. Output table workspace setProperty("OutputTableWorkspace", outTabWs); + // 7. If workspace, put parameters there + if(workspace){ + putParametersIntoWorkspace( outTabWs, workspace ); + } + return; } @@ -733,6 +742,10 @@ namespace DataHandling return tablews; } + void LoadFullprofResolution::putParametersIntoWorkspace( const API::ITableWorkspace_sptr tws, API::MatrixWorkspace_sptr ws) + { + } + } // namespace DataHandling } // namespace Mantid From 21ce24ebc8e7b73ada914e506eb1ebd7a35bb198 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Wed, 27 Nov 2013 11:13:05 +0000 Subject: [PATCH 036/403] Begin to write code to put params into workspace re #8398 My original plan of putting the table into a POCO XML document then putting that into the workspace like LoadParameters does is not on, because LoadParameters does something dodgy, that will sometime need fixing and should not be replicated. So I'm forced to put the parameters in directly. This would lead to better code, but I presently have no idea how to do it. Signed-off-by: Karl Palmen --- .../LoadFullprofResolution.h | 2 +- .../src/LoadFullprofResolution.cpp | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h index 64c9b2a259a1..c384df58f284 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h @@ -86,7 +86,7 @@ namespace DataHandling DataObjects::TableWorkspace_sptr genInfoTableWorkspace(std::vector banks); /// Put parameters into a metrix workspace - void putParametersIntoWorkspace( const API::ITableWorkspace_sptr tws, API::MatrixWorkspace_sptr ws); + void putParametersIntoWorkspace( const API::ITableWorkspace_sptr &tws, API::MatrixWorkspace_sptr ws); }; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index 22d04b03ed29..8d44b341a562 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -1,6 +1,6 @@ /*WIKI* -Load Fullprof resolution (.irf) file to TableWorkspace(s) +Load Fullprof resolution (.irf) file to TableWorkspace(s) and optionally into the instrument of a matrix workspace. *WIKI*/ #include "MantidDataHandling/LoadFullprofResolution.h" @@ -8,6 +8,9 @@ Load Fullprof resolution (.irf) file to TableWorkspace(s) #include "MantidKernel/ArrayProperty.h" #include "MantidAPI/WorkspaceProperty.h" #include "MantidAPI/TableRow.h" +#include "MantidGeometry/Instrument.h" +#include "MantidAPI/InstrumentDataService.h" +#include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" #include #include @@ -23,6 +26,11 @@ using namespace Mantid::DataObjects; using namespace Mantid::Kernel; using namespace std; +using Geometry::Instrument; +using Geometry::Instrument_sptr; +using Geometry::Instrument_const_sptr; +using Mantid::Geometry::InstrumentDefinitionParser; + namespace Mantid { namespace DataHandling @@ -742,8 +750,18 @@ namespace DataHandling return tablews; } - void LoadFullprofResolution::putParametersIntoWorkspace( const API::ITableWorkspace_sptr tws, API::MatrixWorkspace_sptr ws) + void LoadFullprofResolution::putParametersIntoWorkspace( const API::ITableWorkspace_sptr &tws, API::MatrixWorkspace_sptr ws) { + Instrument_const_sptr instrument = ws->getInstrument(); + //Instrument_const_sptr baseInstrument = ws->getInstrument()->baseInstrument(); + + //InstrumentDefinitionParser loadInstr; + //loadInstr.setComponentLinks(instrument, pRootElem); + + auto & pmap = ws->instrumentParameters(); + + //pmap.addString(instrument->getComponentID(), blah); // What do I do here? + } } // namespace DataHandling From 73ef6be384e18bdfb0cfa35eddf29ad0899989a0 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 27 Nov 2013 13:59:44 +0000 Subject: [PATCH 037/403] refs #8520. create quick_explicit To help with backwards compatibility, I really don't want to break anything dependent on quick at this stage (including the reflectometry gui), so I want to leave that function API intact. Instead, I introduce a new function called quick_explicit, which quick will call. --- .../convert_to_wavelength.py | 2 +- .../Reflectometry/isis_reflectometry/quick.py | 169 ++++++------------ .../Reflectometry/isis_reflgui/reflgui.py | 2 +- 3 files changed, 57 insertions(+), 116 deletions(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/convert_to_wavelength.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/convert_to_wavelength.py index 7f5d4c9bb79f..222adaeb5630 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/convert_to_wavelength.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/convert_to_wavelength.py @@ -19,7 +19,7 @@ def sum_workspaces(cls, workspaces): @classmethod def to_workspace(cls, candidate): workspace = None - if isinstance(candidate, mantid.api.MatrixWorkspace): + if isinstance(candidate, mantid.api.Workspace): workspace = candidate elif isinstance(candidate, str): if mantid.api.AnalysisDataService.doesExist(candidate): diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 8e9f9c125724..8bb68b6fd393 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -17,112 +17,61 @@ import math import re - -def quick(run, theta=0, pointdet=1,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', debug=0): - ''' - call signature(s):: - - x=quick(RunNumber) - x=quick(RunNumber, roi=[0,0], db=[0,0], trans=0, outputType='pd') - x=quick(RunNumber,[1,10]) - x=quick(RunNumber,[1,10],[20,40]) - x=quick(RunNumber, trans=2568) - x=quick(RunNumber, trans='SomeSavedWorkspaceName') - - Reduces a ISIS raw or nexus file created on one of the reflectometers applying - only a minimum ammount of corrections. The data is left in terms of lambda. - - Required arguments - ========= ===================================================================== - RunNumber Either an ISIS run number when the paths are set up correctly or - the full path and filename if an ISIS raw file. - ========= ===================================================================== - - Optional keyword arguments: - ========= ===================================================================== - Keyword Description - ========= ===================================================================== - roi Region of interest marking the extent of the reflected beam. - default [0,0] - db Region of interest marking the extent of the direct beam. - default [0,0] - trans transmission run number or saved workspace. The default is 0 (No - transmission run). trans=-1 will supress the division of the - detector by the monitor. - polcorr polarisation correction, 0=no correction (unpolarised run) - usemon monitor to be used for normalisation (-1 is default from IDF) - outputType 'pd' = point detector (Default), 'md'= Multidetector Will use - this to build the equivalent of gd in the old matlab code but - keep all of the simple detector processing in one well organized - function. This should not be used by the average user. - ========= ===================================================================== - - Outputs: - ========= ===================================================================== - x Either a single mantid workspace or worspace group or an array - of them. - ========= ===================================================================== - - Working examples: - >>> # reduce a data set with the default parameters - >>> x=quick(/Users/trc/Dropbox/Work/PolrefTest/POLREF00003014.raw") - - >>> # reduce a data set with a transmission run - >>> t=quick(/Users/trc/Dropbox/Work/PolrefTest/POLREF00003010.raw") - >>> x=quick(/Users/trc/Dropbox/Work/PolrefTest/POLREF00003014.raw", trans=t) - - >>> # reduce a data set using the multidetector and output a single reflectivity - >>> # where the reflected beam is between channel 121 and 130. - >>> x=quick(/Users/trc/Dropbox/Work/PolrefTest/POLREF00003014.raw", [121,130]) - - - Also see: pol - - ToDo: - 1) code for the transmisson DONE! - 2) Similar to the genie on polref add extraction from the multidetector - 3) need to make the variables stored in the frame work contain the run number. DONE! - +def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', debug=False): ''' - - ''' Notes for developers: - - Naming conventions for workspaces which live in the mantid framework are as follows: - - It's nearly random. this needs to be fixed so that name clashes do not occur. - May try adding a pair of underscores to the front of the name. - + Original quick parameters fetched from IDF ''' - run_ws = ConvertToWavelength.to_workspace(run) idf_defaults = get_defaults(run_ws) - to_lam = ConvertToWavelength(run_ws) - nHist = run_ws.getNumberHistograms() - I0MonitorIndex = idf_defaults['I0MonitorIndex'] - MultiDetectorStart = idf_defaults['MultiDetectorStart'] + i0_monitor_index = idf_defaults['I0MonitorIndex'] + multi_detector_start = idf_defaults['MultiDetectorStart'] lambda_min = idf_defaults['LambdaMin'] lambda_max = idf_defaults['LambdaMax'] - detector_index_ranges = (idf_defaults['PointDetectorStart'], idf_defaults['PointDetectorStop']) + point_detector_start = idf_defaults['PointDetectorStart'] + point_detector_stop = idf_defaults['PointDetectorStop'] + multi_detector_start = idf_defaults['MultiDetectorStart'] background_min = idf_defaults['MonitorBackgroundMin'] background_max = idf_defaults['MonitorBackgroundMax'] - intmin = idf_defaults['MonitorIntegralMin'] - intmax = idf_defaults['MonitorIntegralMax'] + int_min = idf_defaults['MonitorIntegralMin'] + int_max = idf_defaults['MonitorIntegralMax'] + + return quick_explicit(run=run, i0_monitor_index = i0_monitor_index, lambda_min = lambda_min, lambda_max = lambda_max, + point_detector_start = point_detector_start, point_detector_stop = point_detector_stop, + multi_detector_start = multi_detector_start, background_min = background_min, background_max = background_max, + int_min = int_min, int_max = int_max, theta = theta, pointdet = pointdet, roi = roi, db = db, trans = trans, debug = debug ) + + +def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_min, background_max, int_min, int_max, + point_detector_start=0, point_detector_stop=0, multi_detector_start=0, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', debug=False): + ''' + Version of quick where all parameters are explicitly provided. + ''' + + run_ws = ConvertToWavelength.to_workspace(run) + to_lam = ConvertToWavelength(run_ws) + nHist = run_ws.getNumberHistograms() - _monitor_ws, _detector_ws = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=I0MonitorIndex, correct_monitor=True, bg_min=background_min, bg_max=background_max ) + if pointdet: + detector_index_ranges = (point_detector_start, point_detector_stop) + else: + detector_index_ranges = (multi_detector_start, nHist-1) + + + _monitor_ws, _detector_ws = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=i0_monitor_index, correct_monitor=True, bg_min=background_min, bg_max=background_max ) inst = run_ws.getInstrument() # Some beamline constants from IDF - print I0MonitorIndex + print i0_monitor_index print nHist - if (nHist > 5 and not(pointdet)): + if not pointdet: # Proccess Multi-Detector; assume MD goes to the end: # if roi or db are given in the function then sum over the apropriate channels print "This is a multidetector run." try: _I0M = RebinToWorkspace(WorkspaceToRebin=_monitor_ws,WorkspaceToMatch=_detector_ws) - IvsLam = _detector_ws / _IOM + IvsLam = _detector_ws / _I0M if (roi != [0,0]) : ReflectedBeam = SumSpectra(InputWorkspace=IvsLam, StartWorkspaceIndex=roi[0], EndWorkspaceIndex=roi[1]) if (db != [0,0]) : @@ -168,14 +117,15 @@ def quick(run, theta=0, pointdet=1,roi=[0,0], db=[0,0], trans='', polcorr=0, use IvsLam = ExponentialCorrection(InputWorkspace=_detector_ws,C0=c0[0],C1=c1[0],Operation='Divide') IvsLam = Divide(LHSWorkspace=IvsLam, RHSWorkspace=_I0P) else: # we have a transmission run - _monInt = Integration(InputWorkspace=_I0P,RangeLower=intmin,RangeUpper=intmax) + _monInt = Integration(InputWorkspace=_I0P,RangeLower=int_min,RangeUpper=int_max) IvsLam = Divide(LHSWorkspace=_detector_ws,RHSWorkspace=_monInt) names = mtd.getObjectNames() if trans in names: trans = RebinToWorkspace(WorkspaceToRebin=trans,WorkspaceToMatch=IvsLam,OutputWorkspace=trans) IvsLam = Divide(LHSWorkspace=IvsLam,RHSWorkspace=trans,OutputWorkspace="IvsLam") # TODO: Hardcoded names are bad else: - IvsLam = transCorr(trans, IvsLam) + IvsLam = transCorr(trans, IvsLam, lambda_min, lambda_max, background_min, background_max, + int_min, int_max, detector_index_ranges, i0_monitor_index) print type(IvsLam) RenameWorkspace(InputWorkspace=IvsLam, OutputWorkspace="IvsLam") # TODO: Hardcoded names are bad @@ -228,20 +178,11 @@ def quick(run, theta=0, pointdet=1,roi=[0,0], db=[0,0], trans='', polcorr=0, use -def transCorr(transrun, i_vs_lam): - - run_ws = ConvertToWavelength.to_workspace(i_vs_lam) - idf_defaults = get_defaults(run_ws) - I0MonitorIndex = idf_defaults['I0MonitorIndex'] - MultiDetectorStart = idf_defaults['MultiDetectorStart'] - lambda_min = idf_defaults['LambdaMin'] - lambda_max = idf_defaults['LambdaMax'] - background_min = idf_defaults['MonitorBackgroundMin'] - background_max = idf_defaults['MonitorBackgroundMax'] - intmin = idf_defaults['MonitorIntegralMin'] - intmax = idf_defaults['MonitorIntegralMax'] - detector_index_ranges = (idf_defaults['PointDetectorStart'], idf_defaults['PointDetectorStop']) - +def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index): + """ + Perform transmission corrections on i_vs_lam. + return the corrected result. + """ transWS = None if ',' in transrun: @@ -250,17 +191,17 @@ def transCorr(transrun, i_vs_lam): print "Transmission runs: ", transrun to_lam = ConvertToWavelength(slam) - _monitor_ws_slam, _detector_ws_slam = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=I0MonitorIndex, correct_monitor=True, bg_min=background_min, bg_max=background_max ) + _monitor_ws_slam, _detector_ws_slam = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=i0_monitor_index, correct_monitor=True, bg_min=background_min, bg_max=background_max ) _i0p_slam = RebinToWorkspace(WorkspaceToRebin=_monitor_ws_slam, WorkspaceToMatch=_detector_ws_slam) - _mon_int_trans = Integration(InputWorkspace=_i0p_slam, RangeLower=intmin, RangeUpper=intmax) + _mon_int_trans = Integration(InputWorkspace=_i0p_slam, RangeLower=int_min, RangeUpper=int_max) _detector_ws_slam = Divide(LHSWorkspace=_detector_ws_slam, RHSWorkspace=_mon_int_trans) to_lam = ConvertToWavelength(llam) - _monitor_ws_llam, _detector_ws_llam = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=I0MonitorIndex, correct_monitor=True, bg_min=background_min, bg_max=background_max ) + _monitor_ws_llam, _detector_ws_llam = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=i0_monitor_index, correct_monitor=True, bg_min=background_min, bg_max=background_max ) _i0p_llam = RebinToWorkspace(WorkspaceToRebin=_monitor_ws_llam, WorkspaceToMatch=_detector_ws_llam) - _mon_int_trans = Integration(InputWorkspace=_i0p_llam, RangeLower=intmin,RangeUpper=intmax) + _mon_int_trans = Integration(InputWorkspace=_i0p_llam, RangeLower=int_min,RangeUpper=int_max) _detector_ws_llam = Divide(LHSWorkspace=_detector_ws_llam, RHSWorkspace=_mon_int_trans) # TODO: HARDCODED STITCHING VALUES!!!!! @@ -269,10 +210,10 @@ def transCorr(transrun, i_vs_lam): else: to_lam = ConvertToWavelength(transrun) - _monitor_ws_trans, _detector_ws_trans = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=I0MonitorIndex, correct_monitor=True, bg_min=background_min, bg_max=background_max ) + _monitor_ws_trans, _detector_ws_trans = to_lam.convert(wavelength_min=lambda_min, wavelength_max=lambda_max, detector_workspace_indexes=detector_index_ranges, monitor_workspace_index=i0_monitor_index, correct_monitor=True, bg_min=background_min, bg_max=background_max ) _i0p_trans = RebinToWorkspace(WorkspaceToRebin=_monitor_ws_trans, WorkspaceToMatch=_detector_ws_trans) - _mon_int_trans = Integration( InputWorkspace=_i0p_trans, RangeLower=intmin, RangeUpper=intmax ) + _mon_int_trans = Integration( InputWorkspace=_i0p_trans, RangeLower=int_min, RangeUpper=int_max ) _transWS = Divide( LHSWorkspace=_detector_ws_trans, RHSWorkspace=_mon_int_trans ) @@ -292,7 +233,7 @@ def cleanup(): def get_defaults(run_ws): ''' - Temporary helper function. Aid refactoring by removing need to specifically ask things of parameter files. + Fetch out instrument level defaults. ''' defaults = dict() if isinstance(run_ws, WorkspaceGroup): @@ -301,13 +242,13 @@ def get_defaults(run_ws): instrument = run_ws.getInstrument() defaults['LambdaMin'] = float( instrument.getNumberParameter('LambdaMin')[0] ) defaults['LambdaMax'] = float( instrument.getNumberParameter('LambdaMax')[0] ) - defaults['MonitorBackgroundMin'] = float( instrument.getNumberParameter('MonitorBackgroundMin')[0] ) - defaults['MonitorBackgroundMax'] = float( instrument.getNumberParameter('MonitorBackgroundMax')[0] ) - defaults['MonitorIntegralMin'] = float( instrument.getNumberParameter('MonitorIntegralMin')[0] ) + defaults['MonitorBackgroundMin'] = float( instrument.getNumberParameter('MonitorBackgroundMin')[0] ) + defaults['MonitorBackgroundMax'] =float( instrument.getNumberParameter('MonitorBackgroundMax')[0] ) + defaults['MonitorIntegralMin'] = float( instrument.getNumberParameter('MonitorIntegralMin')[0] ) defaults['MonitorIntegralMax'] = float( instrument.getNumberParameter('MonitorIntegralMax')[0] ) defaults['MonitorsToCorrect'] = int( instrument.getNumberParameter('MonitorsToCorrect')[0] ) - defaults['PointDetectorStart'] = int( instrument.getNumberParameter('PointDetectorStart')[0] ) - defaults['PointDetectorStop'] = int( instrument.getNumberParameter('PointDetectorStop')[0] ) + defaults['PointDetectorStart'] = int( instrument.getNumberParameter('PointDetectorStart')[0] ) + defaults['PointDetectorStop'] = int( instrument.getNumberParameter('PointDetectorStop')[0] ) defaults['MultiDetectorStart'] = int( instrument.getNumberParameter('MultiDetectorStart')[0] ) defaults['I0MonitorIndex'] = int( instrument.getNumberParameter('I0MonitorIndex')[0] ) return defaults diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflgui/reflgui.py b/Code/Mantid/scripts/Reflectometry/isis_reflgui/reflgui.py index 1c7c0209d2ba..d99785c04240 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflgui/reflgui.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflgui/reflgui.py @@ -18,7 +18,7 @@ from mantid.simpleapi import * # New API # import qti as qti -from isis_reflectometry.quick import * +from isis_reflectometry.quick import quick from isis_reflectometry.combineMulti import * from mantid.api import WorkspaceGroup from settings import * From d6af85ddbf87ef8f176f6596ff1ed7a8718cb9f6 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 27 Nov 2013 15:23:22 +0000 Subject: [PATCH 038/403] refs #8520. Placeholder for correction object. We need a way to pass correction strategies into quick rather than having it rely on the IDF definitions contained within. Wrapping up the algorithm calls so that they can be partially applied outside of quick is the most sensible way to do this. The new system tests are currently passing prior to making the change of swapping this functionality in. --- .../Reflectometry/isis_reflectometry/quick.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 8bb68b6fd393..629f74bc9cc6 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -16,6 +16,31 @@ from convert_to_wavelength import ConvertToWavelength import math import re +import abc + +class CorrectionStrategy(object): + __metaclass__ = abc.ABCMeta # Mark as an abstract class + + @abc.abstractmethod + def apply(self, to_correct): + pass + +class ExponentialCorrectionStrategy(CorrectionStrategy): + + def __init__(self, c0, c1): + self.__c0 = c0 + self.__c1 = c1 + + def apply(self, to_correct): + return ExponentialCorrection(InputWorkspace=to_correct,C0=self.__c0, C1= self.__c1, Operation='Divide') + +class PolynomialCorrectionStrategy(CorrectionStrategy): + def __init__(self, poly_string): + self.__poly_string = poly_string + + def apply(self, to_correct): + return PolynomialCorrection(InputWorkspace=to_correct, Coefficients=self.__poly_string, Operation='Divide') + def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', debug=False): ''' @@ -251,6 +276,7 @@ def get_defaults(run_ws): defaults['PointDetectorStop'] = int( instrument.getNumberParameter('PointDetectorStop')[0] ) defaults['MultiDetectorStart'] = int( instrument.getNumberParameter('MultiDetectorStart')[0] ) defaults['I0MonitorIndex'] = int( instrument.getNumberParameter('I0MonitorIndex')[0] ) + return defaults def groupGet(wksp,whattoget,field=''): From 4c25372dec0dd40f44c105e1a3040637eee71b52 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 27 Nov 2013 17:02:52 +0000 Subject: [PATCH 039/403] refs #8520. Swap in new functionality and add tests. Should now have no more force IDF parameter reads. You can do everything via the quick_explicit. --- .../Reflectometry/isis_reflectometry/quick.py | 49 +++++++++++-------- .../test/ReflectometryQuickAuxiliaryTest.py | 41 +++++++++++++++- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 629f74bc9cc6..60e4e39738d7 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -10,9 +10,9 @@ #from ReflectometerCors import * from l2q import * from combineMulti import * -#from mantidsimple import * # Old API from mantid.simpleapi import * # New API from mantid.api import WorkspaceGroup +from mantid.kernel import logger from convert_to_wavelength import ConvertToWavelength import math import re @@ -32,14 +32,24 @@ def __init__(self, c0, c1): self.__c1 = c1 def apply(self, to_correct): - return ExponentialCorrection(InputWorkspace=to_correct,C0=self.__c0, C1= self.__c1, Operation='Divide') + logger.information("Exponential Correction") + corrected = ExponentialCorrection(InputWorkspace=to_correct,C0=self.__c0, C1= self.__c1, Operation='Divide') + return corrected class PolynomialCorrectionStrategy(CorrectionStrategy): def __init__(self, poly_string): self.__poly_string = poly_string def apply(self, to_correct): - return PolynomialCorrection(InputWorkspace=to_correct, Coefficients=self.__poly_string, Operation='Divide') + logger.information("Polynomial Correction") + corrected = PolynomialCorrection(InputWorkspace=to_correct, Coefficients=self.__poly_string, Operation='Divide') + return corrected + +class NullCorrectionStrategy(CorrectionStrategy): + def apply(self, to_correct): + logger.information("Null Correction") + out = to_correct.clone() + return out def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', debug=False): @@ -60,15 +70,17 @@ def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, background_max = idf_defaults['MonitorBackgroundMax'] int_min = idf_defaults['MonitorIntegralMin'] int_max = idf_defaults['MonitorIntegralMax'] + correction_strategy = idf_defaults['AlgoritmicCorrection'] return quick_explicit(run=run, i0_monitor_index = i0_monitor_index, lambda_min = lambda_min, lambda_max = lambda_max, point_detector_start = point_detector_start, point_detector_stop = point_detector_stop, multi_detector_start = multi_detector_start, background_min = background_min, background_max = background_max, - int_min = int_min, int_max = int_max, theta = theta, pointdet = pointdet, roi = roi, db = db, trans = trans, debug = debug ) + int_min = int_min, int_max = int_max, theta = theta, pointdet = pointdet, roi = roi, db = db, trans = trans, + debug = debug, correction_strategy = correction_strategy ) def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_min, background_max, int_min, int_max, - point_detector_start=0, point_detector_stop=0, multi_detector_start=0, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', debug=False): + point_detector_start=0, point_detector_stop=0, multi_detector_start=0, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', debug=False, correction_strategy=NullCorrectionStrategy): ''' Version of quick where all parameters are explicitly provided. ''' @@ -125,21 +137,7 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi RunNumber = groupGet(IvsLam.getName(),'samp','run_number') if (trans==''): print "No transmission file. Trying default exponential/polynomial correction..." - inst=groupGet(_detector_ws.getName(),'inst') - corrType=inst.getStringParameter('correction')[0] - if (corrType=='polynomial'): - pString=inst.getStringParameter('polystring') - print pString - if len(pString): - IvsLam = PolynomialCorrection(InputWorkspace=_detector_ws,Coefficients=pString[0],Operation='Divide') - else: - print "No polynomial coefficients in IDF. Using monitor spectrum with no corrections." - elif (corrType=='exponential'): - c0=inst.getNumberParameter('C0') - c1=inst.getNumberParameter('C1') - print "Exponential parameters: ", c0[0], c1[0] - if len(c0): - IvsLam = ExponentialCorrection(InputWorkspace=_detector_ws,C0=c0[0],C1=c1[0],Operation='Divide') + IvsLam = correction_strategy.apply(_detector_ws) IvsLam = Divide(LHSWorkspace=IvsLam, RHSWorkspace=_I0P) else: # we have a transmission run _monInt = Integration(InputWorkspace=_I0P,RangeLower=int_min,RangeUpper=int_max) @@ -277,6 +275,17 @@ def get_defaults(run_ws): defaults['MultiDetectorStart'] = int( instrument.getNumberParameter('MultiDetectorStart')[0] ) defaults['I0MonitorIndex'] = int( instrument.getNumberParameter('I0MonitorIndex')[0] ) + correction = NullCorrectionStrategy() + corrType=instrument.getStringParameter('correction')[0] + if corrType == 'polynomial': + poly_string = instrument.getStringParameter('polystring')[0] + correction = PolynomialCorrectionStrategy(poly_string) + elif corrType == 'exponential': + c0=instrument.getNumberParameter('C0')[0] + c1=instrument.getNumberParameter('C1')[0] + correction = ExponentialCorrectionStrategy(c0, c1) + + defaults['AlgoritmicCorrection'] = correction return defaults def groupGet(wksp,whattoget,field=''): diff --git a/Code/Mantid/scripts/test/ReflectometryQuickAuxiliaryTest.py b/Code/Mantid/scripts/test/ReflectometryQuickAuxiliaryTest.py index 7eb579787cea..1237b39cf3c8 100644 --- a/Code/Mantid/scripts/test/ReflectometryQuickAuxiliaryTest.py +++ b/Code/Mantid/scripts/test/ReflectometryQuickAuxiliaryTest.py @@ -88,6 +88,45 @@ def test_groupGet_unknown_log_error_code(self): # Test with group workspace as input self.assertEquals(errorCode, quick.groupGet(mtd[self.__wsName][0].name(), 'samp','MADE-UP-LOG-NAME')) - + def test_exponential_correction_strategy(self): + test_ws = CreateWorkspace(UnitX="TOF", DataX=[0,1,2,3], DataY=[1,1,1], NSpec=1) + + correction = quick.ExponentialCorrectionStrategy(1, 0) # Should have no effect. + self.assertTrue(isinstance(correction, quick.CorrectionStrategy), msg="Should be of type Correction") + + corrected = correction.apply(test_ws) + + self.assertTrue( all( test_ws.readY(0) == corrected.readY(0) ), msg="Input and outputs should be identical" ) + + DeleteWorkspace(test_ws) + DeleteWorkspace(corrected) + + def test_polynomial_correction_strategy(self): + test_ws = CreateWorkspace(UnitX="TOF", DataX=[0,1,2,3], DataY=[1,1,1], NSpec=1) + + correction = quick.PolynomialCorrectionStrategy("1, 0") # Should have no effect. + self.assertTrue(isinstance(correction, quick.CorrectionStrategy), msg="Should be of type Correction") + + corrected = correction.apply(test_ws) + + self.assertTrue( all( test_ws.readY(0) == corrected.readY(0) ), msg="Input and outputs should be identical" ) + + DeleteWorkspace(test_ws) + DeleteWorkspace(corrected) + + def test_null_correction_strategy(self): + test_ws = CreateWorkspace(UnitX="TOF", DataX=[0,1,2,3], DataY=[1,1,1], NSpec=1) + + correction = quick.NullCorrectionStrategy() # Should have no effect. + self.assertTrue(isinstance(correction, quick.CorrectionStrategy), msg="Should be of type Correction") + + corrected = correction.apply(test_ws) + + self.assertTrue( all( test_ws.readY(0) == corrected.readY(0) ), msg="Input and outputs should be identical" ) + + DeleteWorkspace(test_ws) + DeleteWorkspace(corrected) + + if __name__ == '__main__': unittest.main() From ab00aa7aa8fe3137a55d24035f76dbc5ff65cb44 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 27 Nov 2013 18:01:03 +0000 Subject: [PATCH 040/403] ResolutionModel now expects input coords in cartesian crystal frame. This is the default output of ConvertToMD. Internally it rotates to/from lab frame to perform the resolution calculation. Refs #8416 --- .../Quantification/ForegroundModel.h | 6 ++ .../Resolution/TobyFitResolutionModel.h | 2 +- .../Quantification/Models/Strontium122.cpp | 8 +- .../Resolution/TobyFitResolutionModel.cpp | 73 ++++++++++++++++--- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/ForegroundModel.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/ForegroundModel.h index d5d734129820..84f8b75e182e 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/ForegroundModel.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/ForegroundModel.h @@ -25,6 +25,12 @@ #include "MantidAPI/ParamFunction.h" #include "MantidMDAlgorithms/Quantification/ForegroundModelFactory.h" +// Includes that each model will most probably require +// This lightens the load for the user model writer +#include "MantidGeometry/Crystal/OrientedLattice.h" +#include "MantidKernel/Math/Distributions/BoseEinsteinDistribution.h" + + namespace Mantid { //---------------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Resolution/TobyFitResolutionModel.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Resolution/TobyFitResolutionModel.h index 1664803eb0dc..6b92cd6ccdfc 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Resolution/TobyFitResolutionModel.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Resolution/TobyFitResolutionModel.h @@ -53,7 +53,7 @@ namespace Mantid qz(qZ), deltaE(dE) {} /// - const double qx, qy, qz, deltaE; + double qx, qy, qz, deltaE; }; /** diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp index fce19c33f704..8b5fa137cc4a 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/Strontium122.cpp @@ -1,8 +1,6 @@ // Includes #include "MantidMDAlgorithms/Quantification/Models/Strontium122.h" -#include "MantidGeometry/Crystal/OrientedLattice.h" -#include "MantidKernel/Math/Distributions/BoseEinsteinDistribution.h" #include @@ -74,8 +72,8 @@ namespace Mantid /** * Calculates the scattering intensity * @param exptSetup :: Details of the current experiment - * @param point :: The axis values for the current point in Q-W space: Qx, Qy, Qz, DeltaE. These contain the U matrix - * rotation already. + * @param point :: The axis values for the current point in Q-W space: Qx, Qy, Qz, DeltaE. These are in + * crystal cartesian coordinates * @return The weight contributing from this point */ double Strontium122::scatteringIntensity(const API::ExperimentInfo & exptSetup, const std::vector & point) const @@ -89,7 +87,7 @@ namespace Mantid // qhkl = (1/2pi)(RB)^-1(qxyz) const Geometry::OrientedLattice & lattice = exptSetup.sample().getOrientedLattice(); const Kernel::DblMatrix & gr = exptSetup.run().getGoniometerMatrix(); - const Kernel::DblMatrix & bmat = lattice.getUB(); + const Kernel::DblMatrix & bmat = lattice.getB(); // Avoid doing inversion with Matrix class as it forces memory allocations // M^-1 = (1/|M|)*M^T diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/TobyFitResolutionModel.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/TobyFitResolutionModel.cpp index 7689b1bea403..12542daa29aa 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/TobyFitResolutionModel.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/TobyFitResolutionModel.cpp @@ -84,7 +84,7 @@ namespace Mantid /** * Returns the value of the cross-section convoluted with the resolution an event. This assumes that - * the box forms a 4D point with axes: Qx, Qy, Qz, \f$\Delta E\f$ + * the box forms a 4D point with axes: Qx, Qy, Qz, \f$\Delta E\f$ in the cartesian crystal frame * @param box :: An iterator pointing at the current box under examination * @param eventIndex :: An index of the current event in the box * @param innerRunIndex :: An index of the current run within the workspace. This is NOT the run number. The experiment @@ -96,42 +96,95 @@ namespace Mantid { auto iter = m_exptCache.find(std::make_pair(innerRunIndex, box.getInnerDetectorID(eventIndex))); // Guaranteed to exist const CachedExperimentInfo & detCachedExperimentInfo = *(iter->second); - QOmegaPoint qOmega(box, eventIndex); + QOmegaPoint qCrystal(box, eventIndex); + + // Transform to spectrometer coordinates for resolution calculation + // Done by hand to avoid expensive memory allocations when using Matrix classes + const Geometry::OrientedLattice & lattice = detCachedExperimentInfo.experimentInfo().sample().getOrientedLattice(); + const Kernel::DblMatrix & gr = detCachedExperimentInfo.experimentInfo().run().getGoniometerMatrix(); + const Kernel::DblMatrix & umat = lattice.getU(); + + QOmegaPoint qLab(0.0,0.0,0.0,qCrystal.deltaE); + for(unsigned int i = 0; i < 3; ++i) + { + qLab.qx += (gr[0][i]*umat[i][0]*qCrystal.qx + + gr[0][i]*umat[i][1]*qCrystal.qy + + gr[0][i]*umat[i][2]*qCrystal.qz); + + qLab.qy += (gr[1][i]*umat[i][0]*qCrystal.qx + + gr[1][i]*umat[i][1]*qCrystal.qy + + gr[1][i]*umat[i][2]*qCrystal.qz); + + qLab.qz += (gr[2][i]*umat[i][0]*qCrystal.qx + + gr[2][i]*umat[i][1]*qCrystal.qy + + gr[2][i]*umat[i][2]*qCrystal.qz); + } if(m_foregroundOnly) { std::vector & nominalQ = m_deltaQE[PARALLEL_THREAD_NUMBER]; - nominalQ[0] = qOmega.qx; - nominalQ[1] = qOmega.qy; - nominalQ[2] = qOmega.qz; - nominalQ[3] = qOmega.deltaE; + nominalQ[0] = qCrystal.qx; + nominalQ[1] = qCrystal.qy; + nominalQ[2] = qCrystal.qz; + nominalQ[3] = qCrystal.deltaE; return foregroundModel().scatteringIntensity(detCachedExperimentInfo.experimentInfo(), nominalQ); } // -- Add in perturbations to nominal Q from instrument resolution -- // Calculate the matrix of coefficients that contribute to the resolution function (the B matrix in TobyFit). - calculateResolutionCoefficients(detCachedExperimentInfo, qOmega); + calculateResolutionCoefficients(detCachedExperimentInfo, qLab); + + // Pre calculate the transform inverse (RU) matrix elements + double rb00(0.0), rb01(0.0), rb02(0.0), + rb10(0.0), rb11(0.0), rb12(0.0), + rb20(0.0), rb21(0.0), rb22(0.0); + for(unsigned int i = 0; i < 3; ++i) + { + rb00 += gr[0][i]*umat[i][0]; + rb01 += gr[0][i]*umat[i][1]; + rb02 += gr[0][i]*umat[i][2]; + + rb10 += gr[1][i]*umat[i][0]; + rb11 += gr[1][i]*umat[i][1]; + rb12 += gr[1][i]*umat[i][2]; + + rb20 += gr[2][i]*umat[i][0]; + rb21 += gr[2][i]*umat[i][1]; + rb22 += gr[2][i]*umat[i][2]; + } + const double determinant = (rb00*(rb11*rb22 - rb12*rb21) - + rb01*(rb10*rb22 - rb12*rb20) + + rb02*(rb10*rb21 - rb11*rb20)); // Start MC loop and check the relative error every min steps monteCarloLoopStarting(); double sumSigma(0.0), sumSigmaSqr(0.0), avgSigma(0.0); for(int step = 1; step <= m_mcLoopMax; ++step) { - generateIntegrationVariables(detCachedExperimentInfo, qOmega); - calculatePerturbedQE(detCachedExperimentInfo, qOmega); + generateIntegrationVariables(detCachedExperimentInfo, qLab); + calculatePerturbedQE(detCachedExperimentInfo, qLab); std::vector & q0 = m_deltaQE[PARALLEL_THREAD_NUMBER]; // Currently ordered beam,perp,up (z,x,y) // Reorder to X,Y,Z std::swap(q0[0],q0[1]); std::swap(q0[1],q0[2]); + // Transform to crystal frame for model + // Need to tidy this up when we confirm it is correct + const double qcx = ((rb11*rb22 - rb12*rb21)*q0[0] + (rb02*rb21 - rb01*rb22)*q0[1] + (rb01*rb12 - rb02*rb11)*q0[2])/determinant; + const double qcy = ((rb12*rb20 - rb10*rb22)*q0[0] + (rb00*rb22 - rb02*rb20)*q0[1] + (rb02*rb10 - rb00*rb12)*q0[2])/determinant; + const double qcz = ((rb10*rb21 - rb11*rb20)*q0[0] + (rb01*rb20 - rb00*rb21)*q0[1] + (rb00*rb11 - rb01*rb10)*q0[2])/determinant; + q0[0] = qcx; + q0[1] = qcy; + q0[2] = qcz; + // Compute weight from the foreground at this point const double weight = foregroundModel().scatteringIntensity(detCachedExperimentInfo.experimentInfo(), q0); // Add on this contribution to the average sumSigma += weight; sumSigmaSqr += weight*weight; - + // cppcheck-suppress zerodivcond avgSigma = sumSigma/step; if(checkForConvergence(step) && hasConverged(step, sumSigma, sumSigmaSqr, avgSigma)) From db0ee648d38f05140d600360a985a2b19a8ae3d0 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 27 Nov 2013 18:01:46 +0000 Subject: [PATCH 041/403] Add a quantification model that simply returns a Q coordinate. Used mainly for debugging transformations. Refs #8416 --- .../Framework/MDAlgorithms/CMakeLists.txt | 2 + .../Quantification/Models/QCoordinate.h | 58 +++++++++ .../src/Quantification/Models/QCoordinate.cpp | 111 ++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Models/QCoordinate.h create mode 100644 Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp diff --git a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt index cee58573a25e..1456beb4248a 100644 --- a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt @@ -47,6 +47,7 @@ set ( SRC_FILES src/Quantification/ForegroundModelFactory.cpp src/Quantification/MDResolutionConvolution.cpp src/Quantification/MDResolutionConvolutionFactory.cpp + src/Quantification/Models/QCoordinate.cpp src/Quantification/Models/Strontium122.cpp src/Quantification/Resolution/ModeratorChopperResolution.cpp src/Quantification/Resolution/TobyFitBMatrix.cpp @@ -119,6 +120,7 @@ set ( INC_FILES inc/MantidMDAlgorithms/Quantification/ForegroundModelFactory.h inc/MantidMDAlgorithms/Quantification/MDResolutionConvolution.h inc/MantidMDAlgorithms/Quantification/MDResolutionConvolutionFactory.h + inc/MantidMDAlgorithms/Quantification/Models/QCoordinate.h inc/MantidMDAlgorithms/Quantification/Models/Strontium122.h inc/MantidMDAlgorithms/Quantification/Resolution/ModeratorChopperResolution.h inc/MantidMDAlgorithms/Quantification/Resolution/TobyFitBMatrix.h diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Models/QCoordinate.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Models/QCoordinate.h new file mode 100644 index 000000000000..29821927528f --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Quantification/Models/QCoordinate.h @@ -0,0 +1,58 @@ +#ifndef MANTID_MDALGORITHMS_QCOORDINATE_H_ +#define MANTID_MDALGORITHMS_QCOORDINATE_H_ +/** + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: . + Code Documentation is available at: +*/ +#include "MantidMDAlgorithms/Quantification/ForegroundModel.h" + +namespace Mantid +{ + namespace MDAlgorithms + { + + /** + * Defines a diagnostic model that simply returns + * the value of H,K,L,Energy as the weight depending on + * the input parameter + */ + class DLLExport QCoordinate : public ForegroundModel + { + private: + /// String name of the model + std::string name() const { return "QCoordinate"; } + + /// Setup the model + void init(); + /// Called when an attribute is set + void setAttribute(const std::string & name, const API::IFunction::Attribute& attr); + + /// Returns the type of model + ModelType modelType() const { return Broad; } + /// Calculates the intensity for the model for the current parameters. + double scatteringIntensity(const API::ExperimentInfo & exptDescr, const std::vector & point) const; + + /// Which coordinate has been chosen + size_t m_coord; + }; + + } +} +#endif /* MANTID_MDALGORITHMS_QCOORDINATE_H_ */ diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp new file mode 100644 index 000000000000..90102aaa1aa8 --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp @@ -0,0 +1,111 @@ +// Includes +#include "MantidMDAlgorithms/Quantification/Models/QCoordinate.h" +#include + +namespace Mantid +{ + namespace MDAlgorithms + { + DECLARE_FOREGROUNDMODEL(QCoordinate); + + namespace // anonymous + { + /// N attrs + const unsigned int NATTS = 1; + /// Attribute names + const char * ATTR_NAMES[NATTS] = { "Coord" }; + /// 2 \pi + const double TWO_PI = 2.*M_PI; + } + + /** + * Initialize the model + */ + void QCoordinate::init() + { + declareAttribute(ATTR_NAMES[0], API::IFunction::Attribute("H")); + } + + /** + * Called when an attribute is set from the Fit string + * @param name :: The name of the attribute + * @param attr :: The value of the attribute + */ + void QCoordinate::setAttribute(const std::string & name, const API::IFunction::Attribute& attr) + { + if(name == ATTR_NAMES[0]) + { + std::string value = attr.asString(); + if(value == "QcX") m_coord = 0; + else if(value == "QcY") m_coord = 1; + else if(value == "QcZ") m_coord = 2; + else if(value == "H") m_coord = 3; + else if(value == "K") m_coord = 4; + else if(value == "L") m_coord = 5; + else if(value == "En") m_coord = 6; + else + throw std::invalid_argument("Unknown coordinate name passed to QCoordinate model"); + } + else ForegroundModel::setAttribute(name, attr); // pass it on the base + } + + /** + * Calculates the scattering intensity + * @param exptSetup :: Details of the current experiment + * @param point :: The axis values for the current point in Q-W space: Qx, Qy, Qz, DeltaE. They + * are in the cartesian crystal frame + * @return The weight contributing from this point + */ + double QCoordinate::scatteringIntensity(const API::ExperimentInfo & exptSetup, const std::vector & point) const + { + const double qx(point[0]), qy(point[1]), qz(point[2]), eps(point[3]); + if(m_coord == 6) return eps; + + if(m_coord == 0) return qx; + else if(m_coord == 1) return qy; + else if(m_coord == 2) return qz; + + // HKL coords + + // Transform the HKL only requires B matrix & goniometer (R) as ConvertToMD should have already + // handled addition of U matrix + // qhkl = (1/2pi)(RUB)^-1(qxyz) + const Geometry::OrientedLattice & lattice = exptSetup.sample().getOrientedLattice(); + const Kernel::DblMatrix & gr = exptSetup.run().getGoniometerMatrix(); + const Kernel::DblMatrix & bmat = lattice.getUB(); + + // Avoid doing inversion with Matrix class as it forces memory allocations + // M^-1 = (1/|M|)*M^T + double rb00(0.0), rb01(0.0), rb02(0.0), + rb10(0.0), rb11(0.0), rb12(0.0), + rb20(0.0), rb21(0.0), rb22(0.0); + for(unsigned int i = 0; i < 3; ++i) + { + rb00 += gr[0][i]*bmat[i][0]; + rb01 += gr[0][i]*bmat[i][1]; + rb02 += gr[0][i]*bmat[i][2]; + + rb10 += gr[1][i]*bmat[i][0]; + rb11 += gr[1][i]*bmat[i][1]; + rb12 += gr[1][i]*bmat[i][2]; + + rb20 += gr[2][i]*bmat[i][0]; + rb21 += gr[2][i]*bmat[i][1]; + rb22 += gr[2][i]*bmat[i][2]; + } + // 2pi*determinant. The tobyFit definition of rl vector has extra 2pi factor in it + const double twoPiDet= TWO_PI*(rb00*(rb11*rb22 - rb12*rb21) - + rb01*(rb10*rb22 - rb12*rb20) + + rb02*(rb10*rb21 - rb11*rb20)); + + //qh + if(m_coord == 3) return ((rb11*rb22 - rb12*rb21)*qx + (rb02*rb21 - rb01*rb22)*qy + (rb01*rb12 - rb02*rb11)*qz)/twoPiDet; + //qk + else if(m_coord == 4) return ((rb12*rb20 - rb10*rb22)*qx + (rb00*rb22 - rb02*rb20)*qy + (rb02*rb10 - rb00*rb12)*qz)/twoPiDet; + //ql + else if(m_coord == 5) return ((rb10*rb21 - rb11*rb20)*qx + (rb01*rb20 - rb00*rb21)*qy + (rb00*rb11 - rb01*rb10)*qz)/twoPiDet; + else + throw std::invalid_argument("Logical error. Invalid coord type " + boost::lexical_cast(m_coord)); + } + } +} From 702fc70ee5cac7c8bc660613bc1f64627f3c795e Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 28 Nov 2013 11:32:22 +0000 Subject: [PATCH 042/403] Default to overwrite existing workspace in simulation. Refs #8416 --- .../SimulateResolutionConvolvedModel.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp index feec7cde3c4c..80f87cb4a7cf 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/SimulateResolutionConvolvedModel.cpp @@ -43,6 +43,7 @@ namespace Mantid const char * RESOLUTION_NAME = "ResolutionFunction"; const char * FOREGROUND_NAME = "ForegroundModel"; const char * PARS_NAME = "Parameters"; + const char * APPEND_NAME = "AppendToExisting"; } @@ -92,6 +93,10 @@ namespace Mantid "The parameters/attributes for the function & model. See Fit documentation for format", Direction::Input); + declareProperty(APPEND_NAME, false, + "If true then the simulated events will be added to an existing workspace. If the workspace does " + "not exist then it is created", Direction::Input); + } /** @@ -113,13 +118,14 @@ namespace Mantid // If output workspace exists just add the events to that IMDEventWorkspace_sptr existingWS = getProperty(SIMULATED_NAME); - if(!existingWS) + bool append = getProperty(APPEND_NAME); + if(append && existingWS) { - createOutputWorkspace(); + m_outputWS = boost::dynamic_pointer_cast(existingWS); } else { - m_outputWS = boost::dynamic_pointer_cast(existingWS); + createOutputWorkspace(); } auto functionMD = boost::dynamic_pointer_cast(resolution); functionMD->storeSimulatedEvents(m_outputWS); From fef38d95d0b6fd15afe659f45c1adffbe3c1ff65 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 28 Nov 2013 11:32:41 +0000 Subject: [PATCH 043/403] Add unity option to QCoordinate. Refs #8416 --- .../src/Quantification/Models/QCoordinate.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp index 90102aaa1aa8..e4f9f91401a4 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Models/QCoordinate.cpp @@ -43,6 +43,7 @@ namespace Mantid else if(value == "K") m_coord = 4; else if(value == "L") m_coord = 5; else if(value == "En") m_coord = 6; + else if(value == "Unity") m_coord = 7; else throw std::invalid_argument("Unknown coordinate name passed to QCoordinate model"); } @@ -58,15 +59,20 @@ namespace Mantid */ double QCoordinate::scatteringIntensity(const API::ExperimentInfo & exptSetup, const std::vector & point) const { - const double qx(point[0]), qy(point[1]), qz(point[2]), eps(point[3]); + // unity + if(m_coord == 7) return 1.0; + + // energy + const double eps(point[3]); if(m_coord == 6) return eps; + // crystal frame + const double qx(point[0]), qy(point[1]), qz(point[2]); if(m_coord == 0) return qx; else if(m_coord == 1) return qy; else if(m_coord == 2) return qz; // HKL coords - // Transform the HKL only requires B matrix & goniometer (R) as ConvertToMD should have already // handled addition of U matrix // qhkl = (1/2pi)(RUB)^-1(qxyz) From 7e55948b01ee58663c347d4244dfa986222ffdcf Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 28 Nov 2013 14:01:16 +0000 Subject: [PATCH 044/403] Correct property count in test. Refs #8416 --- .../MDAlgorithms/test/SimulateResolutionConvolvedModelTest.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/test/SimulateResolutionConvolvedModelTest.h b/Code/Mantid/Framework/MDAlgorithms/test/SimulateResolutionConvolvedModelTest.h index 30b2c0b806e4..814deae94f85 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/SimulateResolutionConvolvedModelTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/SimulateResolutionConvolvedModelTest.h @@ -21,7 +21,7 @@ class SimulateResolutionConvolvedModelTest : public CxxTest::TestSuite TS_ASSERT_THROWS_NOTHING(alg.initialize()); TS_ASSERT(alg.isInitialized()); - TS_ASSERT_EQUALS(alg.propertyCount(), 5); + TS_ASSERT_EQUALS(alg.propertyCount(), 6); } }; From 5ef3b1a969d3c617d5a4a2de0caf702597f4c29e Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 28 Nov 2013 15:36:08 +0000 Subject: [PATCH 045/403] Fix const-correctness in MDHistWorkspace. Refs #8416 --- .../Framework/API/inc/MantidAPI/IMDHistoWorkspace.h | 6 +++--- .../MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h index b74b4ec7353c..e58fa0a91b9c 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h @@ -45,9 +45,9 @@ namespace API /// See the MDHistoWorkspace definition for descriptions of these virtual coord_t getInverseVolume() const = 0; - virtual signal_t * getSignalArray() = 0; - virtual signal_t * getErrorSquaredArray() = 0; - virtual signal_t * getNumEventsArray() = 0; + virtual signal_t * getSignalArray() const = 0; + virtual signal_t * getErrorSquaredArray() const = 0; + virtual signal_t * getNumEventsArray() const = 0; virtual void setTo(signal_t signal, signal_t errorSquared, signal_t numEvents) = 0; virtual Mantid::Kernel::VMD getCenter(size_t linearIndex) const = 0; virtual void setSignalAt(size_t index, signal_t value) = 0; diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h index 7c726cb7b054..2406ab0d3e25 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h @@ -126,7 +126,7 @@ namespace MDEvents } /** @return the direct pointer to the signal array. For speed */ - signal_t * getSignalArray() + signal_t * getSignalArray() const { return m_signals; } @@ -138,19 +138,19 @@ namespace MDEvents } /** @return the direct pointer to the error squared array. For speed */ - signal_t * getErrorSquaredArray() + signal_t * getErrorSquaredArray() const { return m_errorsSquared; } /** @return the direct pointer to the array of the number of events. For speed */ - signal_t * getNumEventsArray() + signal_t * getNumEventsArray() const { return m_numEvents; } /** @return the direct pointer to the array of mask bits (bool). For speed/testing */ - bool * getMaskArray() + bool * getMaskArray() const { return m_masks; } @@ -197,7 +197,7 @@ namespace MDEvents } /// Returns the number of contributing events from the bin at the specified index. - signal_t getNumEventsAt(size_t index) + signal_t getNumEventsAt(size_t index) const { return m_numEvents[index]; } From 25d46faee338d44f0fb4d6fd4ea36f711b418d2e Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 28 Nov 2013 15:36:49 +0000 Subject: [PATCH 046/403] Fix normalization by events in MDHistWorkspaceIterator. It had not been implemented at all when the events field was added to the MDHistoWorkspace! Refs #8416 --- .../Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp index d7bf1559393e..02e037593d18 100644 --- a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp +++ b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp @@ -244,8 +244,7 @@ namespace MDEvents case VolumeNormalization: return m_ws->getSignalAt(m_pos) * m_ws->getInverseVolume(); case NumEventsNormalization: - /// TODO: # of events normalization - return m_ws->getSignalAt(m_pos); + return m_ws->getSignalAt(m_pos) / m_ws->getNumEventsAt(m_pos); } // Should not reach here return std::numeric_limits::quiet_NaN(); @@ -263,8 +262,7 @@ namespace MDEvents case VolumeNormalization: return m_ws->getErrorAt(m_pos) * m_ws->getInverseVolume(); case NumEventsNormalization: - /// TODO: # of events normalization - return m_ws->getErrorAt(m_pos); + return m_ws->getErrorAt(m_pos) / m_ws->getNumEventsAt(m_pos); } // Should not reach here return std::numeric_limits::quiet_NaN(); @@ -317,7 +315,7 @@ namespace MDEvents /// @return 1 always: e.g. there is one (fake) event in the middle of the box. size_t MDHistoWorkspaceIterator::getNumEvents() const { - return 1; + return static_cast(m_ws->getNumEventsAt(m_pos)); } //---------------------------------------------------------------------------------------------- From e90a1b39c9850231f83c05b64176f0dd5cbf3746 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 29 Nov 2013 10:18:38 +0000 Subject: [PATCH 047/403] Refs #8512 Add better error handling when using an invalid workspace. --- Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp | 3 +++ Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py | 8 +++++++- .../Inelastic/inelastic_indirect_reduction_steps.py | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp index fdce047de588..121194572244 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp @@ -1667,6 +1667,9 @@ void Indirect::calPlotEnergy() "outWS = resolution(files, iconOpt, '', '', instrument, analyser, reflection, Res=False)\n" "print outWS\n"; QString pyOutput = runPythonCode(pyInput).trimmed(); + + //something went wrong in the python + if(pyOutput == "None") return; Mantid::API::MatrixWorkspace_sptr input = boost::dynamic_pointer_cast(Mantid::API::AnalysisDataService::Instance().retrieve(pyOutput.toStdString())); diff --git a/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py b/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py index e06e981dcec5..234f159cd4b3 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py +++ b/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py @@ -63,7 +63,13 @@ def resolution(files, iconOpt, rebinParam, bground, reducer.set_parameter_file(parfile) reducer.set_grouping_policy('All') reducer.set_sum_files(True) - reducer.reduce() + + try: + reducer.reduce() + except Exception, e: + logger.error(str(e)) + return + iconWS = reducer.get_result_workspaces()[0] if factor != None: diff --git a/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py b/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py index 033d699c2566..fe6983a63f08 100644 --- a/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py +++ b/Code/Mantid/scripts/Inelastic/inelastic_indirect_reduction_steps.py @@ -521,7 +521,10 @@ def _unwrap_monitor(self, ws): unwrapped_ws, join = UnwrapMonitor(InputWorkspace=monitor, OutputWorkspace=monitor, LRef=l_ref) RemoveBins(InputWorkspace=monitor,OutputWorkspace= monitor,XMin= join-0.001,XMax= join+0.001, Interpolation='Linear') - FFTSmooth(InputWorkspace=monitor,OutputWorkspace=monitor,WorkspaceIndex=0, IgnoreXBins=True) + try: + FFTSmooth(InputWorkspace=monitor,OutputWorkspace=monitor,WorkspaceIndex=0) + except ValueError: + raise ValueError("Indirect Energy Conversion does not support uneven bin widths.") def _get_reference_length(self, ws, index): workspace = mtd[ws] From 1cc2efe187cfa96e210ddada4c505450609921be Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Fri, 29 Nov 2013 11:03:02 +0000 Subject: [PATCH 048/403] Fix bounding box of cached detector to taking into account grouping. Refs #8416 --- .../src/Quantification/CachedExperimentInfo.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp index 1f599400b066..8404eff688f8 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp @@ -189,13 +189,8 @@ namespace Mantid m_sampleWidths = shape.getBoundingBox().width(); // Detector volume - const Geometry::Object_const_sptr detShape = instrument->getDetector(detID)->shape(); - if(!detShape) - { - throw std::invalid_argument("CachedExperimentInfo::initCaches - Detector has no bounding box, cannot sample from it. ID:" - + boost::lexical_cast(det->getID())); - } - m_detBox = detShape->getBoundingBox(); + // Make sure it encompasses all possible detectors + det->getBoundingBox(m_detBox); const double rad2deg = 180./M_PI; const double thetaInDegs = twoTheta()*rad2deg; From 298fb787e562c518dca5438e1f51617d0677fdf9 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 29 Nov 2013 11:08:59 +0000 Subject: [PATCH 049/403] Refs #8176 Tidy output to table. --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index 7308bf3e506c..3564da58a783 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -87,13 +87,13 @@ def PyExec(self): # Convert all values to string outputValues = map (str, outputValues) - + output = zip (outputNames, outputValues) #build table of values - for name, value in output: - tableWs.addRow([name, value]) - logger.notice(name + ": " + value) + for data in output: + tableWs.addRow(list(data)) + logger.information(name + ": " + value) #remove idf/ipf workspace DeleteWorkspace(workspace) From 637d189a96e8448aa23070e8dfe71cfbc92e4100 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 29 Nov 2013 14:57:12 +0000 Subject: [PATCH 050/403] Refs #8512 Add better error message. --- Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp index 121194572244..0d7d64069ac6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp @@ -1669,7 +1669,11 @@ void Indirect::calPlotEnergy() QString pyOutput = runPythonCode(pyInput).trimmed(); //something went wrong in the python - if(pyOutput == "None") return; + if(pyOutput == "None") + { + showInformationBox("Failed to plot energy. See log for details."); + return; + } Mantid::API::MatrixWorkspace_sptr input = boost::dynamic_pointer_cast(Mantid::API::AnalysisDataService::Instance().retrieve(pyOutput.toStdString())); From 1022b17d38bb4f1dd7103d22fd1edc39f530703a Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Mon, 2 Dec 2013 14:42:12 -0500 Subject: [PATCH 051/403] Re #8536. Added an option to check if the file is writable. --- .../Kernel/inc/MantidKernel/FileValidator.h | 7 ++- .../Kernel/src/DirectoryValidator.cpp | 4 +- .../Framework/Kernel/src/FileValidator.cpp | 59 ++++++++++++++++--- .../Framework/Kernel/test/FileValidatorTest.h | 26 +++++++- 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileValidator.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileValidator.h index bbe5b87c3e01..fde97345c355 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileValidator.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileValidator.h @@ -42,8 +42,7 @@ bool has_ending(const std::string &value, const std::string & ending); class MANTID_KERNEL_DLL FileValidator : public TypedValidator { public: - FileValidator(); - explicit FileValidator(const std::vector& extensions, bool testFileExists = true); + explicit FileValidator(const std::vector& extensions=std::vector(), bool testFileExists = true, bool testCanWrite=false); virtual ~FileValidator(); virtual std::set allowedValues() const; IValidator_sptr clone() const; @@ -52,7 +51,9 @@ class MANTID_KERNEL_DLL FileValidator : public TypedValidator /// The list of permitted extensions const std::set m_extensions; /// Flag indicating whether to test for existence of filename - bool m_fullTest; + bool m_testExist; + /// Flag indicating whether to test for the file being writable + bool m_testCanWrite; private: virtual std::string checkValidity(const std::string &value) const; diff --git a/Code/Mantid/Framework/Kernel/src/DirectoryValidator.cpp b/Code/Mantid/Framework/Kernel/src/DirectoryValidator.cpp index 5e6847dd2b82..33c86eb18035 100644 --- a/Code/Mantid/Framework/Kernel/src/DirectoryValidator.cpp +++ b/Code/Mantid/Framework/Kernel/src/DirectoryValidator.cpp @@ -18,7 +18,7 @@ Logger& DirectoryValidator::g_log = Logger::get("DirectoryValidator"); DirectoryValidator::DirectoryValidator(bool testDirectoryExists) : FileValidator() { - this->m_fullTest = testDirectoryExists; + this->m_testExist = testDirectoryExists; } /// Destructor @@ -52,7 +52,7 @@ std::string DirectoryValidator::checkValidity(const std::string& value) const } //If the path is required to exist check it is there - if ( m_fullTest ) + if ( m_testExist ) { if ( value.empty() || !Poco::File(value).exists() ) return "Directory \"" + value + "\" not found"; diff --git a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp index 8e90d930e212..cdc5f948fd09 100644 --- a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp @@ -25,18 +25,16 @@ namespace Kernel // Initialize the logger Logger& FileValidator::g_log = Logger::get("FileValidator"); -/// Default constructor. -FileValidator::FileValidator() : TypedValidator(), m_extensions(), m_fullTest(true) -{} - /** Constructor * @param extensions :: The permitted file extensions (e.g. .RAW) * @param testFileExists :: Flag indicating whether to test for existence of file (default: yes) */ -FileValidator::FileValidator(const std::vector& extensions, bool testFileExists) : +FileValidator::FileValidator(const std::vector& extensions, bool testFileExists, + bool testCanWrite) : TypedValidator(), m_extensions(extensions.begin(),extensions.end()), - m_fullTest(testFileExists) + m_testExist(testFileExists), + m_testCanWrite(testCanWrite) { for_each(m_extensions.begin(), m_extensions.end(), lowercase()); } @@ -89,11 +87,58 @@ std::string FileValidator::checkValidity(const std::string &value) const } //If the file is required to exist check it is there - if ( m_fullTest && ( value.empty() || !Poco::File(value).exists() ) ) + if ( m_testExist && ( value.empty() || !Poco::File(value).exists() ) ) { return "File \"" + Poco::Path(value).getFileName() + "\" not found"; } + //If the file is required to be writable... + if (m_testCanWrite) + { + if (value.empty()) + return "Cannot write to empty filename"; + + Poco::File file(value); + // the check for writable is different for whether or not a version exists + // this is taken from ConfigService near line 443 + if (file.exists()) + { + try + { + if (!file.canWrite()) + return "File \"" + Poco::Path(value).getFileName() + "\" cannot be written"; + } + catch (std::exception &e) + { + g_log.information() << "Encountered exception while checking for writable: " << e.what(); + } + } + else // if the file doesn't exist try to temporarily create one + { + std::string error; // error message + + try + { + FILE *fp = fopen(value.c_str(), "w+"); + if (!fp) + error = "File \"" + Poco::Path(value).getFileName() + "\" cannot be written"; + else // this only gets run if handle is non-null + { + fclose(fp); + if (file.exists()) + file.remove(false); // non-recursively remove the temp file + } + } + catch (std::exception &e) + { + g_log.information() << "Encountered exception while checking for writable: " << e.what(); + } + + if (!error.empty()) + return error; + } + } + //Otherwise we are okay, file extensions are just a suggestion so no validation on them is necessary return ""; } diff --git a/Code/Mantid/Framework/Kernel/test/FileValidatorTest.h b/Code/Mantid/Framework/Kernel/test/FileValidatorTest.h index 9dc4be3bf6b1..b3d20aa48e8d 100644 --- a/Code/Mantid/Framework/Kernel/test/FileValidatorTest.h +++ b/Code/Mantid/Framework/Kernel/test/FileValidatorTest.h @@ -12,13 +12,18 @@ class FileValidatorTest: public CxxTest::TestSuite { public: -void testVectorConstructor() +void testConstructors() { + // empty constructor + FileValidator v1; + TS_ASSERT_EQUALS(v1.allowedValues().size(), 0 ); + + // one with a vector of extensions std::vector vec; vec.push_back("raw"); vec.push_back("RAW"); - FileValidator v(vec); - TS_ASSERT_EQUALS ( v.allowedValues().size(), 2 ); + FileValidator v2(vec); + TS_ASSERT_EQUALS ( v2.allowedValues().size(), 2 ); } void testPassesOnExistentFile() @@ -109,6 +114,21 @@ void testFailsOnEmptyFileString() TS_ASSERT_EQUALS( file_val.isValid(""), "File \"\" not found" ); } +void testCanWrite() +{ + std::string filename("myJunkFile_hgfvj.cpp"); + + // file existance is optional + FileValidator v1(std::vector(), false, true); + TS_ASSERT_EQUALS( v1.isValid(""), "Cannot write to empty filename" ); + TS_ASSERT_EQUALS( v1.isValid(filename), ""); + + // file existance is required + FileValidator v2(std::vector(), true, true) ; + TS_ASSERT_EQUALS( v2.isValid(""), "File \"\" not found" ); + TS_ASSERT_EQUALS( v2.isValid(filename), "File \"" + filename + "\" not found"); +} + }; #endif /*FILEVALIDATORTEST_H_*/ From b902e1a16e8d50f3ced2ddf864306a70fcd1c018 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Mon, 2 Dec 2013 14:54:45 -0500 Subject: [PATCH 052/403] Re #8536. Using new FileValidator functionality in FileProperty. --- Code/Mantid/Framework/API/src/FileProperty.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/API/src/FileProperty.cpp b/Code/Mantid/Framework/API/src/FileProperty.cpp index 26b6ded0c04b..3850e70b2041 100644 --- a/Code/Mantid/Framework/API/src/FileProperty.cpp +++ b/Code/Mantid/Framework/API/src/FileProperty.cpp @@ -42,7 +42,7 @@ FileProperty::FileProperty(const std::string & name, const std::string& default_ /* Create either a FileValidator or a DirectoryValidator, depending on Action */ (action == FileProperty::Directory || action == FileProperty::OptionalDirectory) ? boost::make_shared(action == FileProperty::Directory) : - boost::make_shared(exts, (action == FileProperty::Load) ) + boost::make_shared(exts, (action == FileProperty::Load), (action == FileProperty::Save) ) , direction), m_action(action), m_defaultExt(""), @@ -69,7 +69,7 @@ FileProperty::FileProperty(const std::string & name, const std::string& default_ /* Create either a FileValidator or a DirectoryValidator, depending on Action */ (action == FileProperty::Directory || action == FileProperty::OptionalDirectory) ? boost::make_shared(action == FileProperty::Directory) : - boost::make_shared(std::vector(1,ext), (action == FileProperty::Load) ) + boost::make_shared(std::vector(1,ext), (action == FileProperty::Load), (action == FileProperty::Save) ) , direction), m_action(action), m_defaultExt(ext), From 453d6b7c0580c4a4f4c4e61d1065636b6641cec7 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Mon, 2 Dec 2013 15:20:17 -0500 Subject: [PATCH 053/403] Re #8536. Using absolute path in the error if possible. --- .../Mantid/Framework/Kernel/src/FileValidator.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp index cdc5f948fd09..5aa1b9046f8a 100644 --- a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp @@ -86,10 +86,19 @@ std::string FileValidator::checkValidity(const std::string &value) const } } + // create a variable for the absolute path to be used in error messages + std::string abspath(value); + if (!value.empty()) + { + Poco::Path path(value); + if (path.isAbsolute()) + abspath = path.toString(); + } + //If the file is required to exist check it is there if ( m_testExist && ( value.empty() || !Poco::File(value).exists() ) ) { - return "File \"" + Poco::Path(value).getFileName() + "\" not found"; + return "File \"" + abspath + "\" not found"; } //If the file is required to be writable... @@ -106,7 +115,7 @@ std::string FileValidator::checkValidity(const std::string &value) const try { if (!file.canWrite()) - return "File \"" + Poco::Path(value).getFileName() + "\" cannot be written"; + return "File \"" + abspath + "\" cannot be written"; } catch (std::exception &e) { @@ -121,7 +130,7 @@ std::string FileValidator::checkValidity(const std::string &value) const { FILE *fp = fopen(value.c_str(), "w+"); if (!fp) - error = "File \"" + Poco::Path(value).getFileName() + "\" cannot be written"; + error = "File \"" + abspath + "\" cannot be written"; else // this only gets run if handle is non-null { fclose(fp); From c1d91f54fdbf1055fc44c5ac2b88c67433ba01f0 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 3 Dec 2013 13:19:43 -0500 Subject: [PATCH 054/403] Re #8536. Creating a clearer error message in FileProperty. --- Code/Mantid/Framework/API/src/FileProperty.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/API/src/FileProperty.cpp b/Code/Mantid/Framework/API/src/FileProperty.cpp index 3850e70b2041..8a76e4065d4d 100644 --- a/Code/Mantid/Framework/API/src/FileProperty.cpp +++ b/Code/Mantid/Framework/API/src/FileProperty.cpp @@ -370,7 +370,7 @@ std::string FileProperty::createDirectory(const std::string & path) const { stempath.makeParent(); } - std::string error(""); + if( !stempath.toString().empty() ) { Poco::File stem(stempath); @@ -378,19 +378,22 @@ std::string FileProperty::createDirectory(const std::string & path) const { try { - stem.createDirectories(); + stem.createDirectories(); } catch(Poco::Exception &e) { - error = e.what(); + std::stringstream msg; + msg << "Failed to create directory \"" << stempath.toString() + << "\": " << e.what() ; + return msg.str(); } } } else { - error = "Invalid directory."; + return "Invalid directory."; } - return error; + return ""; // everything went fine } /** From 157fc1f896361e40ea23fd7788e748e8919e4d0d Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 3 Dec 2013 13:21:23 -0500 Subject: [PATCH 055/403] Re #8536. Don't create a temporary file. --- .../Framework/Kernel/src/FileValidator.cpp | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp index 5aa1b9046f8a..22c94717f768 100644 --- a/Code/Mantid/Framework/Kernel/src/FileValidator.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileValidator.cpp @@ -124,27 +124,35 @@ std::string FileValidator::checkValidity(const std::string &value) const } else // if the file doesn't exist try to temporarily create one { - std::string error; // error message - try { - FILE *fp = fopen(value.c_str(), "w+"); - if (!fp) - error = "File \"" + abspath + "\" cannot be written"; - else // this only gets run if handle is non-null + Poco::Path direc(value); + if (direc.isAbsolute()) { - fclose(fp); - if (file.exists()) - file.remove(false); // non-recursively remove the temp file + // look for an existing parent + while (!Poco::File(direc).exists()) + { + direc = direc.parent(); + } + + // see if the directory exists + Poco::File direcFile(direc); + if (direcFile.exists() && direcFile.isDirectory()) + { + if (direcFile.canWrite()) + return ""; + else + return "Cannot write to directory \"" + direc.toString() + "\""; + } } + + g_log.debug() << "Do not have enough information to validate \"" + << abspath << "\"\n"; } catch (std::exception &e) { g_log.information() << "Encountered exception while checking for writable: " << e.what(); } - - if (!error.empty()) - return error; } } From c14b6cccc6978bc0f14c0cb218f3dabea5602d3b Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Wed, 4 Dec 2013 15:24:07 +0000 Subject: [PATCH 056/403] Import numpy in TubeCalibDemoMerlin_Adjustable.py re #8263 Signed-off-by: Karl Palmen --- .../Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py index f0cd75cc81b0..a18ae2d0ff67 100644 --- a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py +++ b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py @@ -14,6 +14,7 @@ import tube from tube_calib_fit_params import * # To handle fit parameters import os +import numpy def CalibrateMerlin( RunNumber, UsePeakFile=False ): # Run number must include any leading zeros that appear in the file name of the run. From 68619d6c9d75f13350c7d35ea1b3d644cc4e7a30 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 4 Dec 2013 16:01:52 +0000 Subject: [PATCH 057/403] Refs #8534. Initial files for new VectorColumn class. --- .../Framework/DataObjects/CMakeLists.txt | 5 +- .../inc/MantidDataObjects/VectorColumn.h | 150 ++++++++++++++++++ .../DataObjects/src/VectorColumn.cpp | 8 + .../DataObjects/test/VectorColumnTest.h | 28 ++++ 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h create mode 100644 Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp create mode 100644 Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h diff --git a/Code/Mantid/Framework/DataObjects/CMakeLists.txt b/Code/Mantid/Framework/DataObjects/CMakeLists.txt index 0b3939ea3c68..eab9aa0810c4 100644 --- a/Code/Mantid/Framework/DataObjects/CMakeLists.txt +++ b/Code/Mantid/Framework/DataObjects/CMakeLists.txt @@ -22,6 +22,7 @@ set ( SRC_FILES src/SplittersWorkspace.cpp src/TableColumn.cpp src/TableWorkspace.cpp + src/VectorColumn.cpp src/Workspace2D.cpp src/WorkspaceSingleValue.cpp ) @@ -57,6 +58,7 @@ set ( INC_FILES inc/MantidDataObjects/SplittersWorkspace.h inc/MantidDataObjects/TableColumn.h inc/MantidDataObjects/TableWorkspace.h + inc/MantidDataObjects/VectorColumn.h inc/MantidDataObjects/Workspace2D.h inc/MantidDataObjects/WorkspaceSingleValue.h ) @@ -64,9 +66,9 @@ set ( INC_FILES set ( TEST_FILES CompressedWorkspace2DTest.h EventListTest.h - EventsTest.h EventWorkspaceMRUTest.h EventWorkspaceTest.h + EventsTest.h GroupingWorkspaceTest.h Histogram1DTest.h LibraryManagerTest.h @@ -86,6 +88,7 @@ set ( TEST_FILES TableWorkspacePropertyTest.h TableWorkspaceTest.h TofEventTest.h + VectorColumnTest.h WeightedEventNoTimeTest.h WeightedEventTest.h Workspace2DTest.h diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h new file mode 100644 index 000000000000..7542aec4c9eb --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -0,0 +1,150 @@ +#ifndef MANTID_DATAOBJECTS_VECTORCOLUMN_H_ +#define MANTID_DATAOBJECTS_VECTORCOLUMN_H_ + +#include "MantidAPI/Column.h" +#include "MantidKernel/System.h" + + +namespace Mantid +{ +namespace DataObjects +{ + + using namespace Kernel; + using namespace API; + + /** VectorColumn : TODO: DESCRIPTION + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport VectorColumn : public Column + { + public: + VectorColumn() + { + // TODO: implement + } + + virtual ~VectorColumn() + { + // TODO: implement + } + + /// Number of individual elements in the column + virtual size_t size() const + { + return m_data.size(); + } + + /// Returns typeid for the data in the column + virtual const std::type_info& get_type_info() const + { + return typeid(int); // TODO: for now + } + + /// Returns typeid for the pointer type to the data element in the column + virtual const std::type_info& get_pointer_type_info() const + { + return typeid(int); // TODO: for now + } + + /// Print specified item to the stream + virtual void print(size_t index, std::ostream& s) const + { + // TODO: implement + } + + /// Set item from a string value + virtual void read(size_t index, const std::string & text) + { + // TODO: implement + } + + /// Specialized type check + virtual bool isBool() const + { + return false; + } + + /// Overall memory size taken by the column + virtual long int sizeOfData() const + { + return 0; // TODO: for now + } + + /// Create another copy of the column + virtual VectorColumn* clone() const + { + return NULL; // TODO: for now + } + + /// Cast to double + virtual double toDouble(size_t i) const + { + throw std::runtime_error("VectorColumn is not convertible to double."); + } + + /// Assign from double + virtual void fromDouble(size_t i, double value) + { + throw std::runtime_error("VectorColumn is not assignable from double."); + } + + protected: + /// Sets the new column size. + virtual void resize(size_t count) + { + // TODO: implement + } + + /// Inserts an item. + virtual void insert(size_t index) + { + // TODO: implement + } + + /// Removes an item. + virtual void remove(size_t index) + { + } + + /// Pointer to a data element + virtual void* void_pointer(size_t index) + { + return NULL; + } + + /// Pointer to a data element + virtual const void* void_pointer(size_t index) const + { + return NULL; + } + + private: + /// All the vectors stored + std::vector< std::vector > m_data; + }; + + +} // namespace DataObjects +} // namespace Mantid + +#endif /* MANTID_DATAOBJECTS_VECTORCOLUMN_H_ */ diff --git a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp new file mode 100644 index 000000000000..c673a7810041 --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp @@ -0,0 +1,8 @@ +#include "MantidDataObjects/VectorColumn.h" + +namespace Mantid +{ +namespace DataObjects +{ +} // namespace DataObjects +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h new file mode 100644 index 000000000000..0fb5ee01d419 --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -0,0 +1,28 @@ +#ifndef MANTID_DATAOBJECTS_VECTORCOLUMNTEST_H_ +#define MANTID_DATAOBJECTS_VECTORCOLUMNTEST_H_ + +#include + +#include "MantidDataObjects/VectorColumn.h" + +using Mantid::DataObjects::VectorColumn; + +class VectorColumnTest : public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static VectorColumnTest *createSuite() { return new VectorColumnTest(); } + static void destroySuite( VectorColumnTest *suite ) { delete suite; } + + + void test_Something() + { + TSM_ASSERT( "You forgot to write a test!", 0); + } + + +}; + + +#endif /* MANTID_DATAOBJECTS_VECTORCOLUMNTEST_H_ */ \ No newline at end of file From 787b53b298d2a03bcec464c9758aa63ed128a450 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 4 Dec 2013 16:38:49 +0000 Subject: [PATCH 058/403] Refs #8550. Make the column class templated. Instantiated for int for now and done a simple test. --- .../inc/MantidDataObjects/VectorColumn.h | 28 +++++++++++-------- .../DataObjects/src/VectorColumn.cpp | 1 + .../DataObjects/test/VectorColumnTest.h | 8 +++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 7542aec4c9eb..b84e6a89c118 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -35,18 +35,18 @@ namespace DataObjects File change history is stored at: Code Documentation is available at: */ + + template class DLLExport VectorColumn : public Column { public: VectorColumn() { - // TODO: implement + m_type = typeName(); } virtual ~VectorColumn() - { - // TODO: implement - } + {} /// Number of individual elements in the column virtual size_t size() const @@ -57,13 +57,13 @@ namespace DataObjects /// Returns typeid for the data in the column virtual const std::type_info& get_type_info() const { - return typeid(int); // TODO: for now + return typeid( std::vector ); } /// Returns typeid for the pointer type to the data element in the column virtual const std::type_info& get_pointer_type_info() const { - return typeid(int); // TODO: for now + return typeid( std::vector* ); } /// Print specified item to the stream @@ -87,13 +87,13 @@ namespace DataObjects /// Overall memory size taken by the column virtual long int sizeOfData() const { - return 0; // TODO: for now + // TODO: implement } /// Create another copy of the column virtual VectorColumn* clone() const { - return NULL; // TODO: for now + // TODO: implement } /// Cast to double @@ -129,22 +129,28 @@ namespace DataObjects /// Pointer to a data element virtual void* void_pointer(size_t index) { - return NULL; + // TODO: implement } /// Pointer to a data element virtual const void* void_pointer(size_t index) const { - return NULL; + // TODO: implement } private: /// All the vectors stored - std::vector< std::vector > m_data; + std::vector< std::vector > m_data; + + /// Returns the name of the column with the given type. Is specialized using DECLARE_VECTORCOLUMN + std::string typeName(); }; } // namespace DataObjects } // namespace Mantid +#define DECLARE_VECTORCOLUMN(Type,TypeName) \ + template<> std::string VectorColumn::typeName() { return #TypeName; }; + #endif /* MANTID_DATAOBJECTS_VECTORCOLUMN_H_ */ diff --git a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp index c673a7810041..6379392559d8 100644 --- a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp +++ b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp @@ -4,5 +4,6 @@ namespace Mantid { namespace DataObjects { + DECLARE_VECTORCOLUMN(int, vector_int); } // namespace DataObjects } // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h index 0fb5ee01d419..f3eab1b84130 100644 --- a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -15,14 +15,14 @@ class VectorColumnTest : public CxxTest::TestSuite static VectorColumnTest *createSuite() { return new VectorColumnTest(); } static void destroySuite( VectorColumnTest *suite ) { delete suite; } - - void test_Something() + void test_construction() { - TSM_ASSERT( "You forgot to write a test!", 0); + VectorColumn col; + TS_ASSERT_EQUALS( col.type(), "vector_int"); } }; -#endif /* MANTID_DATAOBJECTS_VECTORCOLUMNTEST_H_ */ \ No newline at end of file +#endif /* MANTID_DATAOBJECTS_VECTORCOLUMNTEST_H_ */ From fa76bb339489f748bea0f406f8c9c44b0d837552 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Wed, 4 Dec 2013 16:47:03 +0000 Subject: [PATCH 059/403] Import numpy in TubeCalibDemoMerlin_Simple.py re #8263 Signed-off-by: Karl Palmen --- .../scripts/Calibration/Examples/TubeCalibDemoMerlin_Simple.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Simple.py b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Simple.py index 0a0bcd00ab75..d4b6727f29c9 100644 --- a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Simple.py +++ b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Simple.py @@ -13,6 +13,7 @@ import tube from tube_calib_fit_params import TubeCalibFitParams +import numpy RunNumber = 12024 def CalibrateMerlin(RunNumber): From 38ec9a3534c7ff73853a98315c987f61f2dce220 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 13:21:17 -0500 Subject: [PATCH 060/403] Refs #8508 Moved to a C++ algorithm modified: Framework/CurveFitting/CMakeLists.txt new file: Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h new file: Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp new file: Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h deleted: Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py --- .../Framework/CurveFitting/CMakeLists.txt | 3 + .../DiffRotDiscreteCircle.h | 128 +++++++ .../src/DiffRotDiscreteCircle.cpp | 202 +++++++++++ .../test/DiffRotDiscreteCircleTest.h | 343 ++++++++++++++++++ .../functions/DiffRotDiscreteCircle.py | 65 ---- 5 files changed, 676 insertions(+), 65 deletions(-) create mode 100644 Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h create mode 100644 Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp create mode 100644 Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h delete mode 100644 Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py diff --git a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt index 3cd278e5bc6c..a8ae53dc5ad9 100644 --- a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt +++ b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt @@ -22,6 +22,7 @@ set ( SRC_FILES src/DampingMinimizer.cpp src/DeltaFunction.cpp src/DerivMinimizer.cpp + src/DiffRotDiscreteCircle.cpp src/DiffSphere.cpp src/ElasticDiffSphere.cpp src/EndErfc.cpp @@ -119,6 +120,7 @@ set ( INC_FILES inc/MantidCurveFitting/DeltaFunction.h inc/MantidCurveFitting/DerivMinimizer.h inc/MantidCurveFitting/DiffSphere.h + inc/MantidCurveFitting/DiffRotDiscreteCircle.h inc/MantidCurveFitting/DllConfig.h inc/MantidCurveFitting/ElasticDiffSphere.h inc/MantidCurveFitting/EmptyValues.h @@ -213,6 +215,7 @@ set ( TEST_FILES CubicSplineTest.h DampingMinimizerTest.h DeltaFunctionTest.h + DiffRotDiscreteCircleTest.h EndErfcTest.h ExpDecayMuonTest.h ExpDecayOscTest.h diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h new file mode 100644 index 000000000000..5ac1b817c39f --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -0,0 +1,128 @@ +#ifndef MANTID_DIFFROTDISCRETECIRCLE_H_ +#define MANTID_DIFFROTDISCRETECIRCLE_H_ + +#include "MantidAPI/ParamFunction.h" +#include "MantidAPI/IFunction1D.h" +#include "MantidAPI/FunctionDomain.h" +#include "MantidAPI/Jacobian.h" +#include "MantidAPI/ImmutableCompositeFunction.h" +#include "DeltaFunction.h" + +namespace Mantid +{ +namespace CurveFitting +{ + /** + @author Jose Borreguero, NScD + @date December 02 2013 + + Copyright © 2007-8 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + +/* Class representing the elastic portion of DiffRotDiscreteCircle + * Contains a Delta Dirac. + */ +class DLLExport ElasticDiffRotDiscreteCircle : public DeltaFunction +{ +public: + + /// Constructor + ElasticDiffRotDiscreteCircle(); + + /// Destructor + virtual ~ElasticDiffRotDiscreteCircle() {}; + + /// overwrite IFunction base class methods + virtual std::string name()const{return "ElasticDiffRotDiscreteCircle";} + + /// A rescaling of the peak intensity + double HeightPrefactor() const; + +}; + + +/* Class representing the inelastic portion of DiffRotDiscreteCircle + * Contains a linear combination of Lorentzians. + */ +class DLLExport InelasticDiffRotDiscreteCircle : public API::ParamFunction, public API::IFunction1D +{ +public: + + /// Constructor + InelasticDiffRotDiscreteCircle(); + + /// Destructor + virtual ~InelasticDiffRotDiscreteCircle() {} + + virtual std::string name() const {return "InelasticDiffRotDiscreteCircle";} + +protected: + + virtual void function1D(double * out, const double* xValues, const size_t nData) const; + +private: + + const double m_t2e; // converstion from picosec to mili-eV, or from nanosec to micro-eV +}; + + +/* Class representing the dynamics structure factor of a particle undergoing + * discrete jumps on N-sites evenly distributed in a circle. The particle can only + * jump to neighboring sites. This is the most common type of discrete + * rotational diffusion in a circle. + */ +class DLLExport DiffRotDiscreteCircle : public API::ImmutableCompositeFunction +{ +public: + + /// Constructor + DiffRotDiscreteCircle(); + + /// Destructor + ~DiffRotDiscreteCircle() {}; + + virtual std::string name() const { return "DiffRotDiscreteCircle"; } + + virtual const std::string category() const { return "QENS"; } + + virtual int version() const { return 1; } + + /// Propagate an attribute to member functions + virtual void trickleDownAttribute( const std::string &name ); + + /// Override parent definition + virtual void declareAttribute( const std::string & name, const API::IFunction::Attribute & defaultValue); + + /// Override parent definition + virtual void setAttribute( const std::string & attName, const Attribute & att); + +private: + + boost::shared_ptr m_elastic; + + boost::shared_ptr m_inelastic; + +}; + +} // namespace CurveFitting +} // namespace Mantid + +#endif /*MANTID_DIFFROTDISCRETECIRCLE_H_*/ diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp new file mode 100644 index 000000000000..d0d59e65fd88 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -0,0 +1,202 @@ +/*WIKI* +This fitting function models the dynamics structure factor of a particle undergoing +discrete jumps on N-sites evenly distributed in a circle. The particle can only +jump to neighboring sites. This is the most common type of discrete rotational diffusion +in a circle. + +The fitting parameters are the inverse of the transition rate, \tau +and the circle radius r + + S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) + + \tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N}) + +If the energy units of energy are micro-eV, then tau is expressed in nano-seconds. If E-units are mili-eV then +tau is expressed in pico-seconds. +*WIKI*/ + +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidCurveFitting/DiffRotDiscreteCircle.h" +#include "MantidCurveFitting/BoundaryConstraint.h" +#include "MantidAPI/FunctionFactory.h" +#include +#include "MantidAPI/ParameterTie.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +namespace Mantid +{ +namespace CurveFitting +{ + +DECLARE_FUNCTION(ElasticDiffRotDiscreteCircle); +DECLARE_FUNCTION(InelasticDiffRotDiscreteCircle); +DECLARE_FUNCTION(DiffRotDiscreteCircle); + +ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ + //declareParameter("Height", 1.0); //parameter "Height" already declared in constructor of base class DeltaFunction + declareParameter("Radius", 1.0, "Circle radius"); + + // Ensure positive values for Height and Radius + BoundaryConstraint* HeightConstraint = new BoundaryConstraint( this, "Height", std::numeric_limits::epsilon(), true ); + addConstraint(HeightConstraint); + + BoundaryConstraint* RadiusConstraint = new BoundaryConstraint( this, "Radius", std::numeric_limits::epsilon(), true ); + addConstraint(RadiusConstraint); + + declareAttribute( "Q", API::IFunction::Attribute(0.5) ); + declareAttribute( "N", API::IFunction::Attribute(3) ); + +} + +double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ + const double R = getParameter("Radius"); + const double Q = getAttribute("Q").asDouble(); + const int N = getAttribute("N").asInt(); + double aN = 0; + for ( int k=1; k::epsilon(), true); + addConstraint(IntensityConstraint); + + BoundaryConstraint* RadiusConstraint = new BoundaryConstraint(this, "Radius", std::numeric_limits::epsilon(), true); + addConstraint(RadiusConstraint); + + BoundaryConstraint* DecayConstraint = new BoundaryConstraint(this, "Decay", std::numeric_limits::epsilon(), true); + addConstraint(DecayConstraint); + +} + + +void InelasticDiffRotDiscreteCircle::function1D(double *out, const double* xValues, const size_t nData) const +{ + const double I = getParameter("Intensity"); + const double R = getParameter("Radius"); + const double rate = m_t2e / getParameter("Decay"); // micro-eV or mili-eV + const double Q = getAttribute("Q").asDouble(); + const int N = getAttribute("N").asInt(); + + double sph[N]; + for (int k=1; kgetAttribute(name) by reference, thus the same + * object is shared by the composite function and its members. + */ +void DiffRotDiscreteCircle::trickleDownAttribute( const std::string& name ) +{ + for(size_t iFun=0; iFun < nFunctions(); iFun++) + { + API::IFunction_sptr fun = getFunction(iFun); + if( fun -> hasAttribute( name ) ) + fun -> setAttribute( name, this -> getAttribute(name) ); + } +} + +/* Same as parent except we overwrite attributes of member functions + * having the same name + */ +void DiffRotDiscreteCircle::declareAttribute( const std::string & name, const API::IFunction::Attribute & defaultValue ) +{ + API::ImmutableCompositeFunction::declareAttribute( name, defaultValue ); + trickleDownAttribute( name ); +} + +/* Same as parent except we overwrite attributes of member functions + * having the same name + */ +void DiffRotDiscreteCircle::setAttribute( const std::string& name, const Attribute& att ) +{ + API::ImmutableCompositeFunction::setAttribute( name, att ); + trickleDownAttribute( name ); +} + +DiffRotDiscreteCircle::DiffRotDiscreteCircle() +{ + m_elastic = boost::dynamic_pointer_cast(API::FunctionFactory::Instance().createFunction("ElasticDiffRotDiscreteCircle")); + addFunction( m_elastic ); + m_inelastic = boost::dynamic_pointer_cast(API::FunctionFactory::Instance().createFunction("InelasticDiffRotDiscreteCircle")); + addFunction( m_inelastic ); + + this->setAttributeValue("NumDeriv", true ); + + this->declareAttribute("Q", API::IFunction::Attribute(0.5) ); + this->declareAttribute("N", API::IFunction::Attribute(3) ); + + //Set the aliases + this->setAlias("f1.Intensity","Intensity"); + this->setAlias("f1.Radius","Radius"); + this->setAlias("f1.Decay","Decay"); + + //Set the ties between Elastic and Inelastic parameters + this->addDefaultTies("f0.Height=f1.Intensity,f0.Radius=f1.Radius"); + this->applyTies(); + +} + + + + + + + + + + + + +} // namespace CurveFitting +} // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h new file mode 100644 index 000000000000..4e6103140d01 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -0,0 +1,343 @@ +#ifndef DIFFROTDISCRETECIRCLETEST_H_ +#define DIFFROTDISCRETECIRCLETEST_H_ + +#include +#include +#include +#include + +#include "MantidCurveFitting/Gaussian.h" +#include "MantidCurveFitting/DiffRotDiscreteCircle.h" +#include "MantidCurveFitting/Convolution.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidCurveFitting/Fit.h" +#include "MantidAPI/FunctionFactory.h" +#include "MantidAPI/AlgorithmFactory.h" + +class DiffRotDiscreteCircleTest : public CxxTest::TestSuite +{ + +public: + + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static DiffRotDiscreteCircleTest *createSuite() { return new DiffRotDiscreteCircleTest(); } + static void destroySuite( DiffRotDiscreteCircleTest *suite ) { delete suite; } + + // convolve the elastic part with a resolution function, here a Gaussian + void testDiffRotDiscreteCircleElastic() + { + // initialize the resolution function + const double w0 = random_value( -1.0, 1.0 ); + const double h = random_value( 1.0, 1000.0 ); + const double fwhm = random_value( 1.0, 100.0 ); + boost::shared_ptr resolution( new Mantid::CurveFitting::Gaussian() ); + resolution -> initialize(); // declare parameters + resolution -> setCentre( w0 ); + resolution -> setHeight( h ); + resolution -> setFwhm( fwhm ); + + // initialize the structure factor as the elastic part of DiffRotDiscreteCircle + const double I = random_value( 1.0, 1000.0 ); + const double r = random_value( 0.3, 9.8 ); + const double Q = 0.9; + const int N = 6; + boost::shared_ptr structure_factor( new Mantid::CurveFitting::ElasticDiffRotDiscreteCircle() ); + structure_factor -> setParameter( "Height", I ); + structure_factor -> setParameter( "Radius", r ); + structure_factor -> setAttributeValue( "Q", Q ); + structure_factor -> setAttributeValue( "N", N ); + + // initialize the convolution function + Mantid::CurveFitting::Convolution conv; + conv.addFunction( resolution ); + conv.addFunction( structure_factor ); + + // initialize some frequency values centered around zero + const size_t M = 4001; + double w[ M ]; + const double dw = random_value(0.1, 0.5); // bin width + for( size_t i = 0; i < M; i++ ) w[i] = (static_cast(i) - M/2 ) * dw; + Mantid::API::FunctionDomain1DView xView( &w[0], M ); + Mantid::API::FunctionValues out( xView ); + + // convolve + conv.function( xView, out ); + + // Result must be the resolution function multiplied by the intensity of ElasticDiffRotDiscreteCircle + double scaling = I * structure_factor -> HeightPrefactor(); + Mantid::API::FunctionValues out_resolution( xView ); + resolution -> function( xView, out_resolution ); + for( size_t i = 0; i < M; i++ ) + TS_ASSERT_DELTA( out.getCalculated( i ), scaling * out_resolution.getCalculated( i ), 1e-3 ); + + } // testDiffRotDiscreteCircleElastic + + + /// Fit the convolution of the inelastic part with a Gaussian resolution function + void testDiffRotDiscreteCircleInelastic() + { + /* Note: it turns out that parameters Intensity and Radius are highly covariant, so that more than one minimum exists. + * Thus, I tied parameter Radius. This is OK since one usually knows the radius of the circle of the jumping diffusion + */ + + // initialize the fitting function in a Fit algorithm + // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units + std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1.0,PeakCentre=0.0,Sigma=20.0,ties=(Height=1.0,PeakCentre=0.0,Sigma=20.0);name=InelasticDiffRotDiscreteCircle,N=3,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567)"; + + // Initialize the fit function in the Fit algorithm + Mantid::CurveFitting::Fit fitalg; + TS_ASSERT_THROWS_NOTHING( fitalg.initialize() ); + TS_ASSERT( fitalg.isInitialized() ); + fitalg.setProperty( "Function", funtion_string ); + + // create the data workspace by evaluating the fit function in the Fit algorithm + auto data_workspace = generateWorkspace( fitalg ); + //saveWorkspace( data_workspace, "/tmp/junk.nxs" ); // for debugging purposes only + + //override the function with new parameters, then do the Fit + funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1.0,PeakCentre=0.0,Sigma=20.0,ties=(Height=1.0,PeakCentre=0.0,Sigma=20.0);name=InelasticDiffRotDiscreteCircle,N=3,Q=0.5,Intensity=10.0,Radius=1.567,Decay=20.0,ties=(Radius=1.567))"; + fitalg.setProperty( "Function", funtion_string ); + fitalg.setProperty( "InputWorkspace", data_workspace ); + fitalg.setPropertyValue( "WorkspaceIndex", "0" ); + TS_ASSERT_THROWS_NOTHING( TS_ASSERT( fitalg.execute() ) ); + TS_ASSERT( fitalg.isExecuted() ); + + // check Chi-square is small + const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); + TS_ASSERT_DELTA( chi_squared, 0.01, 0.01 ); + //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes + + // check the parameters of the resolution did not change + Mantid::API::IFunction_sptr fitalg_function = fitalg.getProperty( "Function" ); + auto fitalg_conv = boost::dynamic_pointer_cast( fitalg_function ) ; + Mantid::API::IFunction_sptr fitalg_resolution = fitalg_conv->getFunction( 0 ); + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "PeakCentre" ), 0.0, 0.00001 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "Height" ), 1.0, 1.0 * 0.001 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "Sigma" ), 20.0, 20.0* 0.001 ); // allow for a small percent variation + //std::cout << "\nPeakCentre = " << fitalg_resolution->getParameter("PeakCentre") << " Height= " << fitalg_resolution->getParameter("Height") << " Sigma=" << fitalg_resolution->getParameter("Sigma") << "\n"; // only for debugging purposes + + // check the parameters of the inelastic part + Mantid::API::IFunction_sptr fitalg_structure_factor = fitalg_conv->getFunction( 1 ); + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Intensity" ), 47.014, 47.014 * 0.05 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Radius" ), 1.567, 1.567 * 0.05 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Decay" ), 7.567, 7.567 * 0.05 ); // allow for a small percent variation + //std::cout << "\nGOAL: Intensity = 47.014, Radius = 1.567, Decay = 7.567\n"; // only for debugging purposes + //std::cout << "OPTIMIZED: Intensity = " << fitalg_structure_factor->getParameter("Intensity") << " Radius = " << fitalg_structure_factor->getParameter("Radius") << " Decay = " << fitalg_structure_factor->getParameter("Decay") << "\n"; // only for debugging purposes + + } // testDiffRotDiscreteCircleElastic + + + /// check ties between elastic and inelastic parts + void testDiffRotDiscreteCircleTies() + { + const double I = 2.9; + const double R = 2.3; + const double tao = 0.45; + const double Q = 0.7; + const int N = 4; + Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.setParameter( "f1.Intensity", I ); + func.setParameter( "f1.Radius" , R ); + func.setParameter( "f1.Decay", tao ); + func.setAttributeValue( "Q" , Q ); + func.setAttributeValue( "N", N ); + + // check values where correctly initialized + auto ids = boost::dynamic_pointer_cast( func.getFunction(1) ); + TS_ASSERT_EQUALS( ids->getParameter("Intensity"), I ); + TS_ASSERT_EQUALS( ids->getParameter("Radius"), R ); + TS_ASSERT_EQUALS( ids->getParameter("Decay"), tao ); + TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); + TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); + + //check the ties were applied correctly + func.applyTies(); //elastic parameters are tied to inelastic parameters + auto eds = boost::dynamic_pointer_cast( func.getFunction(0) ); + TS_ASSERT_EQUALS( eds->getParameter("Height") , I ); + TS_ASSERT_EQUALS( eds->getParameter("Radius") , R ); + TS_ASSERT_EQUALS( eds->getAttribute("Q").asDouble(), Q ); + } + + + /// check aliases in the composite function + void testDiffRotDiscreteCircleAliases() + { + const double I = 2.9; + const double R = 2.3; + const double tao = 0.45; + + // This should set parameters of the inelastic part + Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.setParameter( "Intensity", I ); + func.setParameter( "Radius", R ); + func.setParameter( "Decay", tao ); + + // check the parameter of the inelastic part + auto ifunc = boost::dynamic_pointer_cast( func.getFunction(1) ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Intensity" ), I ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Radius" ), R ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Decay" ), tao ); + + // check the parameters of the elastic part + func.applyTies(); //elastic parameters are tied to inelastic parameters + auto efunc = boost::dynamic_pointer_cast( func.getFunction(0) ); + TS_ASSERT_EQUALS( efunc -> getParameter( "Height" ) , I ); + TS_ASSERT_EQUALS( efunc -> getParameter( "Radius" ) , R ); + + } // testDiffRotDiscreteCircleAliases + + + /// Fit the convolution of the jumping diffusion with a Gaussian resolution function + void testDiffRotDiscreteCircle() + { + // initialize the fitting function in a Fit algorithm + // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units + std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1,PeakCentre=0,Sigma=20,ties=(Height=1,PeakCentre=0,Sigma=20);(name=DiffRotDiscreteCircle,N=3,NumDeriv=true,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567))"; + + // Initialize the fit function in the Fit algorithm + Mantid::CurveFitting::Fit fitalg; + TS_ASSERT_THROWS_NOTHING( fitalg.initialize() ); + TS_ASSERT( fitalg.isInitialized() ); + fitalg.setProperty( "Function", funtion_string ); + + // create the data workspace by evaluating the fit function in the Fit algorithm + auto data_workspace = generateWorkspace( fitalg ); + //saveWorkspace( data_workspace, "/tmp/junk.nxs" ); // for debugging purposes only + + //override the function with new parameters, then do the Fit + funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1,PeakCentre=0,Sigma=20,ties=(Height=1,PeakCentre=0,Sigma=20);(name=DiffRotDiscreteCircle,N=3,NumDeriv=true,Q=0.5,Intensity=10.0,Radius=1.567,Decay=20.0))"; + fitalg.setProperty( "Function", funtion_string ); + fitalg.setProperty( "InputWorkspace", data_workspace ); + fitalg.setPropertyValue( "WorkspaceIndex", "0" ); + TS_ASSERT_THROWS_NOTHING( TS_ASSERT( fitalg.execute() ) ); + TS_ASSERT( fitalg.isExecuted() ); + + // check Chi-square is small + const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); + TS_ASSERT_DELTA( chi_squared, 0.01, 0.01 ); + //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes + + // check the parameters of the resolution did not change + Mantid::API::IFunction_sptr fitalg_function = fitalg.getProperty( "Function" ); + auto fitalg_conv = boost::dynamic_pointer_cast( fitalg_function ) ; + Mantid::API::IFunction_sptr fitalg_resolution = fitalg_conv->getFunction( 0 ); + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "PeakCentre" ), 0.0, 0.00001 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "Height" ), 1.0, 1.0 * 0.001 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "Sigma" ), 20.0, 20.0* 0.001 ); // allow for a small percent variation + //std::cout << "\nPeakCentre = " << fitalg_resolution->getParameter("PeakCentre") << " Height= " << fitalg_resolution->getParameter("Height") << " Sigma=" << fitalg_resolution->getParameter("Sigma") << "\n"; // only for debugging purposes + + // check the parameters of the inelastic part + Mantid::API::IFunction_sptr fitalg_structure_factor = fitalg_conv->getFunction( 1 ); + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Intensity" ), 47.014, 47.014 * 0.05 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Radius" ), 1.567, 1.567 * 0.05 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Decay" ), 7.567, 7.567 * 0.05 ); // allow for a small percent variation + //std::cout << "\nGOAL: Intensity = 47.014, Radius = 1.567, Decay = 7.567\n"; // only for debugging purposes + //std::cout << "OPTIMIZED: Intensity = " << fitalg_structure_factor->getParameter("Intensity") << " Radius = " << fitalg_structure_factor->getParameter("Radius") << " Decay = " << fitalg_structure_factor->getParameter("Decay") << "\n"; // only for debugging purposes + + } // testDiffRotDiscreteCircle + + +private: + + /// returns a real value from a uniform distribution + double random_value(const double & a, const double & b) + { + boost::mt19937 rng; + boost::uniform_real distribution( a, b ); + return distribution(rng); + } + + + /// save the domain and the values of a function to a nexus file + void saveValues( Mantid::API::IFunction_sptr &function_pointer, Mantid::API::FunctionDomain1DView &xView, const std::string &filename ) + { + Mantid::API::FunctionValues dataYvalues( xView ); + function_pointer -> function( xView, dataYvalues ); // evaluate the function + const size_t M = xView.size(); + // create temporaray workspace. + auto temp_ws = WorkspaceCreationHelper::Create2DWorkspace(1, static_cast( M ) ); + for( size_t i = 0; i < M; i++ ) + { + temp_ws -> dataX( 0 )[ i ] = xView[ i ]; + temp_ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); + temp_ws -> dataE( 0 )[ i ] = 0.1 * dataYvalues.getCalculated( i ); // assume the error is 10% of the actual value + } + const double dw = xView[1]-xView[0]; // bin width + temp_ws -> dataX( 0 )[ M ] = temp_ws -> dataX( 0 )[ M - 1 ] + dw; + // save workspace to file. + auto save = Mantid::API::AlgorithmFactory::Instance().create( "SaveNexus", 1 ); + if ( !save ) throw std::runtime_error( "Algorithm not created" ); + save -> initialize(); + save -> setProperty( "Filename", filename ); + save -> setProperty( "InputWorkspace", temp_ws ); + save->execute(); + + // some cleaning + Mantid::API::AnalysisDataService::Instance().remove( temp_ws -> getName() ); + + } + + /// save a worskapece to a nexus file + void saveWorkspace( Mantid::DataObjects::Workspace2D_sptr &ws, const std::string &filename ) + { + auto save = Mantid::API::AlgorithmFactory::Instance().create( "SaveNexus", 1 ); + if ( !save ) throw std::runtime_error( "Algorithm not created" ); + save -> initialize(); + save -> setProperty( "Filename", filename ); + save -> setProperty( "InputWorkspace", ws ); + save->execute(); + } + + // create a data workspace using a Fit algorithm + Mantid::DataObjects::Workspace2D_sptr generateWorkspace( Mantid::CurveFitting::Fit & fitalg ) + { + // initialize some frequency values centered around zero. Will work as dataX + const size_t M = 1001; + double dataX[ M ]; + const double dw = 0.4; // typical bin width for BASIS@ORNL beamline, in micro-seconds + for( size_t i = 0; i < M; i++ ) dataX[i] = (static_cast(i) - M/2 ) * dw; + + // Evaluate the fitting function. Will work as dataY + Mantid::API::FunctionDomain1DView dataXview( &dataX[0], M ); + Mantid::API::FunctionValues dataYvalues( dataXview ); + Mantid::API::IFunction_sptr fitalg_function = fitalg.getProperty( "Function" ); + fitalg_function -> function( dataXview, dataYvalues ); + + // create the workspace + auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, M ); + double fractional_error = 0.01; // error taken as a percent of the signal + for( size_t i = 0; i < M; i++ ) + { + ws -> dataX( 0 )[ i ] = dataX[ i ] - dw/2; // bin boundaries are shifted by half the bind width + ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); + ws -> dataE( 0 )[ i ] = fractional_error * dataYvalues.getCalculated( i ); // assume the error is a small percent of the actual value + } + ws -> dataX( 0 )[ M ] = dataX[ M - 1 ] + dw/2; // recall number of bin boundaries is 1 + #bins + + // return now the workspace + return ws; + } + +}; + + + + + + + + + + + + + + + + + + + + +#endif /* DIFFROTDISCRETECIRCLETEST_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py b/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py deleted file mode 100644 index 2aa8d53932bb..000000000000 --- a/Code/Mantid/Framework/PythonInterface/plugins/functions/DiffRotDiscreteCircle.py +++ /dev/null @@ -1,65 +0,0 @@ -'''*WIKI* - -This fitting function models the dynamics structure factor of a particle undergoing -discrete jumps on N-sites evenly distributed in a circle. The particle can only -jump to neighboring sites. This is the most common type of discrete rotational diffusion -in a circle. - -The fitting parameters are the inverse of the transition rate, \tau -and the circle radius r - - S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) - - \tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N}) - -If the energy units of energy are micro-eV, then tau is expressed in pico-seconds. If E-units are micro-eV then -tau is expressed in nano-seconds. -*WIKI* - -@author Jose Borreguero, NScD -@date November 22, 2013 - -Copyright © 2007-8 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -File change history is stored at: -Code Documentation is available at: -''' - -from mantid.api import IFunction1D, FunctionFactory #, BoundaryConstraint -from mantid import logger -import numpy as np -import copy - -from pdb import set_trace as tr - -class DiffRotDiscreteCircleElastic(IFunction1D): - '''Elastic part of the structure factor - ''' - def __init__(self): - '''declare some constants''' - super(DiffRotDiscreteCircleElastic, self).__init__() - self._meV2ps = 4.136 - self._parmset = set(['height','tau','beta']) #valid syntaxfor python >= 2.6 - self._parm2index = {'height':0,'tau':1,'beta':2} #order in which they were defined - - def category(self): - return 'QENS' - - From de36ec3b13e8559f064f9dd55eba05841d7bf679 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 4 Dec 2013 18:41:08 +0000 Subject: [PATCH 061/403] Refs #8550. Read method functionality, plus tests for it. --- .../inc/MantidDataObjects/VectorColumn.h | 33 +++++++++++++-- .../DataObjects/test/VectorColumnTest.h | 42 +++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index b84e6a89c118..3be8571ced14 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -4,6 +4,10 @@ #include "MantidAPI/Column.h" #include "MantidKernel/System.h" +#include +#include +#include +#include namespace Mantid { @@ -75,7 +79,28 @@ namespace DataObjects /// Set item from a string value virtual void read(size_t index, const std::string & text) { - // TODO: implement + std::vector newValues; + + boost::char_separator delim(","); + boost::tokenizer< boost::char_separator > elements(text, delim); + + for ( auto it = elements.begin(); it != elements.end(); it++ ) + { + std::string element(*it); + + boost::trim(element); + + try + { + newValues.push_back( boost::lexical_cast(element) ); + } + catch(boost::bad_lexical_cast&) + { + throw std::invalid_argument("Unable to convert one of the elements: " + element); + } + } + + m_data.at(index) = newValues; } /// Specialized type check @@ -112,7 +137,7 @@ namespace DataObjects /// Sets the new column size. virtual void resize(size_t count) { - // TODO: implement + m_data.resize(count); } /// Inserts an item. @@ -129,13 +154,13 @@ namespace DataObjects /// Pointer to a data element virtual void* void_pointer(size_t index) { - // TODO: implement + return &m_data.at(index); } /// Pointer to a data element virtual const void* void_pointer(size_t index) const { - // TODO: implement + return &m_data.at(index); } private: diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h index f3eab1b84130..6246ea23b6de 100644 --- a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -7,6 +7,15 @@ using Mantid::DataObjects::VectorColumn; +template +class VectorColumnTestHelper : public VectorColumn +{ +public: + using VectorColumn::resize; + using VectorColumn::insert; + using VectorColumn::remove; +}; + class VectorColumnTest : public CxxTest::TestSuite { public: @@ -21,6 +30,39 @@ class VectorColumnTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( col.type(), "vector_int"); } + void test_read() + { + VectorColumnTestHelper col; + + col.resize(5); + + // Simple case + TS_ASSERT_THROWS_NOTHING( col.read(0,"1,2,3") ); + std::vector v1; + v1.push_back(1); v1.push_back(2); v1.push_back(3); + TS_ASSERT_EQUALS( col.cell< std::vector >(0), v1 ); + + // Check if trimming works + TS_ASSERT_THROWS_NOTHING( col.read(1," 4, 5, 6") ); + std::vector v2; + v2.push_back(4); v2.push_back(5); v2.push_back(6); + TS_ASSERT_EQUALS( col.cell< std::vector >(1), v2 ); + + // Single element + TS_ASSERT_THROWS_NOTHING( col.read(2,"7") ); + std::vector v3; + v3.push_back(7); + TS_ASSERT_EQUALS( col.cell< std::vector >(2), v3 ); + + // Empty string + TS_ASSERT_THROWS_NOTHING( col.read(3,"") ); + std::vector v4; + TS_ASSERT_EQUALS( col.cell< std::vector >(3), v4 ); + TS_ASSERT_EQUALS( col.cell< std::vector >(4), v4 ); + + // Non-convertable characters + TS_ASSERT_THROWS( col.read(4,"1,2,a,3"), std::invalid_argument); + } }; From 3f4b415830c4e860b710156ad436a47339937528 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 4 Dec 2013 18:41:27 +0000 Subject: [PATCH 062/403] Refs #8550. Print implementation and tests. --- .../inc/MantidDataObjects/VectorColumn.h | 16 ++++++++++- .../DataObjects/test/VectorColumnTest.h | 27 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 3be8571ced14..0aad690735b0 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -73,7 +73,21 @@ namespace DataObjects /// Print specified item to the stream virtual void print(size_t index, std::ostream& s) const { - // TODO: implement + const std::vector& values = m_data.at(index); + + auto it = values.begin(); + + if ( it != values.end() ) + { + s << *it; + ++it; + } + + for ( ; it != values.end(); ++it ) + { + s << ','; + s << *it; + } } /// Set item from a string value diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h index 6246ea23b6de..1b4b2acfb208 100644 --- a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -64,6 +64,33 @@ class VectorColumnTest : public CxxTest::TestSuite TS_ASSERT_THROWS( col.read(4,"1,2,a,3"), std::invalid_argument); } + void test_print() + { + VectorColumnTestHelper col; + + col.resize(3); + + // Simple case + std::vector v1; + v1.push_back(11); v1.push_back(22); v1.push_back(33); v1.push_back(44); v1.push_back(55); + col.cell< std::vector >(0) = v1; + std::ostringstream s1; + TS_ASSERT_THROWS_NOTHING( col.print(0, s1) ); + TS_ASSERT_EQUALS( s1.str(), "11,22,33,44,55" ); + + // Single element + std::vector v2; + v2.push_back(9876); + col.cell< std::vector >(1) = v2; + std::ostringstream s2; + TS_ASSERT_THROWS_NOTHING( col.print(1, s2) ); + TS_ASSERT_EQUALS( s2.str(), "9876" ); + + // Unset element + std::ostringstream s3; + TS_ASSERT_THROWS_NOTHING( col.print(2, s3) ); + TS_ASSERT( s3.str().empty() ); + } }; From 8af64157f97c1ad42cf47632e3da3294bd93dcef Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 14:08:36 -0500 Subject: [PATCH 063/403] Refs #8508 Cosmetic changes in the code --- .../DiffRotDiscreteCircle.h | 10 +- .../src/DiffRotDiscreteCircle.cpp | 122 ++++++++---------- 2 files changed, 61 insertions(+), 71 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h index 5ac1b817c39f..0e711510bc02 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -51,7 +51,7 @@ class DLLExport ElasticDiffRotDiscreteCircle : public DeltaFunction virtual ~ElasticDiffRotDiscreteCircle() {}; /// overwrite IFunction base class methods - virtual std::string name()const{return "ElasticDiffRotDiscreteCircle";} + virtual std::string name()const{ return "ElasticDiffRotDiscreteCircle"; } /// A rescaling of the peak intensity double HeightPrefactor() const; @@ -72,11 +72,11 @@ class DLLExport InelasticDiffRotDiscreteCircle : public API::ParamFunction, publ /// Destructor virtual ~InelasticDiffRotDiscreteCircle() {} - virtual std::string name() const {return "InelasticDiffRotDiscreteCircle";} + virtual std::string name() const { return "InelasticDiffRotDiscreteCircle"; } protected: - virtual void function1D(double * out, const double* xValues, const size_t nData) const; + virtual void function1D( double * out, const double* xValues, const size_t nData ) const; private: @@ -109,10 +109,10 @@ class DLLExport DiffRotDiscreteCircle : public API::ImmutableCompositeFunction virtual void trickleDownAttribute( const std::string &name ); /// Override parent definition - virtual void declareAttribute( const std::string & name, const API::IFunction::Attribute & defaultValue); + virtual void declareAttribute( const std::string & name, const API::IFunction::Attribute & defaultValue ); /// Override parent definition - virtual void setAttribute( const std::string & attName, const Attribute & att); + virtual void setAttribute( const std::string & attName, const Attribute & att ); private: diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index d0d59e65fd88..38680cf27fba 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -41,14 +41,14 @@ DECLARE_FUNCTION(DiffRotDiscreteCircle); ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ //declareParameter("Height", 1.0); //parameter "Height" already declared in constructor of base class DeltaFunction - declareParameter("Radius", 1.0, "Circle radius"); + declareParameter( "Radius", 1.0, "Circle radius" ); // Ensure positive values for Height and Radius BoundaryConstraint* HeightConstraint = new BoundaryConstraint( this, "Height", std::numeric_limits::epsilon(), true ); - addConstraint(HeightConstraint); + addConstraint( HeightConstraint ); BoundaryConstraint* RadiusConstraint = new BoundaryConstraint( this, "Radius", std::numeric_limits::epsilon(), true ); - addConstraint(RadiusConstraint); + addConstraint( RadiusConstraint ); declareAttribute( "Q", API::IFunction::Attribute(0.5) ); declareAttribute( "N", API::IFunction::Attribute(3) ); @@ -56,79 +56,80 @@ ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ } double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ - const double R = getParameter("Radius"); - const double Q = getAttribute("Q").asDouble(); - const int N = getAttribute("N").asInt(); + const double R = getParameter( "Radius" ); + const double Q = getAttribute( "Q" ).asDouble(); + const int N = getAttribute( "N" ).asInt(); double aN = 0; - for ( int k=1; k::epsilon(), true); + BoundaryConstraint* IntensityConstraint = new BoundaryConstraint( this, "Intensity", std::numeric_limits< double >::epsilon(), true ); addConstraint(IntensityConstraint); - BoundaryConstraint* RadiusConstraint = new BoundaryConstraint(this, "Radius", std::numeric_limits::epsilon(), true); - addConstraint(RadiusConstraint); + BoundaryConstraint* RadiusConstraint = new BoundaryConstraint( this, "Radius", std::numeric_limits< double >::epsilon(), true ); + addConstraint( RadiusConstraint ); - BoundaryConstraint* DecayConstraint = new BoundaryConstraint(this, "Decay", std::numeric_limits::epsilon(), true); - addConstraint(DecayConstraint); + BoundaryConstraint* DecayConstraint = new BoundaryConstraint( this, "Decay", std::numeric_limits< double >::epsilon(), true ); + addConstraint( DecayConstraint ); } -void InelasticDiffRotDiscreteCircle::function1D(double *out, const double* xValues, const size_t nData) const +void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xValues, const size_t nData ) const { - const double I = getParameter("Intensity"); - const double R = getParameter("Radius"); - const double rate = m_t2e / getParameter("Decay"); // micro-eV or mili-eV - const double Q = getAttribute("Q").asDouble(); - const int N = getAttribute("N").asInt(); - - double sph[N]; - for (int k=1; kgetAttribute(name) by reference, thus the same * object is shared by the composite function and its members. */ -void DiffRotDiscreteCircle::trickleDownAttribute( const std::string& name ) +void DiffRotDiscreteCircle::trickleDownAttribute( const std::string & name ) { - for(size_t iFun=0; iFun < nFunctions(); iFun++) + for ( size_t iFun = 0; iFun < nFunctions(); iFun++ ) { - API::IFunction_sptr fun = getFunction(iFun); + API::IFunction_sptr fun = getFunction( iFun ); if( fun -> hasAttribute( name ) ) - fun -> setAttribute( name, this -> getAttribute(name) ); + fun -> setAttribute( name, this -> getAttribute( name ) ); } } @@ -166,37 +167,26 @@ void DiffRotDiscreteCircle::setAttribute( const std::string& name, const Attribu DiffRotDiscreteCircle::DiffRotDiscreteCircle() { - m_elastic = boost::dynamic_pointer_cast(API::FunctionFactory::Instance().createFunction("ElasticDiffRotDiscreteCircle")); + m_elastic = boost::dynamic_pointer_cast( API::FunctionFactory::Instance().createFunction( "ElasticDiffRotDiscreteCircle" ) ); addFunction( m_elastic ); - m_inelastic = boost::dynamic_pointer_cast(API::FunctionFactory::Instance().createFunction("InelasticDiffRotDiscreteCircle")); + m_inelastic = boost::dynamic_pointer_cast( API::FunctionFactory::Instance().createFunction( "InelasticDiffRotDiscreteCircle" ) ); addFunction( m_inelastic ); - this->setAttributeValue("NumDeriv", true ); + this->setAttributeValue( "NumDeriv", true ); - this->declareAttribute("Q", API::IFunction::Attribute(0.5) ); - this->declareAttribute("N", API::IFunction::Attribute(3) ); + this->declareAttribute( "Q", API::IFunction::Attribute( 0.5 ) ); + this->declareAttribute( "N", API::IFunction::Attribute( 3 ) ); //Set the aliases - this->setAlias("f1.Intensity","Intensity"); - this->setAlias("f1.Radius","Radius"); - this->setAlias("f1.Decay","Decay"); + this->setAlias( "f1.Intensity", "Intensity" ); + this->setAlias( "f1.Radius", "Radius" ); + this->setAlias( "f1.Decay", "Decay" ); //Set the ties between Elastic and Inelastic parameters - this->addDefaultTies("f0.Height=f1.Intensity,f0.Radius=f1.Radius"); + this->addDefaultTies( "f0.Height=f1.Intensity,f0.Radius=f1.Radius" ); this->applyTies(); } - - - - - - - - - - - } // namespace CurveFitting } // namespace Mantid From a5889007a57b9c8b7d8b1186192d67ba0ca0ff33 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 14:21:18 -0500 Subject: [PATCH 064/403] Refs #8508 Inserted WIKI page in source docstring --- .../src/DiffRotDiscreteCircle.cpp | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 38680cf27fba..a8f777afd164 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -1,20 +1,48 @@ /*WIKI* -This fitting function models the dynamics structure factor of a particle undergoing -discrete jumps on N-sites evenly distributed in a circle. The particle can only -jump to neighboring sites. This is the most common type of discrete rotational diffusion -in a circle. +== Summary == + +This fitting function models the dynamics structure factor of a particle undergoing discrete jumps on N-sites +evenly distributed in a circle. The particle can only jump to neighboring sites. +This is the most common type of discrete rotational diffusion in a circle. The fitting parameters are the inverse of the transition rate, \tau and the circle radius r - S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} - A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) + A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) \tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N}) -If the energy units of energy are micro-eV, then tau is expressed in nano-seconds. If E-units are mili-eV then -tau is expressed in pico-seconds. +If the energy units are \mueV, then \tau is expressed in nano-seconds. If E-units are meV then +\tau is expressed in pico-seconds. + +== Properties == + +{| border="1" cellpadding="5" cellspacing="0" +!Order +!Name +!Default +!Description +|- +|1 +|Intensity +|0.1 +|Intensity of the peak +|- +|2 +|Radius +|1.0 +|Circle radius +|- +|3 +|Decay +|100.0 +|inverse of the transition rate (ps if energy in meV; ns if energy in \mueV) +|} + + +[[Category:Fit_functions]] *WIKI*/ //---------------------------------------------------------------------- From 8cf4875a34a0961a37de0337619408b4c0e0dc01 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 14:24:59 -0500 Subject: [PATCH 065/403] Refs #8508 Include limits header for numeric_limits --- Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index a8f777afd164..3252f9a4f2e8 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -48,6 +48,7 @@ If the energy units are \mueV, then \tau is expressed //---------------------------------------------------------------------- // Includes //---------------------------------------------------------------------- +#include #include "MantidCurveFitting/DiffRotDiscreteCircle.h" #include "MantidCurveFitting/BoundaryConstraint.h" #include "MantidAPI/FunctionFactory.h" From 47014c8e8db1fc8fcb7c3e107bd83e81c0e60a11 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 14:46:44 -0500 Subject: [PATCH 066/403] Refs #8508 Avoid declaring statically sized arrays Windows compiler complains when declaring a statically sized array while passing in a size variable which is evaluated at run-time --- .../CurveFitting/src/DiffRotDiscreteCircle.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 3252f9a4f2e8..f49f465016b2 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -128,14 +128,17 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal const double Q = getAttribute( "Q" ).asDouble(); const int N = getAttribute( "N" ).asInt(); - double sph[ N ]; + + //double sph[ N ]; + double* sph = new double[ N ]; for ( int k = 1; k < N; k++ ) { double x = 2 * Q * R * sin( M_PI * k / N ); sph[ k ] = sin( x ) / x; // spherical Besell function of order zero 'j0' is sin(x)/x } - double ratel[ N ]; + //double ratel[ N ]; + double* ratel = new double[ N ]; for ( int l = 1; l < ( N - 1 ); l++) { ratel[ l ] = rate * 4 * pow( sin( M_PI * l / N ), 2 ); // notice that 0 < l/N < 1 @@ -160,6 +163,10 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal } out[ i ] = I * S / M_PI; } + + // some cleaning + delete [] ratel; + delete [] sph; } /* Propagate the attribute to its member functions. From 8ca3319cb0c42ca0b88142ef85c974c6ea064fcd Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 14:48:31 -0500 Subject: [PATCH 067/403] Refs #8508 declaring a statically sized array v2 I had another one of those :( --- .../Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index f49f465016b2..2d1d6471cb4d 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -129,7 +129,6 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal const int N = getAttribute( "N" ).asInt(); - //double sph[ N ]; double* sph = new double[ N ]; for ( int k = 1; k < N; k++ ) { @@ -137,7 +136,6 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal sph[ k ] = sin( x ) / x; // spherical Besell function of order zero 'j0' is sin(x)/x } - //double ratel[ N ]; double* ratel = new double[ N ]; for ( int l = 1; l < ( N - 1 ); l++) { From bd821fd40f198786562fcdad3c29ab628e614055 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 15:21:09 -0500 Subject: [PATCH 068/403] Refs #8508 Changed the WIKI docstring --- .../CurveFitting/src/DiffRotDiscreteCircle.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 2d1d6471cb4d..5a752d9ebcdd 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -27,17 +27,17 @@ If the energy units are \mueV, then \tau is expressed |- |1 |Intensity -|0.1 -|Intensity of the peak +|1.0 +|Intensity of the peak [arbitrary units] |- |2 |Radius |1.0 -|Circle radius +|Circle radius [Angstroms] |- |3 |Decay -|100.0 +|1.0 |inverse of the transition rate (ps if energy in meV; ns if energy in \mueV) |} @@ -70,7 +70,7 @@ DECLARE_FUNCTION(DiffRotDiscreteCircle); ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ //declareParameter("Height", 1.0); //parameter "Height" already declared in constructor of base class DeltaFunction - declareParameter( "Radius", 1.0, "Circle radius" ); + declareParameter( "Radius", 1.0, "Circle radius [Angstroms] " ); // Ensure positive values for Height and Radius BoundaryConstraint* HeightConstraint = new BoundaryConstraint( this, "Height", std::numeric_limits::epsilon(), true ); @@ -100,9 +100,9 @@ double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ InelasticDiffRotDiscreteCircle::InelasticDiffRotDiscreteCircle() : m_t2e(4.136) { - declareParameter( "Intensity",1.0, "scaling factor" ); - declareParameter( "Radius", 1.0, "Circle radius" ); - declareParameter( "Decay", 1.0, "Inverse of transition rate, in nanoseconds or picoseconds" ); + declareParameter( "Intensity",1.0, "scaling factor [arbitrary units]" ); + declareParameter( "Radius", 1.0, "Circle radius [Angstroms]" ); + declareParameter( "Decay", 1.0, "Inverse of transition rate, in nanoseconds if energy in micro-ev, or picoseconds if energy in mili-eV" ); declareAttribute( "Q", API::IFunction::Attribute( 0.5 ) ); declareAttribute( "N", API::IFunction::Attribute( 3 ) ); From d7c67d8c1efaf2614a8ad91da4e76c789f114cd6 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 4 Dec 2013 16:39:33 -0500 Subject: [PATCH 069/403] Refs #8508 Substitute array with vector --- .../src/DiffRotDiscreteCircle.cpp | 53 ++--- .../test/DiffRotDiscreteCircleTest.h | 198 +++++++++--------- 2 files changed, 122 insertions(+), 129 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 5a752d9ebcdd..b948ce438431 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -55,10 +55,6 @@ If the energy units are \mueV, then \tau is expressed #include #include "MantidAPI/ParameterTie.h" -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - namespace Mantid { namespace CurveFitting @@ -91,8 +87,8 @@ double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ double aN = 0; for ( int k = 1; k < N; k++ ) { - double x = 2 * Q * R * sin( M_PI * k / N ); - aN += sin( x ) / x; // spherical Besell function of order zero j0==sin(x)/x + double x = 2 * Q * R * sin( M_PI * k / N ); + aN += sin( x ) / x; // spherical Besell function of order zero j0==sin(x)/x } aN += 1; // limit for j0 when k==N, or x==0 return aN / N; @@ -129,42 +125,39 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal const int N = getAttribute( "N" ).asInt(); - double* sph = new double[ N ]; + std::vector sph( N ); for ( int k = 1; k < N; k++ ) { - double x = 2 * Q * R * sin( M_PI * k / N ); - sph[ k ] = sin( x ) / x; // spherical Besell function of order zero 'j0' is sin(x)/x + double x = 2 * Q * R * sin( M_PI * k / N ); + sph[ k ] = sin( x ) / x; // spherical Besell function of order zero 'j0' is sin(x)/x } - double* ratel = new double[ N ]; + std::vector ratel( N ); for ( int l = 1; l < ( N - 1 ); l++) { - ratel[ l ] = rate * 4 * pow( sin( M_PI * l / N ), 2 ); // notice that 0 < l/N < 1 + ratel[ l ] = rate * 4 * pow( sin( M_PI * l / N ), 2 ); // notice that 0 < l/N < 1 } for ( size_t i = 0; i < nData; i++ ) { - double w = xValues[ i ]; - double S = 0.0; - for ( int l = 1; l < ( N - 1 ); l++ ) - { - double lorentzian = ratel[ l ] / ( ratel[ l ] * ratel[ l ] + w * w ); - double al = 0.0; - for ( int k = 1; k < N; k++ ) - { - double y = 2 * M_PI * l * k / N; - al += cos( y ) * sph[ k ]; - } - al += 1; // limit for j0 when k==N, or x==0 - al /= N; - S += al * lorentzian; - } - out[ i ] = I * S / M_PI; + double w = xValues[ i ]; + double S = 0.0; + for ( int l = 1; l < ( N - 1 ); l++ ) + { + double lorentzian = ratel[ l ] / ( ratel[ l ] * ratel[ l ] + w * w ); + double al = 0.0; + for ( int k = 1; k < N; k++ ) + { + double y = 2 * M_PI * l * k / N; + al += cos( y ) * sph[ k ]; + } + al += 1; // limit for j0 when k==N, or x==0 + al /= N; + S += al * lorentzian; + } + out[ i ] = I * S / M_PI; } - // some cleaning - delete [] ratel; - delete [] sph; } /* Propagate the attribute to its member functions. diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h index 4e6103140d01..ffc9033161bf 100644 --- a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -77,15 +77,15 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite /// Fit the convolution of the inelastic part with a Gaussian resolution function void testDiffRotDiscreteCircleInelastic() { - /* Note: it turns out that parameters Intensity and Radius are highly covariant, so that more than one minimum exists. - * Thus, I tied parameter Radius. This is OK since one usually knows the radius of the circle of the jumping diffusion - */ + /* Note: it turns out that parameters Intensity and Radius are highly covariant, so that more than one minimum exists. + * Thus, I tied parameter Radius. This is OK since one usually knows the radius of the circle of the jumping diffusion + */ - // initialize the fitting function in a Fit algorithm - // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units - std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1.0,PeakCentre=0.0,Sigma=20.0,ties=(Height=1.0,PeakCentre=0.0,Sigma=20.0);name=InelasticDiffRotDiscreteCircle,N=3,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567)"; + // initialize the fitting function in a Fit algorithm + // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units + std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1.0,PeakCentre=0.0,Sigma=20.0,ties=(Height=1.0,PeakCentre=0.0,Sigma=20.0);name=InelasticDiffRotDiscreteCircle,N=3,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567)"; - // Initialize the fit function in the Fit algorithm + // Initialize the fit function in the Fit algorithm Mantid::CurveFitting::Fit fitalg; TS_ASSERT_THROWS_NOTHING( fitalg.initialize() ); TS_ASSERT( fitalg.isInitialized() ); @@ -131,59 +131,59 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite /// check ties between elastic and inelastic parts void testDiffRotDiscreteCircleTies() { - const double I = 2.9; - const double R = 2.3; - const double tao = 0.45; - const double Q = 0.7; - const int N = 4; - Mantid::CurveFitting::DiffRotDiscreteCircle func; - func.setParameter( "f1.Intensity", I ); - func.setParameter( "f1.Radius" , R ); - func.setParameter( "f1.Decay", tao ); - func.setAttributeValue( "Q" , Q ); - func.setAttributeValue( "N", N ); - - // check values where correctly initialized - auto ids = boost::dynamic_pointer_cast( func.getFunction(1) ); - TS_ASSERT_EQUALS( ids->getParameter("Intensity"), I ); - TS_ASSERT_EQUALS( ids->getParameter("Radius"), R ); - TS_ASSERT_EQUALS( ids->getParameter("Decay"), tao ); - TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); - TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); - - //check the ties were applied correctly - func.applyTies(); //elastic parameters are tied to inelastic parameters - auto eds = boost::dynamic_pointer_cast( func.getFunction(0) ); - TS_ASSERT_EQUALS( eds->getParameter("Height") , I ); - TS_ASSERT_EQUALS( eds->getParameter("Radius") , R ); - TS_ASSERT_EQUALS( eds->getAttribute("Q").asDouble(), Q ); + const double I = 2.9; + const double R = 2.3; + const double tao = 0.45; + const double Q = 0.7; + const int N = 4; + Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.setParameter( "f1.Intensity", I ); + func.setParameter( "f1.Radius" , R ); + func.setParameter( "f1.Decay", tao ); + func.setAttributeValue( "Q" , Q ); + func.setAttributeValue( "N", N ); + + // check values where correctly initialized + auto ids = boost::dynamic_pointer_cast( func.getFunction(1) ); + TS_ASSERT_EQUALS( ids->getParameter("Intensity"), I ); + TS_ASSERT_EQUALS( ids->getParameter("Radius"), R ); + TS_ASSERT_EQUALS( ids->getParameter("Decay"), tao ); + TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); + TS_ASSERT_EQUALS( ids->getAttribute("Q").asDouble(), Q ); + + //check the ties were applied correctly + func.applyTies(); //elastic parameters are tied to inelastic parameters + auto eds = boost::dynamic_pointer_cast( func.getFunction(0) ); + TS_ASSERT_EQUALS( eds->getParameter("Height") , I ); + TS_ASSERT_EQUALS( eds->getParameter("Radius") , R ); + TS_ASSERT_EQUALS( eds->getAttribute("Q").asDouble(), Q ); } /// check aliases in the composite function void testDiffRotDiscreteCircleAliases() { - const double I = 2.9; - const double R = 2.3; - const double tao = 0.45; - - // This should set parameters of the inelastic part - Mantid::CurveFitting::DiffRotDiscreteCircle func; - func.setParameter( "Intensity", I ); - func.setParameter( "Radius", R ); - func.setParameter( "Decay", tao ); - - // check the parameter of the inelastic part - auto ifunc = boost::dynamic_pointer_cast( func.getFunction(1) ); - TS_ASSERT_EQUALS( ifunc -> getParameter( "Intensity" ), I ); - TS_ASSERT_EQUALS( ifunc -> getParameter( "Radius" ), R ); - TS_ASSERT_EQUALS( ifunc -> getParameter( "Decay" ), tao ); - - // check the parameters of the elastic part - func.applyTies(); //elastic parameters are tied to inelastic parameters - auto efunc = boost::dynamic_pointer_cast( func.getFunction(0) ); - TS_ASSERT_EQUALS( efunc -> getParameter( "Height" ) , I ); - TS_ASSERT_EQUALS( efunc -> getParameter( "Radius" ) , R ); + const double I = 2.9; + const double R = 2.3; + const double tao = 0.45; + + // This should set parameters of the inelastic part + Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.setParameter( "Intensity", I ); + func.setParameter( "Radius", R ); + func.setParameter( "Decay", tao ); + + // check the parameter of the inelastic part + auto ifunc = boost::dynamic_pointer_cast( func.getFunction(1) ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Intensity" ), I ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Radius" ), R ); + TS_ASSERT_EQUALS( ifunc -> getParameter( "Decay" ), tao ); + + // check the parameters of the elastic part + func.applyTies(); //elastic parameters are tied to inelastic parameters + auto efunc = boost::dynamic_pointer_cast( func.getFunction(0) ); + TS_ASSERT_EQUALS( efunc -> getParameter( "Height" ) , I ); + TS_ASSERT_EQUALS( efunc -> getParameter( "Radius" ) , R ); } // testDiffRotDiscreteCircleAliases @@ -191,11 +191,11 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite /// Fit the convolution of the jumping diffusion with a Gaussian resolution function void testDiffRotDiscreteCircle() { - // initialize the fitting function in a Fit algorithm - // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units - std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1,PeakCentre=0,Sigma=20,ties=(Height=1,PeakCentre=0,Sigma=20);(name=DiffRotDiscreteCircle,N=3,NumDeriv=true,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567))"; + // initialize the fitting function in a Fit algorithm + // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units + std::string funtion_string = "(composite=Convolution,FixResolution=true,NumDeriv=true;name=Gaussian,Height=1,PeakCentre=0,Sigma=20,ties=(Height=1,PeakCentre=0,Sigma=20);(name=DiffRotDiscreteCircle,N=3,NumDeriv=true,Q=0.5,Intensity=47.014,Radius=1.567,Decay=7.567))"; - // Initialize the fit function in the Fit algorithm + // Initialize the fit function in the Fit algorithm Mantid::CurveFitting::Fit fitalg; TS_ASSERT_THROWS_NOTHING( fitalg.initialize() ); TS_ASSERT( fitalg.isInitialized() ); @@ -227,7 +227,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite TS_ASSERT_DELTA( fitalg_resolution -> getParameter( "Sigma" ), 20.0, 20.0* 0.001 ); // allow for a small percent variation //std::cout << "\nPeakCentre = " << fitalg_resolution->getParameter("PeakCentre") << " Height= " << fitalg_resolution->getParameter("Height") << " Sigma=" << fitalg_resolution->getParameter("Sigma") << "\n"; // only for debugging purposes - // check the parameters of the inelastic part + // check the parameters of the DiffRotDiscreteCircle Mantid::API::IFunction_sptr fitalg_structure_factor = fitalg_conv->getFunction( 1 ); TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Intensity" ), 47.014, 47.014 * 0.05 ); // allow for a small percent variation TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Radius" ), 1.567, 1.567 * 0.05 ); // allow for a small percent variation @@ -243,9 +243,9 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite /// returns a real value from a uniform distribution double random_value(const double & a, const double & b) { - boost::mt19937 rng; - boost::uniform_real distribution( a, b ); - return distribution(rng); + boost::mt19937 rng; + boost::uniform_real distribution( a, b ); + return distribution(rng); } @@ -255,26 +255,26 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite Mantid::API::FunctionValues dataYvalues( xView ); function_pointer -> function( xView, dataYvalues ); // evaluate the function const size_t M = xView.size(); - // create temporaray workspace. - auto temp_ws = WorkspaceCreationHelper::Create2DWorkspace(1, static_cast( M ) ); - for( size_t i = 0; i < M; i++ ) - { - temp_ws -> dataX( 0 )[ i ] = xView[ i ]; - temp_ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); - temp_ws -> dataE( 0 )[ i ] = 0.1 * dataYvalues.getCalculated( i ); // assume the error is 10% of the actual value - } + // create temporaray workspace. + auto temp_ws = WorkspaceCreationHelper::Create2DWorkspace(1, static_cast( M ) ); + for( size_t i = 0; i < M; i++ ) + { + temp_ws -> dataX( 0 )[ i ] = xView[ i ]; + temp_ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); + temp_ws -> dataE( 0 )[ i ] = 0.1 * dataYvalues.getCalculated( i ); // assume the error is 10% of the actual value + } const double dw = xView[1]-xView[0]; // bin width - temp_ws -> dataX( 0 )[ M ] = temp_ws -> dataX( 0 )[ M - 1 ] + dw; - // save workspace to file. - auto save = Mantid::API::AlgorithmFactory::Instance().create( "SaveNexus", 1 ); - if ( !save ) throw std::runtime_error( "Algorithm not created" ); - save -> initialize(); - save -> setProperty( "Filename", filename ); - save -> setProperty( "InputWorkspace", temp_ws ); - save->execute(); - - // some cleaning - Mantid::API::AnalysisDataService::Instance().remove( temp_ws -> getName() ); + temp_ws -> dataX( 0 )[ M ] = temp_ws -> dataX( 0 )[ M - 1 ] + dw; + // save workspace to file. + auto save = Mantid::API::AlgorithmFactory::Instance().create( "SaveNexus", 1 ); + if ( !save ) throw std::runtime_error( "Algorithm not created" ); + save -> initialize(); + save -> setProperty( "Filename", filename ); + save -> setProperty( "InputWorkspace", temp_ws ); + save->execute(); + + // some cleaning + Mantid::API::AnalysisDataService::Instance().remove( temp_ws -> getName() ); } @@ -292,28 +292,28 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite // create a data workspace using a Fit algorithm Mantid::DataObjects::Workspace2D_sptr generateWorkspace( Mantid::CurveFitting::Fit & fitalg ) { - // initialize some frequency values centered around zero. Will work as dataX - const size_t M = 1001; - double dataX[ M ]; - const double dw = 0.4; // typical bin width for BASIS@ORNL beamline, in micro-seconds - for( size_t i = 0; i < M; i++ ) dataX[i] = (static_cast(i) - M/2 ) * dw; - - // Evaluate the fitting function. Will work as dataY - Mantid::API::FunctionDomain1DView dataXview( &dataX[0], M ); - Mantid::API::FunctionValues dataYvalues( dataXview ); + // initialize some frequency values centered around zero. Will work as dataX + const size_t M = 1001; + double dataX[ M ]; + const double dw = 0.4; // typical bin width for BASIS@ORNL beamline, in micro-seconds + for( size_t i = 0; i < M; i++ ) dataX[i] = (static_cast(i) - M/2 ) * dw; + + // Evaluate the fitting function. Will work as dataY + Mantid::API::FunctionDomain1DView dataXview( &dataX[0], M ); + Mantid::API::FunctionValues dataYvalues( dataXview ); Mantid::API::IFunction_sptr fitalg_function = fitalg.getProperty( "Function" ); fitalg_function -> function( dataXview, dataYvalues ); // create the workspace - auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, M ); - double fractional_error = 0.01; // error taken as a percent of the signal - for( size_t i = 0; i < M; i++ ) - { - ws -> dataX( 0 )[ i ] = dataX[ i ] - dw/2; // bin boundaries are shifted by half the bind width - ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); - ws -> dataE( 0 )[ i ] = fractional_error * dataYvalues.getCalculated( i ); // assume the error is a small percent of the actual value - } - ws -> dataX( 0 )[ M ] = dataX[ M - 1 ] + dw/2; // recall number of bin boundaries is 1 + #bins + auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, M ); + double fractional_error = 0.01; // error taken as a percent of the signal + for( size_t i = 0; i < M; i++ ) + { + ws -> dataX( 0 )[ i ] = dataX[ i ] - dw/2; // bin boundaries are shifted by half the bind width + ws -> dataY( 0 )[ i ] = dataYvalues.getCalculated( i ); + ws -> dataE( 0 )[ i ] = fractional_error * dataYvalues.getCalculated( i ); // assume the error is a small percent of the actual value + } + ws -> dataX( 0 )[ M ] = dataX[ M - 1 ] + dw/2; // recall number of bin boundaries is 1 + #bins // return now the workspace return ws; From 2f3f48fbd0b58cb86647230711543bc6786605d3 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 10:10:07 +0000 Subject: [PATCH 070/403] Refs #8550. VectorColumn: sizeOfData() method. --- .../inc/MantidDataObjects/VectorColumn.h | 11 +++++++++-- .../Framework/DataObjects/test/VectorColumnTest.h | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 0aad690735b0..4b1575b72c21 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -123,10 +123,17 @@ namespace DataObjects return false; } - /// Overall memory size taken by the column + /// Overall memory size taken by the column (bytes) virtual long int sizeOfData() const { - // TODO: implement + long int size(0); + + for ( auto elemIt = m_data.begin(); elemIt != m_data.end(); ++elemIt ) + size += elemIt->size() * sizeof(Type); + { + } + + return size; } /// Create another copy of the column diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h index 1b4b2acfb208..3a17b5e519a5 100644 --- a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -91,6 +91,19 @@ class VectorColumnTest : public CxxTest::TestSuite TS_ASSERT_THROWS_NOTHING( col.print(2, s3) ); TS_ASSERT( s3.str().empty() ); } + + void test_sizeOfData() + { + VectorColumnTestHelper col; + + col.resize(3); + + col.read(0, "1,2,3"); + col.read(1, "3,4,5"); + col.read(2, "7,8,9,10"); + + TS_ASSERT_EQUALS( col.sizeOfData(), 10 * sizeof(int) ); + } }; From d3ca69f3afe16f7509191832fb95ebb78be16ee3 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 10:28:51 +0000 Subject: [PATCH 071/403] Refs #8550. VectorColumn: implementation of the remaining methods. Plus registration macro and some additional tests. --- .../inc/MantidDataObjects/VectorColumn.h | 17 ++++++++++++++--- .../Framework/DataObjects/src/VectorColumn.cpp | 5 +++++ .../DataObjects/test/VectorColumnTest.h | 3 +++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 4b1575b72c21..6e3813303d69 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -139,18 +139,25 @@ namespace DataObjects /// Create another copy of the column virtual VectorColumn* clone() const { - // TODO: implement + VectorColumn* newColumn = new VectorColumn(); + newColumn->m_data = m_data; + newColumn->setName(m_name); + newColumn->setPlotType(m_plotType); + return newColumn; } /// Cast to double virtual double toDouble(size_t i) const { + UNUSED_ARG(i); throw std::runtime_error("VectorColumn is not convertible to double."); } /// Assign from double virtual void fromDouble(size_t i, double value) { + UNUSED_ARG(i); + UNUSED_ARG(value); throw std::runtime_error("VectorColumn is not assignable from double."); } @@ -164,12 +171,14 @@ namespace DataObjects /// Inserts an item. virtual void insert(size_t index) { - // TODO: implement + // Insert empty vector at the given position + m_data.insert( m_data.begin() + index, std::vector() ); } /// Removes an item. virtual void remove(size_t index) { + m_data.erase(m_data.begin() + index); } /// Pointer to a data element @@ -197,6 +206,8 @@ namespace DataObjects } // namespace Mantid #define DECLARE_VECTORCOLUMN(Type,TypeName) \ - template<> std::string VectorColumn::typeName() { return #TypeName; }; + template<> std::string VectorColumn::typeName() { return #TypeName; }; \ + Kernel::RegistrationHelper register_column_##TypeName( \ + ( API::ColumnFactory::Instance().subscribe< VectorColumn >(#TypeName), 0) ); \ #endif /* MANTID_DATAOBJECTS_VECTORCOLUMN_H_ */ diff --git a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp index 6379392559d8..8ef9dd34d6ec 100644 --- a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp +++ b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp @@ -1,9 +1,14 @@ +#include "MantidAPI/ColumnFactory.h" #include "MantidDataObjects/VectorColumn.h" namespace Mantid { namespace DataObjects { + // Please feel free to declare new types as you need them. Syntax is: + // DECLARE_VECTORCOLUMN(type, name-of-the-type); + DECLARE_VECTORCOLUMN(int, vector_int); + DECLARE_VECTORCOLUMN(double, vector_double); } // namespace DataObjects } // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h index 3a17b5e519a5..43aa7a42850a 100644 --- a/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h +++ b/Code/Mantid/Framework/DataObjects/test/VectorColumnTest.h @@ -28,6 +28,9 @@ class VectorColumnTest : public CxxTest::TestSuite { VectorColumn col; TS_ASSERT_EQUALS( col.type(), "vector_int"); + + VectorColumn col2; + TS_ASSERT_EQUALS( col2.type(), "vector_double"); } void test_read() From 6c88904377ada5be67b481d071481095a0db0c33 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Thu, 5 Dec 2013 10:37:36 +0000 Subject: [PATCH 072/403] Remove TubeCalibDemoMerlin_Adjustable.py re #8263 This example is no longer needed. It demonstrated a withdrawn feature and was the example that no longer worked. Signed-off-by: Karl Palmen --- .../TubeCalibDemoMerlin_Adjustable.py | 101 ------------------ 1 file changed, 101 deletions(-) delete mode 100644 Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py diff --git a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py deleted file mode 100644 index a18ae2d0ff67..000000000000 --- a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMerlin_Adjustable.py +++ /dev/null @@ -1,101 +0,0 @@ -# -# TUBE CALIBRATION DEMONSTRATION PROGRAM FOR MERLIN -# -# This is example that allows some calibration slit peaks to be adjusted. -# First execute the part from thwe beginning to the end of the CalibrateMerlin function -# then the later parts. -# -# Here we run the calibration of MERLIN or selected part of MERLIN -# (excluding short tubes of door 3) -# This calibration is organised by the function CalibrateMerlin, -# which takes a string consisting of the run number of a calibration run number as argument. -# The workspace with calibrated instrument is saved to a Nexus file -# -import tube -from tube_calib_fit_params import * # To handle fit parameters -import os -import numpy - -def CalibrateMerlin( RunNumber, UsePeakFile=False ): -# Run number must include any leading zeros that appear in the file name of the run. - - # == Set parameters for calibration == - - # File details - filename = 'MER'+str(RunNumber) # Name of calibration run - rangeLower = 3000 # Integrate counts in each spectra from rangeLower to rangeUpper - rangeUpper = 20000 # - - # Set parameters for ideal tube. - Left = 2.0 # Where the left end of tube should be in pixels (target for AP) - Centre = 512.5 # Where the centre of the tube should be in pixels (target for CP) - Right = 1023.0 # Where the right of the tube should be in pxels (target for BP) - ActiveLength = 2.9 # Active length of tube in Metres - - # Set initial parameters for peak finding - ExpectedHeight = 1000.0 # Expected Height of Peaks (initial value of fit parameter) - ExpectedWidth = 32.0 # Expected width of centre peak (initial value of fit parameter) - ExpectedPositions = [35.0, 512.0, 989.0] # Expected positions of the edges and peak (initial values of fit parameters) - - # Set what we want to calibrate (e.g whole intrument or one door ) - CalibratedComponent = 'MERLIN/door8' # Calibrate whole instrument - - # Get calibration raw file and integrate it - rawCalibInstWS = LoadRaw(filename) #'raw' in 'rawCalibInstWS' means unintegrated. - print "Integrating Workspace" - CalibInstWS = Integration( rawCalibInstWS, RangeLower=rangeLower, RangeUpper=rangeUpper ) - DeleteWorkspace(rawCalibInstWS) - print "Created workspace (CalibInstWS) with integrated data from run and instrument to calibrate" - - # == Create Objects needed for calibration == - - # Get ideal tube - # the known positions are given in pixels inside the tubes and transformed to provide the positions - # with the center of the tube as the origin - knownPositions = ActiveLength*(numpy.array([ Left, Right, Centre])/1024 - 0.5) - funcForm = [1,1,1] - - print "Created objects needed for calibration." - - # == Get the calibration and put results into calibration table == - # also put peaks into PeakFile - saveDirectory = config['defaultsave.directory'] - peakFileName = "TubeCalibDemoMerlin_Peaks.txt" - - # pass more parameters to tube.calibrate by name - extra_options = dict() - extra_options['excludeShortTubes']=ActiveLength - extra_options['outputPeak']=True - if(not UsePeakFile): - # Get fitting parameters - fitPar = TubeCalibFitParams( ExpectedPositions, ExpectedHeight, ExpectedWidth ) - fitPar.setAutomatic(True) - extra_options['fitPar'] = fitPar - - - calibrationTable, peakTable = tube.calibrate(CalibInstWS, CalibratedComponent, knownPositions, funcForm, - **extra_options) - - peakFileName = "TubeCalibDemoMerlin_Peaks.txt" - if UsePeakFile: - tube.savePeak(peakTable, peakFileName) - print " Put slit peaks into file",peakFileName, "in save directory",saveDirectory,"." - - print "Got calibration (new positions of detectors)" - - # == Apply the Calibation == - ApplyCalibration( Workspace=CalibInstWS, PositionTable=calibrationTable) - print "Applied calibration" - - # == Save workspace == - SaveNexusProcessed( CalibInstWS, 'TubeCalibDemoMerlinResult.nxs',"Result of Running TubeCalibDemoMerlin_Adjustable.py") - print "saved calibrated workspace (CalibInstWS) into Nexus file TubeCalibDemoMerlinResult.nxs in save directory",saveDirectory,"." - - # ==== End of CalibrateMerlin() ==== - # INITIALLY EXECUTE THE CODE FROM THE BEGINNING TO HERE, THEN EACH OF THE TWO CALLS BELOW IN ORDER SEPARATELY - -# Run this one first -CalibrateMerlin( 12024 ) - -#Then edit the'TubeCalibDemoMerlin_Peaks.txt' file, then run -CalibrateMerlin( 12024, True) From 6cbe39caaef041cac6b4dba864833a8594f0aa20 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 12:55:33 +0000 Subject: [PATCH 073/403] Refs #8550. VectorColumn: ability to use it from Python. Plus tests for that. --- .../DataObjects/src/VectorColumn.cpp | 7 ++-- .../api/src/Exports/ITableWorkspace.cpp | 36 ++++++++++++++++++- .../python/mantid/api/ITableWorkspaceTest.py | 13 +++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp index 8ef9dd34d6ec..2a7f77657d13 100644 --- a/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp +++ b/Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp @@ -8,7 +8,10 @@ namespace DataObjects // Please feel free to declare new types as you need them. Syntax is: // DECLARE_VECTORCOLUMN(type, name-of-the-type); - DECLARE_VECTORCOLUMN(int, vector_int); - DECLARE_VECTORCOLUMN(double, vector_double); + // However, when you do that, please don't forget to add new type to the ITableWorkspace.cpp + // so that it can be converted to Python list + + DECLARE_VECTORCOLUMN(int, vector_int) + DECLARE_VECTORCOLUMN(double, vector_double) } // namespace DataObjects } // namespace Mantid diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp index 1849c0dc66ca..6142da4c71d7 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp @@ -2,6 +2,9 @@ #include "MantidAPI/Column.h" #include "MantidAPI/TableRow.h" #include "MantidAPI/WorkspaceProperty.h" +#include "MantidPythonInterface/kernel/Converters/NDArrayToVector.h" +#include "MantidPythonInterface/kernel/Converters/PySequenceToVector.h" +#include "MantidPythonInterface/kernel/Converters/CloneToNumpy.h" #include "MantidPythonInterface/kernel/SharedPtrToPythonMacro.h" #include "MantidPythonInterface/kernel/Registry/RegisterSingleValueHandler.h" #include "MantidPythonInterface/kernel/PropertyWithValue.h" @@ -14,6 +17,11 @@ #include #include +// See http://docs.scipy.org/doc/numpy/reference/c-api.array.html#PY_ARRAY_UNIQUE_SYMBOL +#define PY_ARRAY_UNIQUE_SYMBOL KERNEL_ARRAY_API +#define NO_IMPORT_ARRAY +#include + using Mantid::API::ITableWorkspace; using Mantid::API::ITableWorkspace_sptr; using Mantid::API::TableRow; @@ -26,6 +34,7 @@ using namespace boost::python; namespace { namespace bpl = boost::python; + namespace Converters = Mantid::PythonInterface::Converters; /// Boost macro for "looping" over builtin types #define BUILTIN_TYPES \ @@ -36,6 +45,10 @@ namespace BOOST_PP_TUPLE_TO_LIST( \ 1, (Mantid::Kernel::V3D) \ ) + #define ARRAY_TYPES \ + BOOST_PP_TUPLE_TO_LIST( \ + 2, (std::vector, std::vector ) \ + ) /** * Get out the Python value from a specific cell of the supplied column. This is meant to @@ -64,12 +77,18 @@ namespace if(!entry) throw std::invalid_argument("Cannot find converter from C++ type.");\ result = entry->to_python((const void *)&column->cell(row));\ } + #define GET_ARRAY(R, _, T) \ + else if(typeID == typeid(T))\ + {\ + result = Converters::Clone::apply::create1D( column->cell(row) ); \ + } // -- Use the boost preprocessor to generate a list of else if clause to cut out copy // and pasted code. PyObject *result(NULL); if(false){} // So that it always falls through to the list checking BOOST_PP_LIST_FOR_EACH(GET_BUILTIN, _ , BUILTIN_TYPES) + BOOST_PP_LIST_FOR_EACH(GET_ARRAY, _ , ARRAY_TYPES) BOOST_PP_LIST_FOR_EACH(GET_USER, _ , USER_TYPES) else { @@ -92,11 +111,25 @@ namespace return; } -#define SET_CELL(R, _, T) \ + #define SET_CELL(R, _, T) \ else if(typeID == typeid(T)) \ {\ column->cell(row) = bpl::extract(value)();\ } + #define SET_VECTOR_CELL(R, _, T) \ + else if(typeID == typeid(T)) \ + {\ + if( ! PyArray_Check( value.ptr() ) ) \ + { \ + column->cell(row) = Converters::PySequenceToVector(value)(); \ + } \ + else \ + { \ + column->cell(row) = Converters::NDArrayToVector(value)();\ + } \ + } + + // -- Use the boost preprocessor to generate a list of else if clause to cut out copy // and pasted code. // I think cppcheck is getting confused by the define @@ -104,6 +137,7 @@ namespace const std::type_info & typeID = column->get_type_info(); if(false){} // So that it always falls through to the list checking BOOST_PP_LIST_FOR_EACH(SET_CELL, _ , BUILTIN_TYPES) + BOOST_PP_LIST_FOR_EACH(SET_VECTOR_CELL, _ , ARRAY_TYPES) BOOST_PP_LIST_FOR_EACH(SET_CELL, _ , USER_TYPES) else { diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/ITableWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/ITableWorkspaceTest.py index fbb13778cffa..c2d94fcb267d 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/ITableWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/ITableWorkspaceTest.py @@ -2,6 +2,7 @@ from testhelpers import run_algorithm from mantid.kernel import std_vector_str from mantid.api import WorkspaceFactory +import numpy class ITableWorkspaceTest(unittest.TestCase): @@ -108,6 +109,18 @@ def test_set_and_extract_boolean_columns(self): self.assertTrue(table.cell(0, 0)) self.assertFalse(table.cell(1, 0)) + + def test_set_and_extract_vector_columns(self): + table = WorkspaceFactory.createTable() + table.addColumn(type='vector_int', name='values') + + # Settings from general Python list + table.addRow([ [1,2,3,4,5] ]) + # Setting from numpy array + table.addRow([ numpy.array([6,7,8,9,10]) ]) + + self.assertTrue( numpy.array_equal( table.cell(0,0), numpy.array([1,2,3,4,5]) ) ) + self.assertTrue( numpy.array_equal( table.cell(1,0), numpy.array([6,7,8,9,10]) ) ) if __name__ == '__main__': unittest.main() From f9c77d15f7c4175621fcccf92668711eee834381 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 13:40:21 +0000 Subject: [PATCH 074/403] Refs #8550. Windows error and a general warning fix. --- .../Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h | 2 +- .../PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 6e3813303d69..367250b959ec 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -129,8 +129,8 @@ namespace DataObjects long int size(0); for ( auto elemIt = m_data.begin(); elemIt != m_data.end(); ++elemIt ) - size += elemIt->size() * sizeof(Type); { + size += static_cast( elemIt->size() * sizeof(Type) ); } return size; diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp index 6142da4c71d7..a715b769ede2 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ITableWorkspace.cpp @@ -18,7 +18,7 @@ #include // See http://docs.scipy.org/doc/numpy/reference/c-api.array.html#PY_ARRAY_UNIQUE_SYMBOL -#define PY_ARRAY_UNIQUE_SYMBOL KERNEL_ARRAY_API +#define PY_ARRAY_UNIQUE_SYMBOL API_ARRAY_API #define NO_IMPORT_ARRAY #include From 65d843e8edc126ba87bf38eede264056a1762197 Mon Sep 17 00:00:00 2001 From: Roman Tolchenov Date: Thu, 5 Dec 2013 14:21:53 +0000 Subject: [PATCH 075/403] ISISLiveEventDataListener tries to load instrument. If it cannot it gives a warning and carries on. Re #8555 --- .../src/ISISLiveEventDataListener.cpp | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp index 3289f213f673..3713a9101df9 100644 --- a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp +++ b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp @@ -100,7 +100,6 @@ bool ISISLiveEventDataListener::connect(const Poco::Net::SocketAddress &address) if (address.host().toString().compare( "0.0.0.0") == 0) { Poco::Net::SocketAddress tempAddress("127.0.0.1:10000"); - //Poco::Net::SocketAddress tempAddress("NDXTESTFAA:10000"); try { m_socket.connect( tempAddress); // BLOCKING connect } catch (...) { @@ -408,17 +407,32 @@ void ISISLiveEventDataListener::loadSpectraMap() */ void ISISLiveEventDataListener::loadInstrument(const std::string &instrName) { - API::Algorithm_sptr alg = API::AlgorithmFactory::Instance().create("LoadInstrument",-1); - alg->initialize(); - alg->setPropertyValue("InstrumentName",instrName); - alg->setProperty("Workspace", m_eventBuffer[0]); - alg->setProperty("RewriteSpectraMap", false); - alg->setChild(true); - alg->execute(); - // check if the instrument was loaded - if ( !alg->isExecuted() ) + // try to load the instrument. if it doesn't load give a warning and carry on + if ( instrName.empty() ) { - throw std::runtime_error("Failed to load instrument " + instrName); + g_log.warning() << "Unable to read instrument name from DAE." << std::endl; + return; + } + const char *warningMessage = "Failed to load instrument "; + try + { + API::Algorithm_sptr alg = API::AlgorithmFactory::Instance().create("LoadInstrument",-1); + alg->initialize(); + alg->setPropertyValue("InstrumentName",instrName); + alg->setProperty("Workspace", m_eventBuffer[0]); + alg->setProperty("RewriteSpectraMap", false); + alg->setChild(true); + alg->execute(); + // check if the instrument was loaded + if ( !alg->isExecuted() ) + { + g_log.warning() << warningMessage << instrName << std::endl; + } + } + catch(std::exception& e) + { + g_log.warning() << warningMessage << instrName << std::endl; + g_log.warning() << e.what() << instrName << std::endl; } } From a6a122b3bd26258b10655974b8dfad94a08279a8 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Thu, 5 Dec 2013 15:51:09 +0000 Subject: [PATCH 076/403] Add non-active parameterXML property re #8546 I also drilled it down into the execManually method changing its arguments. Signed-off-by: Karl Palmen --- .../inc/MantidDataHandling/LoadParameterFile.h | 2 +- .../DataHandling/src/LoadIDFFromNexus.cpp | 2 +- .../DataHandling/src/LoadInstrument.cpp | 2 +- .../DataHandling/src/LoadParameterFile.cpp | 16 ++++++++++------ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h index 83147785439b..1a0bad10c7f7 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h @@ -84,7 +84,7 @@ namespace Mantid /// Algorithm's category for identification overriding a virtual method virtual const std::string category() const { return "DataHandling\\Instrument";} - static void execManually(std::string filename, Mantid::API::ExperimentInfo_sptr localWorkspace); + static void execManually(bool useString, std::string filename, std::string parameterString, Mantid::API::ExperimentInfo_sptr localWorkspace); private: /// Sets documentation strings for this algorithm diff --git a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp index 9e81ce5b3132..63188bc98028 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp @@ -90,7 +90,7 @@ void LoadIDFFromNexus::runLoadParameterFile(const MatrixWorkspace_sptr & workspa const std::string paramFile = directory + instrumentName + "_Parameters.xml"; try { - LoadParameterFile::execManually(paramFile, workspace); + LoadParameterFile::execManually(false, paramFile,"", workspace); } catch ( std::runtime_error& ) { g_log.notice() << "File " << paramFile << " not found or un-parsable. " "However, the instrument has been loaded successfully.\n"; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp index f79f227b0f30..4aec499f0b65 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp @@ -237,7 +237,7 @@ namespace Mantid try { // To allow the use of ExperimentInfo instead of workspace, we call it manually - LoadParameterFile::execManually(fullPathParamIDF, m_workspace); + LoadParameterFile::execManually(false, fullPathParamIDF, "", m_workspace); g_log.debug("Parameters loaded successfully."); } catch (std::invalid_argument& e) { diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index fa30cca9b7b5..6ec3424405a2 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -59,8 +59,8 @@ DECLARE_ALGORITHM(LoadParameterFile) /// Sets documentation strings for this algorithm void LoadParameterFile::initDocs() { - this->setWikiSummary("Loads instrument parameters into a [[workspace]]. where these parameters are associated component names as defined in Instrument Definition File ([[InstrumentDefinitionFile|IDF]])."); - this->setOptionalMessage("Loads instrument parameters into a workspace. where these parameters are associated component names as defined in Instrument Definition File (IDF)."); + this->setWikiSummary("Loads instrument parameters into a [[workspace]]. where these parameters are associated component names as defined in Instrument Definition File ([[InstrumentDefinitionFile|IDF]]) or a string consisting of the contents of such.."); + this->setOptionalMessage("Loads instrument parameters into a workspace. where these parameters are associated component names as defined in Instrument Definition File (IDF) or a string consisting of the contents of such."); } @@ -80,8 +80,9 @@ void LoadParameterFile::init() declareProperty( new WorkspaceProperty("Workspace","Anonymous",Direction::InOut), "The name of the workspace to load the instrument parameters into." ); - declareProperty(new FileProperty("Filename","", FileProperty::Load, ".xml"), - "The filename (including its full or relative path) of a parameter defintion file. The file extension must either be .xml or .XML."); + declareProperty(new FileProperty("Filename","", FileProperty::OptionalLoad, ".xml"), + "The filename (including its full or relative path) of a parameter definition file. The file extension must either be .xml or .XML."); + declareProperty("ParameterXML","","The parameter definition XML as a string."); } /** Executes the algorithm. Reading in the file and creating and populating @@ -95,13 +96,16 @@ void LoadParameterFile::exec() // Retrieve the filename from the properties std::string filename = getPropertyValue("Filename"); + // Retrieve the parameter XML string from the properties + std::string parameterXML = getPropertyValue("ParameterXML"); + // Get the input workspace const MatrixWorkspace_sptr localWorkspace = getProperty("Workspace"); - execManually(filename, localWorkspace); + execManually(false, filename, parameterXML, localWorkspace); } -void LoadParameterFile::execManually(std::string filename, Mantid::API::ExperimentInfo_sptr localWorkspace) +void LoadParameterFile::execManually(bool useString, std::string filename, std::string parameterXML, Mantid::API::ExperimentInfo_sptr localWorkspace) { // TODO: Refactor to remove the need for the const cast Instrument_sptr instrument = boost::const_pointer_cast(localWorkspace->getInstrument()->baseInstrument()); From a2607bee82abdcfed4bcf110a55216f6bf725192 Mon Sep 17 00:00:00 2001 From: Ricardo Leal Date: Thu, 5 Dec 2013 16:58:25 +0100 Subject: [PATCH 077/403] Re #8526 Working version. accepts vana. --- .../inc/MantidDataHandling/LoadILL.h | 7 +- .../Framework/DataHandling/src/LoadILL.cpp | 121 ++++++++++++++---- 2 files changed, 98 insertions(+), 30 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILL.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILL.h index b46c2cc937fb..2a7ead842a01 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILL.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILL.h @@ -78,7 +78,7 @@ namespace DataHandling { int getDetectorElasticPeakPosition(const NeXus::NXInt &data); void loadTimeDetails(NeXus::NXEntry& entry); NeXus::NXData loadNexusFileData(NeXus::NXEntry& entry); - void loadDataIntoTheWorkSpace(NeXus::NXEntry& entry); + void loadDataIntoTheWorkSpace(NeXus::NXEntry& entry, int vanaCalculatedDetectorElasticPeakPosition = -1); void runLoadInstrument(); @@ -86,10 +86,13 @@ namespace DataHandling { static double calculateError(double in) { return sqrt(in); } + int validateVanadium(const std::string &); API::MatrixWorkspace_sptr m_localWorkspace; - std::string m_filename; ///< The file to load +// NeXus::NXRoot m_dataRoot; +// NeXus::NXRoot m_vanaRoot; + std::string m_instrumentName; ///< Name of the instrument std::string m_instrumentPath; ///< Name of the instrument path diff --git a/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp b/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp index c1a7edf00e91..df203d840d8f 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp @@ -1,8 +1,14 @@ /*WIKI* -Loads an ILL nexus file into a [[Workspace2D]] with the given name. +Loads an ILL TOF NeXus file into a [[Workspace2D]] with the given name. + +This loader calculates the elastic peak position (EPP) on the fly. +In cases where the dispersion peak might be higher than the EPP, it is good practice to load a Vanadium file. + +The property FilenameVanadium is optional. If it is present the EPP will be loaded from the Vanadium data. + +To date this algorithm only supports: IN4, IN5 and IN6 -To date this algorithm only supports: IN5 *WIKI*/ @@ -79,14 +85,19 @@ namespace Mantid //--------------------------------------------------- LoadILL::LoadILL() : + API::IFileLoader() { - m_instrumentName = ""; m_wavelength = 0; m_channelWidth = 0; m_numberOfChannels = 0; m_numberOfHistograms = 0; + m_numberOfTubes = 0; + m_numberOfPixelsPerTube = 0; + m_monitorElasticPeakPosition = 0; + m_l1 = 0; + m_l2 = 0; m_supportedInstruments.push_back("IN4"); m_supportedInstruments.push_back("IN5"); m_supportedInstruments.push_back("IN6"); @@ -100,36 +111,78 @@ namespace Mantid { declareProperty( new FileProperty("Filename", "", FileProperty::Load, ".nxs"), - "Name of the SPE file to load"); + "File path of the Data file to load"); + declareProperty( + new FileProperty("FilenameVanadium", "", FileProperty::OptionalLoad, ".nxs"), + "File path of the Vanadium file to load (Optional)"); + declareProperty( new WorkspaceProperty<>("OutputWorkspace", "", Direction::Output), "The name to use for the output workspace"); } + /** + * + */ + int LoadILL::validateVanadium(const std::string &filenameVanadium) { + NeXus::NXRoot vanaRoot(filenameVanadium); + NXEntry vanaFirstEntry = vanaRoot.openFirstEntry(); + + double wavelength = vanaFirstEntry.getFloat("wavelength"); + + // read in the data + NXData dataGroup = vanaFirstEntry.openNXData("data"); + NXInt data = dataGroup.openIntData(); + + size_t numberOfTubes = static_cast(data.dim0()); + size_t numberOfPixelsPerTube = static_cast(data.dim1()); + size_t numberOfChannels = static_cast(data.dim2()); + + if (wavelength != m_wavelength || numberOfTubes != m_numberOfTubes + || numberOfPixelsPerTube != m_numberOfPixelsPerTube + || numberOfChannels != m_numberOfChannels) { + throw std::runtime_error( + "Vanadium and Data were not collected in the same conditions!"); + } + + data.load(); + int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition( + data); + return calculatedDetectorElasticPeakPosition; + } + + /** * Execute the algorithm */ void LoadILL::exec() { // Retrieve filename - m_filename = getPropertyValue("Filename"); + std::string filenameData = getPropertyValue("Filename"); + std::string filenameVanadium = getPropertyValue("FilenameVanadium"); + // open the root node - NXRoot root(m_filename); - // find the first entry - NXEntry entry = root.openFirstEntry(); + NeXus::NXRoot dataRoot(filenameData); + NXEntry dataFirstEntry = dataRoot.openFirstEntry(); - loadInstrumentDetails(entry); - loadTimeDetails(entry); - initWorkSpace(entry); + loadInstrumentDetails(dataFirstEntry); + loadTimeDetails(dataFirstEntry); + initWorkSpace(dataFirstEntry); runLoadInstrument(); // just to get IDF contents initInstrumentSpecific(); - loadDataIntoTheWorkSpace(entry); + int calculatedDetectorElasticPeakPosition = -1; + if (filenameVanadium != "") { + g_log.information() << "Calculating the elastic peak position from the Vanadium." << std::endl; + calculatedDetectorElasticPeakPosition = validateVanadium(filenameVanadium); + } + + loadDataIntoTheWorkSpace(dataFirstEntry,calculatedDetectorElasticPeakPosition); - loadRunDetails(entry); - loadExperimentDetails(entry); + loadRunDetails(dataFirstEntry); + loadExperimentDetails(dataFirstEntry); // load the instrument from the IDF if it exists runLoadInstrument(); @@ -141,20 +194,27 @@ namespace Mantid /** * */ - void LoadILL::loadInstrumentDetails(NeXus::NXEntry& firstEntry) - { + void LoadILL::loadInstrumentDetails(NeXus::NXEntry& firstEntry) { - m_instrumentPath = m_loader.findInstrumentNexusPath(firstEntry); + m_instrumentPath = m_loader.findInstrumentNexusPath(firstEntry); - if (m_instrumentPath == "") - { - throw std::runtime_error("Cannot set the instrument name from the Nexus file!"); - } - m_instrumentName = m_loader.getStringFromNexusPath(firstEntry, - m_instrumentPath + "/name"); - g_log.debug() << "Instrument name set to: " + m_instrumentName << std::endl; + if (m_instrumentPath == "") { + throw std::runtime_error( + "Cannot set the instrument name from the Nexus file!"); + } - } + m_instrumentName = m_loader.getStringFromNexusPath(firstEntry, + m_instrumentPath + "/name"); + + if (std::find(m_supportedInstruments.begin(), m_supportedInstruments.end(), + m_instrumentName) == m_supportedInstruments.end()) { + std::string message = "The instrument " + m_instrumentName + " is not valid for this loader!"; + throw std::runtime_error(message); + } + + g_log.debug() << "Instrument name set to: " + m_instrumentName << std::endl; + + } /** * Creates the workspace and initialises member variables with @@ -411,8 +471,9 @@ namespace Mantid * Loads all the spectra into the workspace, including that from the monitor * * @param entry :: The Nexus entry + * @param vanaCalculatedDetectorElasticPeakPosition :: If -1 uses this value as the elastic peak position at the detector. */ - void LoadILL::loadDataIntoTheWorkSpace(NeXus::NXEntry& entry) + void LoadILL::loadDataIntoTheWorkSpace(NeXus::NXEntry& entry, int vanaCalculatedDetectorElasticPeakPosition) { // read in the data @@ -424,8 +485,12 @@ namespace Mantid * Detector: Find real elastic peak in the detector. * Looks for a few elastic peaks on the equatorial line of the detector. */ - int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition( - data); + int calculatedDetectorElasticPeakPosition; + if (vanaCalculatedDetectorElasticPeakPosition == -1) + calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition(data); + else + calculatedDetectorElasticPeakPosition = vanaCalculatedDetectorElasticPeakPosition; + double theoreticalElasticTOF = (m_loader.calculateTOF(m_l1,m_wavelength) + m_loader.calculateTOF(m_l2,m_wavelength)) * 1e6; //microsecs From 69ea0418c77f805fc08f4802a899b36af63e257e Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 16:23:18 +0000 Subject: [PATCH 078/403] Refs #8550. Returning Detector Grouping from LoadMuonNexus. Plus tests for it. --- .../inc/MantidDataHandling/LoadMuonNexus1.h | 8 + .../DataHandling/src/LoadMuonNexus.cpp | 3 + .../DataHandling/src/LoadMuonNexus1.cpp | 96 +++++++++++- .../DataHandling/test/LoadMuonNexus1Test.h | 138 ++++++++++++++++++ 4 files changed, 244 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h index 09a90e1c0155..368353fdaa57 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h @@ -108,6 +108,14 @@ namespace Mantid /// Creates Dead Time Table using all the data between begin and end TableWorkspace_sptr createDeadTimeTable(std::vector::const_iterator begin, std::vector::const_iterator end); + + /// Loads detector grouping information + void loadDetectorGrouping(Mantid::NeXus::NXRoot& root); + + /// Creates Detector Grouping Table using all the data from the range + TableWorkspace_sptr createDetectorGroupingTable(std::vector::const_iterator begin, + std::vector::const_iterator end); + }; } // namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp index f13efb2dff3e..b9618c7b73c0 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp @@ -91,6 +91,9 @@ namespace Mantid declareProperty(new WorkspaceProperty("DeadTimeTable", "", Direction::Output, PropertyMode::Optional), "Table or a group of tables containing detector dead times"); + + declareProperty(new WorkspaceProperty("DetectorGroupingTable", "", Direction::Output, PropertyMode::Optional), + "Table or a group of tables with information about the detector grouping stored in the file (if any)"); } /// Validates the optional 'spectra to read' properties, if they have been set diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 725e583c4cd8..1e89a0c0f330 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -170,9 +170,12 @@ namespace Mantid m_numberOfPeriods = nxload.t_nper; } - // When we know number of periods and spectra - we can load dead times + // Try to load dead time info loadDeadTimes(root); + // Try to load detector grouping info + loadDetectorGrouping(root); + // Need to extract the user-defined output workspace name Property *ws = getProperty("OutputWorkspace"); std::string localWSName = ws->value(); @@ -520,6 +523,64 @@ namespace Mantid // error } + /** + * Loads detector grouping. + * @param root :: Root entry of the Nexus file to read from + */ + void LoadMuonNexus1::loadDetectorGrouping(NXRoot& root) + { + if ( getPropertyValue("DetectorGroupingTable").empty() ) + return; + + NXEntry dataEntry = root.openEntry("run/histogram_data_1"); + + NXInfo infoGrouping = dataEntry.getDataSetInfo("grouping"); + if ( infoGrouping.stat != NX_ERROR ) + { + NXInt groupingData = dataEntry.openNXInt("grouping"); + groupingData.load(); + + int numGroupingEntries = groupingData.dim0(); + + std::vector grouping; + grouping.reserve(numGroupingEntries); + + for ( int i = 0; i < numGroupingEntries; i++ ) + grouping.push_back(groupingData[i]); + + if ( numGroupingEntries < m_numberOfSpectra ) + { + throw Exception::FileError("Number of grouping entries is less than number of spectra", + m_filename); + } + else if ( numGroupingEntries == m_numberOfSpectra) + { + // Simpliest case - one grouping entry per spectra + TableWorkspace_sptr table = createDetectorGroupingTable( grouping.begin(), grouping.end() ); + setProperty("DetectorGroupingTable", table); + } + else + { + // More complex case - grouping information for every period + + if ( numGroupingEntries != m_numberOfSpectra * m_numberOfPeriods ) + { + throw Exception::FileError("Number of grouping entries doesn't cover every spectra in every period", + m_filename); + } + + WorkspaceGroup_sptr tableGroup = boost::make_shared(); + + for ( auto it = grouping.begin(); it != grouping.end(); it += m_numberOfSpectra ) + { + tableGroup->addWorkspace( createDetectorGroupingTable(it, it + m_numberOfSpectra) ); + } + + setProperty("DetectorGroupingTable", tableGroup); + } + } + } + /** * Creates Dead Time Table using all the data between begin and end. * @@ -547,6 +608,39 @@ namespace Mantid return deadTimeTable; } + /** + * Creates Detector Grouping Table using all the data between begin and end. + * + * @param begin :: Iterator to the first element of the data to use + * @param end :: Iterator to the last element of the data to use + * @return Detector Grouping Table create using the data + */ + TableWorkspace_sptr LoadMuonNexus1::createDetectorGroupingTable( + std::vector::const_iterator begin, std::vector::const_iterator end) + { + auto detectorGroupingTable = boost::dynamic_pointer_cast( + WorkspaceFactory::Instance().createTable("TableWorkspace") ); + + detectorGroupingTable->addColumn("str", "ItemType"); + detectorGroupingTable->addColumn("str", "ItemName"); + detectorGroupingTable->addColumn("vector_int", "Elements"); + + std::map> grouping; + + for ( auto it = begin; it != end; ++it ) + { + grouping[*it].push_back( static_cast( std::distance(begin,it) ) ); + } + + for ( auto it = grouping.begin(); it != grouping.end(); ++it ) + { + TableRow newRow = detectorGroupingTable->appendRow(); + newRow << "Group" << boost::lexical_cast(it->first) << it->second; + } + + return detectorGroupingTable; + } + /** Load in a single spectrum taken from a NeXus file * @param tcbs :: The vector containing the time bin boundaries * @param hist :: The workspace index diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h index 7bee9c72985a..cab5da8b8679 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h @@ -492,7 +492,145 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite AnalysisDataService::Instance().deepRemoveGroup(outWSName); AnalysisDataService::Instance().deepRemoveGroup(deadTimesWSName); } + + void test_loadingDetectorGrouping_singlePeriod() + { + const std::string outWSName = "LoadMuonNexus1Test_OutputWS"; + const std::string detectorGroupingWSName = "LoadMuonNexus1Test_DetectorGrouping"; + + LoadMuonNexus1 alg; + + TS_ASSERT_THROWS_NOTHING( alg.initialize() ); + TS_ASSERT( alg.isInitialized() ); + + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "emu00006473.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("DetectorGroupingTable", detectorGroupingWSName) ); + + TS_ASSERT_THROWS_NOTHING( alg.execute() ); + TS_ASSERT( alg.isExecuted() ); + + TableWorkspace_sptr detectorGrouping; + + TS_ASSERT_THROWS_NOTHING( detectorGrouping = + AnalysisDataService::Instance().retrieveWS( detectorGroupingWSName ) ); + + TS_ASSERT( detectorGrouping ); + + if ( detectorGrouping ) + { + TS_ASSERT_EQUALS( detectorGrouping->columnCount(), 3 ); + TS_ASSERT_EQUALS( detectorGrouping->rowCount(), 2 ); + + TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->type(), "str" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(1)->type(), "str" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(2)->type(), "vector_int" ); + + TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->name(), "ItemType" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(1)->name(), "ItemName" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(2)->name(), "Elements" ); + + TS_ASSERT_EQUALS( detectorGrouping->cell(0,0), "Group" ); + TS_ASSERT_EQUALS( detectorGrouping->cell(1,0), "Group" ); + + TS_ASSERT_EQUALS( detectorGrouping->cell(0,1), "1" ); + TS_ASSERT_EQUALS( detectorGrouping->cell(1,1), "2" ); + + std::vector e1, e2; + TS_ASSERT_THROWS_NOTHING( e1 = detectorGrouping->cell< std::vector >(0,2) ); + TS_ASSERT_THROWS_NOTHING( e2 = detectorGrouping->cell< std::vector >(1,2) ); + + TS_ASSERT_EQUALS( e1.size(), 16); + TS_ASSERT_EQUALS( e2.size(), 16); + + TS_ASSERT_EQUALS( e1[0], 0 ); + TS_ASSERT_EQUALS( e1[15], 15); + + TS_ASSERT_EQUALS( e2[0], 16 ); + TS_ASSERT_EQUALS( e2[15], 31 ); + } + + AnalysisDataService::Instance().remove(outWSName); + AnalysisDataService::Instance().remove(detectorGroupingWSName); + } + void test_loadingDetectorGrouping_multiPeriod() + { + const std::string outWSName = "LoadMuonNexus1Test_OutputWS"; + const std::string detectorGroupingWSName = "LoadMuonNexus1Test_DetectorGrouping"; + + LoadMuonNexus1 alg; + + TS_ASSERT_THROWS_NOTHING( alg.initialize() ); + TS_ASSERT( alg.isInitialized() ); + + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "MUSR00015189.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("DetectorGroupingTable", detectorGroupingWSName) ); + + TS_ASSERT_THROWS_NOTHING( alg.execute() ); + TS_ASSERT( alg.isExecuted() ); + + WorkspaceGroup_sptr detectorGrouping; + + TS_ASSERT_THROWS_NOTHING( detectorGrouping = + AnalysisDataService::Instance().retrieveWS( detectorGroupingWSName ) ); + + TS_ASSERT( detectorGrouping ); + + if ( detectorGrouping ) + { + TS_ASSERT_EQUALS( detectorGrouping->size(), 2 ); + + TableWorkspace_sptr table1 = boost::dynamic_pointer_cast( detectorGrouping->getItem(0) ); + TS_ASSERT( table1 ); + + if ( table1 ) + { + TS_ASSERT_EQUALS( table1->columnCount(), 3 ); + TS_ASSERT_EQUALS( table1->rowCount(), 2 ); + + std::vector e1, e2; + TS_ASSERT_THROWS_NOTHING( e1 = table1->cell< std::vector >(0,2) ); + TS_ASSERT_THROWS_NOTHING( e2 = table1->cell< std::vector >(1,2) ); + + TS_ASSERT_EQUALS( e1.size(), 32); + TS_ASSERT_EQUALS( e2.size(), 32); + + TS_ASSERT_EQUALS( e1[0], 32 ); + TS_ASSERT_EQUALS( e1[31], 63 ); + + TS_ASSERT_EQUALS( e2[0], 0 ); + TS_ASSERT_EQUALS( e2[31], 31 ); + } + + TableWorkspace_sptr table2 = boost::dynamic_pointer_cast( detectorGrouping->getItem(1) ); + TS_ASSERT( table2 ); + + if ( table2 ) + { + TS_ASSERT_EQUALS( table2->columnCount(), 3 ); + TS_ASSERT_EQUALS( table2->rowCount(), 2 ); + + std::vector e1, e2; + TS_ASSERT_THROWS_NOTHING( e1 = table2->cell< std::vector >(0,2) ); + TS_ASSERT_THROWS_NOTHING( e2 = table2->cell< std::vector >(1,2) ); + + TS_ASSERT_EQUALS( e1.size(), 32); + TS_ASSERT_EQUALS( e2.size(), 32); + + TS_ASSERT_EQUALS( e1[0], 32 ); + TS_ASSERT_EQUALS( e1[31], 63 ); + + TS_ASSERT_EQUALS( e2[0], 0 ); + TS_ASSERT_EQUALS( e2[31], 31); + + } + } + + AnalysisDataService::Instance().deepRemoveGroup(outWSName); + AnalysisDataService::Instance().deepRemoveGroup(detectorGroupingWSName); + } private: LoadMuonNexus1 nxLoad,nxload2,nxload3; std::string outputSpace; From 18982a6fdefea788c9b48f64c2df7e44d2ae1fcc Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 5 Dec 2013 18:13:23 +0000 Subject: [PATCH 079/403] Refs #8550. Initial files for MuonGroupDetectors. --- .../Framework/Algorithms/CMakeLists.txt | 15 ++- .../inc/MantidAlgorithms/MuonGroupDetectors.h | 56 ++++++++ .../Algorithms/src/MuonGroupDetectors.cpp | 121 ++++++++++++++++++ .../Algorithms/test/MuonGroupDetectorsTest.h | 96 ++++++++++++++ 4 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MuonGroupDetectors.h create mode 100644 Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp create mode 100644 Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 2704d17de2c5..71e2a2414275 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -46,8 +46,8 @@ set ( SRC_FILES src/ConvertToPointData.cpp src/ConvertUnits.cpp src/CopyInstrumentParameters.cpp - src/CopySample.cpp src/CopyLogs.cpp + src/CopySample.cpp src/CorrectFlightPaths.cpp src/CorrectKiKf.cpp src/CorrectToFile.cpp @@ -100,8 +100,8 @@ set ( SRC_FILES src/FindDeadDetectors.cpp src/FindDetectorsOutsideLimits.cpp src/FindPeakBackground.cpp - src/FitPeak.cpp src/FindPeaks.cpp + src/FitPeak.cpp src/FixGSASInstrumentFile.cpp src/FlatPlateAbsorption.cpp src/GeneralisedSecondDifference.cpp @@ -139,6 +139,7 @@ set ( SRC_FILES src/MultipleScatteringCylinderAbsorption.cpp src/Multiply.cpp src/MultiplyRange.cpp + src/MuonGroupDetectors.cpp src/NormaliseByCurrent.cpp src/NormaliseByDetector.cpp src/NormaliseToMonitor.cpp @@ -266,8 +267,8 @@ set ( INC_FILES inc/MantidAlgorithms/ConvertToPointData.h inc/MantidAlgorithms/ConvertUnits.h inc/MantidAlgorithms/CopyInstrumentParameters.h - inc/MantidAlgorithms/CopySample.h inc/MantidAlgorithms/CopyLogs.h + inc/MantidAlgorithms/CopySample.h inc/MantidAlgorithms/CorrectFlightPaths.h inc/MantidAlgorithms/CorrectKiKf.h inc/MantidAlgorithms/CorrectToFile.h @@ -320,8 +321,8 @@ set ( INC_FILES inc/MantidAlgorithms/FindDeadDetectors.h inc/MantidAlgorithms/FindDetectorsOutsideLimits.h inc/MantidAlgorithms/FindPeakBackground.h - inc/MantidAlgorithms/FitPeak.h inc/MantidAlgorithms/FindPeaks.h + inc/MantidAlgorithms/FitPeak.h inc/MantidAlgorithms/FixGSASInstrumentFile.h inc/MantidAlgorithms/FlatPlateAbsorption.h inc/MantidAlgorithms/GSLFunctions.h @@ -360,6 +361,7 @@ set ( INC_FILES inc/MantidAlgorithms/MultipleScatteringCylinderAbsorption.h inc/MantidAlgorithms/Multiply.h inc/MantidAlgorithms/MultiplyRange.h + inc/MantidAlgorithms/MuonGroupDetectors.h inc/MantidAlgorithms/NormaliseByCurrent.h inc/MantidAlgorithms/NormaliseByDetector.h inc/MantidAlgorithms/NormaliseToMonitor.h @@ -498,8 +500,8 @@ set ( TEST_FILES ConvertToPointDataTest.h ConvertUnitsTest.h CopyInstrumentParametersTest.h - CopySampleTest.h CopyLogsTest.h + CopySampleTest.h CorrectFlightPathsTest.h CorrectKiKfTest.h CorrectToFileTest.h @@ -546,8 +548,8 @@ set ( TEST_FILES FindDeadDetectorsTest.h FindDetectorsOutsideLimitsTest.h FindPeakBackgroundTest.h - FitPeakTest.h FindPeaksTest.h + FitPeakTest.h FixGSASInstrumentFileTest.h FlatPlateAbsorptionTest.h GenerateEventsFilterTest.h @@ -579,6 +581,7 @@ set ( TEST_FILES MultipleScatteringCylinderAbsorptionTest.h MultiplyRangeTest.h MultiplyTest.h + MuonGroupDetectorsTest.h NormaliseByCurrentTest.h NormaliseByDetectorTest.h NormaliseToMonitorTest.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MuonGroupDetectors.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MuonGroupDetectors.h new file mode 100644 index 000000000000..6fa3570e3e8e --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MuonGroupDetectors.h @@ -0,0 +1,56 @@ +#ifndef MANTID_ALGORITHMS_MUONGROUPDETECTORS_H_ +#define MANTID_ALGORITHMS_MUONGROUPDETECTORS_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ +namespace Algorithms +{ + + /** MuonGroupDetectors : applies detector grouping to a workspace. (Muon version) + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport MuonGroupDetectors : public API::Algorithm + { + public: + MuonGroupDetectors(); + virtual ~MuonGroupDetectors(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + + private: + virtual void initDocs(); + void init(); + void exec(); + + + }; + + +} // namespace Algorithms +} // namespace Mantid + +#endif /* MANTID_ALGORITHMS_MUONGROUPDETECTORS_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp new file mode 100644 index 000000000000..510bdbb28c5a --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp @@ -0,0 +1,121 @@ +/*WIKI* +Applies detector grouping to a workspace. (Muon version). + +TODO: Table format description +*WIKI*/ + +#include "MantidAlgorithms/MuonGroupDetectors.h" +#include "MantidAPI/WorkspaceFactory.h" +#include "MantidDataObjects/TableWorkspace.h" + + +namespace Mantid +{ +namespace Algorithms +{ + + using namespace Kernel; + using namespace API; + using namespace DataObjects; + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(MuonGroupDetectors) + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + MuonGroupDetectors::MuonGroupDetectors() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + MuonGroupDetectors::~MuonGroupDetectors() + { + } + + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string MuonGroupDetectors::name() const { return "MuonGroupDetectors";}; + + /// Algorithm's version for identification. @see Algorithm::version + int MuonGroupDetectors::version() const { return 1;}; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string MuonGroupDetectors::category() const { return "Muon"; } + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void MuonGroupDetectors::initDocs() + { + this->setWikiSummary("Applies detector grouping to a workspace. (Muon version)."); + this->setOptionalMessage("Applies detector grouping to a workspace. (Muon version)."); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void MuonGroupDetectors::init() + { + declareProperty(new WorkspaceProperty("InputWorkspace","",Direction::Input), + "Workspace to apply grouping to."); + + declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input), + "Table with detector grouping information. Check wiki page for table format expected."); + + declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), + "Workspace with detectors grouped."); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void MuonGroupDetectors::exec() + { + TableWorkspace_sptr table = getProperty("DetectorGroupingTable"); + + // Check that table does have expected format + + if ( table->columnCount() != 3 ) + throw std::invalid_argument("Detector Grouping Table should have 3 columns"); + + if ( table->getColumn(0)->type() != "str" ) + throw std::invalid_argument("Invalid type of the first column. Should be string."); + + if ( table->getColumn(1)->type() != "str" ) + throw std::invalid_argument("Invalid type of the second column. Should be string."); + + if ( table->getColumn(2)->type() != "vector_int" ) + throw std::invalid_argument("Invalid type of the third column. Should be vector of ints."); + + size_t numGroups(0); + + // First pass to determine how many non-empty groups we have + for ( size_t row = 0; row < table->rowCount(); ++row ) + { + std::string& itemName = table->cell(row, 0); + std::vector& elements = table->cell< std::vector >(row, 2); + + if ( itemName == "Group" && elements.size() != 0 ) + { + numGroups++; + } + } + + if ( numGroups == 0 ) + throw std::invalid_argument("Detector Grouping Table doesn't contain any non-empty groups"); + + MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); + + // Create output workspace with all the same parameters as an input one except number of histograms + MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create(inWS, numGroups); + + setProperty("OutputWorkspace", outWS); + } + + + +} // namespace Algorithms +} // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h new file mode 100644 index 000000000000..767051c33f64 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h @@ -0,0 +1,96 @@ +#ifndef MANTID_ALGORITHMS_MUONGROUPDETECTORSTEST_H_ +#define MANTID_ALGORITHMS_MUONGROUPDETECTORSTEST_H_ + +#include + +#include "MantidAPI/TableRow.h" +#include "MantidAlgorithms/MuonGroupDetectors.h" +#include "MantidDataObjects/TableWorkspace.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" + +using Mantid::Algorithms::MuonGroupDetectors; + +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace Mantid::DataObjects; + +class MuonGroupDetectorsTest : public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static MuonGroupDetectorsTest *createSuite() { return new MuonGroupDetectorsTest(); } + static void destroySuite( MuonGroupDetectorsTest *suite ) { delete suite; } + + + void test_Init() + { + MuonGroupDetectors alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_exec() + { + // Name of the output workspace. + const std::string outWSName("MuonGroupDetectorsTest_OutputWS"); + + MatrixWorkspace_sptr inWS = WorkspaceCreationHelper::Create2DWorkspace123(5,3); + TableWorkspace_sptr grouping = createDetectorGroupingTable(); + + MuonGroupDetectors alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setProperty("InputWorkspace", inWS) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", grouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. TODO: Change to your desired type + MatrixWorkspace_sptr ws; + TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWSName) ); + TS_ASSERT(ws); + + if ( ws ) + { + TSM_ASSERT( "You forgot to check the results!", 0); + } + + // Remove workspace from the data service. + AnalysisDataService::Instance().remove(outWSName); + } + +private: + + TableWorkspace_sptr createDetectorGroupingTable() + { + auto t = boost::make_shared(); + + t->addColumn("str", "ItemType"); + t->addColumn("str", "ItemName"); + t->addColumn("vector_int", "Elements"); + + std::vector group1; + group1.push_back(0); group1.push_back(1); + TableRow row1 = t->appendRow(); + row1 << "Group" << "1" << group1; + + std::vector group2; + group2.push_back(2); group2.push_back(2); group2.push_back(3); + TableRow row2 = t->appendRow(); + row2 << "Group" << "2" << group2; + + // Just to make sure groups are used only + std::vector pair; + pair.push_back(0); pair.push_back(1); + TableRow row3 = t->appendRow(); + row3 << "Pair" << "ThePair" << pair; + + return t; + } + +}; + + +#endif /* MANTID_ALGORITHMS_MUONGROUPDETECTORSTEST_H_ */ From 595f5903d86ae7901c365f3a3bdc3cb6864b3067 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 5 Dec 2013 15:19:40 -0500 Subject: [PATCH 080/403] Refs #8508 Upper limit in one for loop was wrong --- .../Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index b948ce438431..bf17ff9ea875 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -133,7 +133,7 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal } std::vector ratel( N ); - for ( int l = 1; l < ( N - 1 ); l++) + for ( int l = 1; l < N; l++) // l goes up to N-1 { ratel[ l ] = rate * 4 * pow( sin( M_PI * l / N ), 2 ); // notice that 0 < l/N < 1 } @@ -142,11 +142,11 @@ void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xVal { double w = xValues[ i ]; double S = 0.0; - for ( int l = 1; l < ( N - 1 ); l++ ) + for ( int l = 1; l < N; l++ ) // l goes up to N-1 { double lorentzian = ratel[ l ] / ( ratel[ l ] * ratel[ l ] + w * w ); double al = 0.0; - for ( int k = 1; k < N; k++ ) + for ( int k = 1; k < N; k++ ) // case k==N after the loop { double y = 2 * M_PI * l * k / N; al += cos( y ) * sph[ k ]; From e4727397bfeefffcc90f38fc0e606e0c14daec3f Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 5 Dec 2013 15:21:00 -0500 Subject: [PATCH 081/403] Refs #8508 Test simple lorentzian case N=3 --- .../test/DiffRotDiscreteCircleTest.h | 98 ++++++++++++++++++- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h index ffc9033161bf..09ebaa06ed16 100644 --- a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -1,6 +1,7 @@ #ifndef DIFFROTDISCRETECIRCLETEST_H_ #define DIFFROTDISCRETECIRCLETEST_H_ +#include #include #include #include @@ -92,7 +93,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite fitalg.setProperty( "Function", funtion_string ); // create the data workspace by evaluating the fit function in the Fit algorithm - auto data_workspace = generateWorkspace( fitalg ); + auto data_workspace = generateWorkspaceFromFitAlgorithm( fitalg ); //saveWorkspace( data_workspace, "/tmp/junk.nxs" ); // for debugging purposes only //override the function with new parameters, then do the Fit @@ -127,6 +128,57 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite } // testDiffRotDiscreteCircleElastic + /* Check the particular case for N = 3 + * In this case, the inelastic part should reduce to a single Lorentzian in 'w': + * ( 2 / pi ) * A1( Q ) * ( 3 * tao / ( 9 + ( w * tao )**2 ) ) + * A1( Q ) = ( 1 / 3 ) * ( 1 - j0( Q * R * sqrt( 3 ) ) ) + * j0( x ) = sin( x ) / x + */ + void testDiffRotDiscreteCircleInelasticN3() + { + const double I = 2.9; + const double R = 2.3; + const double tao = 0.468; + const double Q = 0.9; + + // generate data workspace with the single lorentzian function + auto data_workspace = generateN3Workspace( I, R, tao, Q ); + //saveWorkspace( data_workspace, "/tmp/junk_single_lorentzian.nxs" ); // for debugging purposes only + + // initialize the fitting function string + // Parameter units are assumed in micro-eV, Angstroms, Angstroms**(-1), and nano-seconds. Intensities have arbitrary units + std::string funtion_string = "name=InelasticDiffRotDiscreteCircle,N=3,Q=0.9,Intensity=2.9,Radius=2.3,Decay=0.468"; + + // Do a fit with no iterations + Mantid::CurveFitting::Fit fitalg; + TS_ASSERT_THROWS_NOTHING( fitalg.initialize() ); + TS_ASSERT( fitalg.isInitialized() ); + fitalg.setProperty( "Function", funtion_string ); + fitalg.setProperty( "MaxIterations", 0 ); // no iterations + fitalg.setProperty( "InputWorkspace", data_workspace ); + fitalg.setPropertyValue( "WorkspaceIndex", "0" ); + TS_ASSERT_THROWS_NOTHING( TS_ASSERT( fitalg.execute() ) ); + TS_ASSERT( fitalg.isExecuted() ); + + // create temporary workspace to check Y-values produced by the Fit algorithm // for debugging purposes only + //auto temp_workspace = generateWorkspaceFromFitAlgorithm( fitalg ); // for debugging purposes only + //saveWorkspace( temp_workspace, "/tmp/junk_from_fit_algorithm.nxs" ); // for debugging purposes only + + // check Chi-square is small + const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); + TS_ASSERT_DELTA( chi_squared, 1e-09, 1e-09 ); + //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes + + // check the parameters of the InelasticDiffRotDiscreteCircle + Mantid::API::IFunction_sptr fitalg_structure_factor = fitalg.getProperty( "Function" ); + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Intensity" ), I, I * 0.01 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Radius" ), R, R * 0.01 ); // allow for a small percent variation + TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Decay" ), tao, tao * 0.01 ); // allow for a small percent variation + //std::cout << "\nGOAL: Intensity = 2.9, Radius = 2.3, Decay = 0.468\n"; // only for debugging purposes + //std::cout << "OPTIMIZED: Intensity = " << fitalg_structure_factor->getParameter("Intensity") << " Radius = " << fitalg_structure_factor->getParameter("Radius") << " Decay = " << fitalg_structure_factor->getParameter("Decay") << "\n"; // only for debugging purposes + + } + /// check ties between elastic and inelastic parts void testDiffRotDiscreteCircleTies() @@ -202,7 +254,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite fitalg.setProperty( "Function", funtion_string ); // create the data workspace by evaluating the fit function in the Fit algorithm - auto data_workspace = generateWorkspace( fitalg ); + auto data_workspace = generateWorkspaceFromFitAlgorithm( fitalg ); //saveWorkspace( data_workspace, "/tmp/junk.nxs" ); // for debugging purposes only //override the function with new parameters, then do the Fit @@ -278,6 +330,45 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite } + + /* Create a workspace with the following single lorentzian in 'w' + * ( 2 / pi ) * A1( Q ) * ( 3 * tao / ( 9 + ( w * tao )**2 ) ) + * A1( Q ) = ( 1 / 3 ) * ( 1 - j0( Q * R * sqrt( 3 ) ) ) + * j0( x ) = sin( x ) / x + */ + Mantid::DataObjects::Workspace2D_sptr generateN3Workspace( const double & I, const double & R, const double & tao, const double & Q ) + { + const double rate = 4.136 / tao; // conversion from picosec to mili-eV, or from nanosec to micro-eV + + // calculate prefix A1. Better be verbose for clarity + const double x = Q * R * sqrt( 3.0 ); + const double j0 = sin( x ) / x; + const double A1 = ( 1.0 / 3.0 ) * ( 1.0 - j0 ); + + // initialize some frequency values centered around zero. Will work as dataX + const size_t M = 1001; + double dataX[ M ]; + const double dw = 0.4; // typical bin width for BASIS@ORNL beamline, in micro-seconds + for( size_t i = 0; i < M; i++ ) dataX[i] = (static_cast(i) - M/2 ) * dw; + + // create the workspace + auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, M ); + double fractional_error = 0.01; // error taken as a percent of the signal + for( size_t i = 0; i < M; i++ ) + { + double bin_boundary = dataX[ i ] - dw / 2.0; // bin boundaries are shifted by half the bind width + double y = I * ( 2.0 / M_PI ) * A1 * ( 3.0 * rate / ( 9.0 * rate * rate + dataX[ i ] * dataX[ i ]) ); // verbose for clarity + ws -> dataX( 0 )[ i ] = bin_boundary ; + ws -> dataY( 0 )[ i ] = y; + ws -> dataE( 0 )[ i ] = fractional_error * y; // assume the error is a small percent of the actual value + } + ws -> dataX( 0 )[ M ] = dataX[ M - 1 ] + dw/2; // recall number of bin boundaries is 1 + #bins + + // return now the workspace + return ws; + } + + /// save a worskapece to a nexus file void saveWorkspace( Mantid::DataObjects::Workspace2D_sptr &ws, const std::string &filename ) { @@ -289,8 +380,9 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite save->execute(); } + // create a data workspace using a Fit algorithm - Mantid::DataObjects::Workspace2D_sptr generateWorkspace( Mantid::CurveFitting::Fit & fitalg ) + Mantid::DataObjects::Workspace2D_sptr generateWorkspaceFromFitAlgorithm( Mantid::CurveFitting::Fit & fitalg ) { // initialize some frequency values centered around zero. Will work as dataX const size_t M = 1001; From 457861313d7a8e18ad6e85d3aaeaa2fc6335a75f Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 5 Dec 2013 16:17:14 -0500 Subject: [PATCH 082/403] Refs #8508 change asserts for Chi2 --- .../test/DiffRotDiscreteCircleTest.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h index 09ebaa06ed16..b39bdfefccd3 100644 --- a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -106,7 +106,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite // check Chi-square is small const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); - TS_ASSERT_DELTA( chi_squared, 0.01, 0.01 ); + TS_ASSERT_LESS_THAN( chi_squared, 0.001 ); //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes // check the parameters of the resolution did not change @@ -164,12 +164,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite //auto temp_workspace = generateWorkspaceFromFitAlgorithm( fitalg ); // for debugging purposes only //saveWorkspace( temp_workspace, "/tmp/junk_from_fit_algorithm.nxs" ); // for debugging purposes only - // check Chi-square is small - const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); - TS_ASSERT_DELTA( chi_squared, 1e-09, 1e-09 ); - //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes - - // check the parameters of the InelasticDiffRotDiscreteCircle + // check the parameters of the InelasticDiffRotDiscreteCircle did not change Mantid::API::IFunction_sptr fitalg_structure_factor = fitalg.getProperty( "Function" ); TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Intensity" ), I, I * 0.01 ); // allow for a small percent variation TS_ASSERT_DELTA( fitalg_structure_factor -> getParameter( "Radius" ), R, R * 0.01 ); // allow for a small percent variation @@ -177,6 +172,11 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite //std::cout << "\nGOAL: Intensity = 2.9, Radius = 2.3, Decay = 0.468\n"; // only for debugging purposes //std::cout << "OPTIMIZED: Intensity = " << fitalg_structure_factor->getParameter("Intensity") << " Radius = " << fitalg_structure_factor->getParameter("Radius") << " Decay = " << fitalg_structure_factor->getParameter("Decay") << "\n"; // only for debugging purposes + // check Chi-square is small + const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); + TS_ASSERT_LESS_THAN( chi_squared, 1e-12 ); + //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes + } @@ -267,7 +267,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite // check Chi-square is small const double chi_squared = fitalg.getProperty("OutputChi2overDoF"); - TS_ASSERT_DELTA( chi_squared, 0.01, 0.01 ); + TS_ASSERT_LESS_THAN( chi_squared, 0.001 ); //std::cout << "\nchi_squared = " << chi_squared << "\n"; // only for debugging purposes // check the parameters of the resolution did not change From da798fd6df66f754b6f718d4055c5e04083bc1ba Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 5 Dec 2013 16:46:40 -0500 Subject: [PATCH 083/403] Refs #8508 More detailed description of the fitting function --- .../src/DiffRotDiscreteCircle.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index bf17ff9ea875..b233b3196f95 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -8,14 +8,25 @@ This is the most common type of discrete rotational diffusion in a circle. The fitting parameters are the inverse of the transition rate, \tau and the circle radius r - S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2} +
S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2}
- A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{\pi k}{N}) ) cos(\frac{2\pi lk}{N}) +
A_l(Q,r) = \frac{1}{N} \sum_{k=1}^{N} j_0( 2 Q r sin(\frac{\pi k}{N}) ) cos(\frac{2\pi lk}{N})
- \tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N}) +
\tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N})
-If the energy units are \mueV, then \tau is expressed in nano-seconds. If E-units are meV then -\tau is expressed in pico-seconds. +If the unit of \omega is energy, and the energy unit is \mueV, then \tau is expressed in nano-seconds. If E-unit is meV then \tau is expressed in pico-seconds. The conversion equation used between the jump transition rate k, expressed in energy units, and \tau is: k\cdot \tau=4.136\, meV\cdot ps=4.136\, \mu eV\cdot ns + +== Example: Methyl Rotations == +Methyl Rotations can be modelled setting N=3. In this case, the inelastic part reduces to a single Lorentzian: + +
S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{2}{\pi} A_1 (Q,r) \frac{3 \tau}{9+(\omega \tau)^2}
+ +If, alternatively, one models these dynamics using the [[Lorentzian]] function provided in Mantid: + +
S(Q,E) = A \delta (\omega) + \frac{B}{\pi} \left( \frac{\frac{\Gamma}{2}}{(\frac{\Gamma}{2})^2 + \omega^2}\right)
+Then the following equalities hold: +
B = 2\,A_1
+
\Gamma = 6\cdot 4.126/\tau
== Properties == @@ -43,6 +54,7 @@ If the energy units are \mueV, then \tau is expressed [[Category:Fit_functions]] + *WIKI*/ //---------------------------------------------------------------------- From 3e89ba209aac57ef1ed09bdaecc3e12798f92777 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 5 Dec 2013 16:58:01 -0500 Subject: [PATCH 084/403] Refs #8508 Even more detailed description modified: DiffRotDiscreteCircle.cpp --- .../Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index b233b3196f95..2de63a6fc38b 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -5,8 +5,11 @@ This fitting function models the dynamics structure factor of a particle undergo evenly distributed in a circle. The particle can only jump to neighboring sites. This is the most common type of discrete rotational diffusion in a circle. -The fitting parameters are the inverse of the transition rate, \tau -and the circle radius r +Markov model for jumps between neighboring sites: + +
\frac{d}{dt} p_j(t) = \frac{1}{\tau} [p_{j-1}(t) -2 p_j(t) + p_{j+1}(t)]
+ +The Decay fitting parameter \tau is the inverse of the transition rate. This, along with the circle radius r, conform the two fundamental fitting parameters of the structure factor S(Q,E):
S(Q,E) = A_0(Q,r) \delta (\omega) + \frac{1}{\pi} \sum_{l=1}^{N-1} A_l (Q,r) \frac{\tau_l}{1+(\omega \tau_l)^2}
@@ -54,7 +57,6 @@ Then the following equalities hold: [[Category:Fit_functions]] - *WIKI*/ //---------------------------------------------------------------------- From 1d6178b75e88d6d679618e41daa586a5a1cc931a Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 6 Dec 2013 11:20:41 +0000 Subject: [PATCH 085/403] Refs #8550. MuonGroupDetectors: code to apply grouping. Plus some tests for it. --- .../Algorithms/src/MuonGroupDetectors.cpp | 48 ++++++++++++++++--- .../Algorithms/test/MuonGroupDetectorsTest.h | 28 +++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp index 510bdbb28c5a..86c796e861e7 100644 --- a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp @@ -90,7 +90,8 @@ namespace Algorithms if ( table->getColumn(2)->type() != "vector_int" ) throw std::invalid_argument("Invalid type of the third column. Should be vector of ints."); - size_t numGroups(0); + std::vector groupRows; // Rows with non-empty groups + groupRows.reserve(table->rowCount()); // Most of rows will be groups // First pass to determine how many non-empty groups we have for ( size_t row = 0; row < table->rowCount(); ++row ) @@ -98,19 +99,52 @@ namespace Algorithms std::string& itemName = table->cell(row, 0); std::vector& elements = table->cell< std::vector >(row, 2); - if ( itemName == "Group" && elements.size() != 0 ) - { - numGroups++; - } + if ( itemName == "Group" && elements.size() != 0 ) + groupRows.push_back(row); + } - if ( numGroups == 0 ) + if ( groupRows.size() == 0 ) throw std::invalid_argument("Detector Grouping Table doesn't contain any non-empty groups"); MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); // Create output workspace with all the same parameters as an input one except number of histograms - MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create(inWS, numGroups); + MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create( inWS, groupRows.size() ); + + // Compile the groups + for ( auto groupIt = groupRows.begin(); groupIt != groupRows.end(); ++groupIt ) + { + size_t groupIndex = static_cast( std::distance(groupRows.begin(),groupIt) ); + + // Not "detectors" as such, but workspace indices. For Muons there is only one detector for + // workspace index in the data before grouping. + std::vector& detectors = table->cell< std::vector >(*groupIt,2); + + // We will be setting them anew + outWS->getSpectrum(groupIndex)->clearDetectorIDs(); + + for(auto detIt = detectors.begin(); detIt != detectors.end(); detIt++) + { + for( size_t i = 0; i < inWS->blocksize(); ++i ) + { + // Sum the y values + outWS->dataY(groupIndex)[i] += inWS->dataY(*detIt)[i]; + + // Sum the errors in quadrature + outWS->dataE(groupIndex)[i] = + sqrt(pow(outWS->dataE(groupIndex)[i], 2) + pow(inWS->dataE(*detIt)[i], 2)); + } + + // Detectors list of the group should contain all the detectors of it's elements + outWS->getSpectrum(groupIndex)->addDetectorIDs( inWS->getSpectrum(*detIt)->getDetectorIDs() ); + } + + // Using the first detector X values + outWS->dataX(groupIndex) = inWS->dataX(detectors.front()); + + outWS->getSpectrum(groupIndex)->setSpectrumNo( static_cast(groupIndex + 1) ); + } setProperty("OutputWorkspace", outWS); } diff --git a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h index 767051c33f64..8d1bce31171d 100644 --- a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h @@ -10,6 +10,7 @@ using Mantid::Algorithms::MuonGroupDetectors; +using namespace Mantid; using namespace Mantid::Kernel; using namespace Mantid::API; using namespace Mantid::DataObjects; @@ -36,6 +37,7 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite const std::string outWSName("MuonGroupDetectorsTest_OutputWS"); MatrixWorkspace_sptr inWS = WorkspaceCreationHelper::Create2DWorkspace123(5,3); + TableWorkspace_sptr grouping = createDetectorGroupingTable(); MuonGroupDetectors alg; @@ -47,14 +49,34 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite TS_ASSERT_THROWS_NOTHING( alg.execute(); ); TS_ASSERT( alg.isExecuted() ); - // Retrieve the workspace from data service. TODO: Change to your desired type MatrixWorkspace_sptr ws; TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWSName) ); TS_ASSERT(ws); if ( ws ) { - TSM_ASSERT( "You forgot to check the results!", 0); + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 2); + TS_ASSERT_EQUALS( ws->blocksize(), 3 ); + + TS_ASSERT_EQUALS( ws->readY(0)[0], 4 ); + TS_ASSERT_EQUALS( ws->readY(1)[0], 6 ); + + TS_ASSERT_EQUALS( ws->readX(0)[1], 1 ); + TS_ASSERT_EQUALS( ws->readX(1)[1], 1 ); + + TS_ASSERT_DELTA( ws->readE(0)[2], 4.243, 0.001); + TS_ASSERT_DELTA( ws->readE(1)[2], 5.196, 0.001); + + TS_ASSERT_EQUALS( ws->getSpectrum(0)->getSpectrumNo(), 1); + TS_ASSERT_EQUALS( ws->getSpectrum(1)->getSpectrumNo(), 2); + + std::set d1; + d1.insert(0); d1.insert(1); + TS_ASSERT_EQUALS( ws->getSpectrum(0)->getDetectorIDs(), d1 ); + + std::set d2; + d2.insert(2); d2.insert(3); d2.insert(4); + TS_ASSERT_EQUALS( ws->getSpectrum(1)->getDetectorIDs(), d2 ); } // Remove workspace from the data service. @@ -77,7 +99,7 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite row1 << "Group" << "1" << group1; std::vector group2; - group2.push_back(2); group2.push_back(2); group2.push_back(3); + group2.push_back(2); group2.push_back(3); group2.push_back(4); TableRow row2 = t->appendRow(); row2 << "Group" << "2" << group2; From 8b104b6353c3e927723535f80a078c330ef07ec1 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 6 Dec 2013 11:35:30 +0000 Subject: [PATCH 086/403] Refs #8550. Use new functionality in PlotAsymmetryByLogValue. --- .../src/PlotAsymmetryByLogValue.cpp | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/PlotAsymmetryByLogValue.cpp b/Code/Mantid/Framework/Algorithms/src/PlotAsymmetryByLogValue.cpp index 80b1207b0611..eac0e5c0a88b 100644 --- a/Code/Mantid/Framework/Algorithms/src/PlotAsymmetryByLogValue.cpp +++ b/Code/Mantid/Framework/Algorithms/src/PlotAsymmetryByLogValue.cpp @@ -270,21 +270,31 @@ namespace Mantid if(m_autogroup) { - IAlgorithm_sptr applyGrouping = createChildAlgorithm("ApplyGroupingFromMuonNexus"); - applyGrouping->initialize(); - applyGrouping->setProperty("InputWorkspace", loadedWs); - applyGrouping->setPropertyValue("Filename", fn.str()); + Workspace_sptr loadedDetGrouping = load->getProperty("DetectorGroupingTable"); + + if ( ! loadedDetGrouping ) + throw std::runtime_error("No grouping info in the file.\n\nPlease specify grouping manually"); + + // Could be groups of workspaces, so need to work with ADS + ScopedWorkspace inWS(loadedWs); + ScopedWorkspace grouping(loadedDetGrouping); + ScopedWorkspace outWS; try { + IAlgorithm_sptr applyGrouping = createChildAlgorithm("MuonGroupDetectors", -1, -1, false); + applyGrouping->initialize(); + applyGrouping->setPropertyValue( "InputWorkspace", inWS.name() ); + applyGrouping->setPropertyValue( "DetectorGroupingTable", grouping.name() ); + applyGrouping->setPropertyValue( "OutputWorkspace", outWS.name() ); applyGrouping->execute(); + + loadedWs = outWS.retrieve(); } catch(...) { - throw std::runtime_error("Unable to auto-group the workspace. Please specify grouping manually"); + throw std::runtime_error("Unable to group detectors.\n\nPlease specify grouping manually."); } - - loadedWs = applyGrouping->getProperty("OutputWorkspace"); } WorkspaceGroup_sptr loadedGroup = boost::dynamic_pointer_cast(loadedWs); From 94586525f2323cff119ce4efcb8f76a03dc14445 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Fri, 6 Dec 2013 11:37:10 +0000 Subject: [PATCH 087/403] Use AutoPtr in LoadParameterFile.cpp re #8546 Signed-off-by: Karl Palmen --- .../Framework/DataHandling/src/LoadParameterFile.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index 6ec3424405a2..760a42894900 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -35,6 +35,7 @@ This algorithm allows instrument parameters to be specified in a separate file f #include #include #include +#include #include #include #include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" @@ -46,6 +47,7 @@ using Poco::XML::Node; using Poco::XML::NodeList; using Poco::XML::NodeIterator; using Poco::XML::NodeFilter; +using Poco::XML::AutoPtr; using Mantid::Geometry::InstrumentDefinitionParser; @@ -112,7 +114,7 @@ void LoadParameterFile::execManually(bool useString, std::string filename, std:: // Set up the DOM parser and parse xml file DOMParser pParser; - Document* pDoc; + AutoPtr pDoc; try { pDoc = pParser.parse(filename); @@ -127,7 +129,7 @@ void LoadParameterFile::execManually(bool useString, std::string filename, std:: } // Get pointer to root element - Element* pRootElem = pDoc->documentElement(); + AutoPtr pRootElem = pDoc->documentElement(); if ( !pRootElem->hasChildNodes() ) { throw Kernel::Exception::InstrumentDefinitionError("No root element in XML Parameter file", filename); @@ -140,7 +142,6 @@ void LoadParameterFile::execManually(bool useString, std::string filename, std:: // populate parameter map of workspace localWorkspace->populateInstrumentParameters(); - pDoc->release(); } } // namespace DataHandling From 7dcd2cca229680e0e3ac4f1cbbad303f4f33ec4d Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 6 Dec 2013 12:04:00 +0000 Subject: [PATCH 088/403] Refs #8550. Remove unused ApplyGroupingFromMuonNexus. --- .../Framework/DataHandling/CMakeLists.txt | 9 +- .../ApplyGroupingFromMuonNexus.h | 62 ----- .../src/ApplyGroupingFromMuonNexus.cpp | 211 ------------------ .../test/ApplyGroupingFromMuonNexusTest.h | 152 ------------- 4 files changed, 3 insertions(+), 431 deletions(-) delete mode 100644 Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ApplyGroupingFromMuonNexus.h delete mode 100644 Code/Mantid/Framework/DataHandling/src/ApplyGroupingFromMuonNexus.cpp delete mode 100644 Code/Mantid/Framework/DataHandling/test/ApplyGroupingFromMuonNexusTest.h diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 24f39e04ac69..a6d2877b0070 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -1,6 +1,5 @@ set ( SRC_FILES src/AppendGeometryToSNSNexus.cpp - src/ApplyGroupingFromMuonNexus.cpp src/CompressEvents.cpp src/ConvertFullprofToXML.cpp src/CreateChopperModel.cpp @@ -131,7 +130,6 @@ set ( SRC_FILES set ( INC_FILES inc/MantidDataHandling/AppendGeometryToSNSNexus.h - inc/MantidDataHandling/ApplyGroupingFromMuonNexus.h inc/MantidDataHandling/CompressEvents.h inc/MantidDataHandling/ConvertFullprofToXML.h inc/MantidDataHandling/CreateChopperModel.h @@ -262,7 +260,6 @@ set ( INC_FILES set ( TEST_FILES AppendGeometryToSNSNexusTest.h - ApplyGroupingFromMuonNexusTest.h CompressEventsTest.h ConvertFullprofToXMLTest.h CreateChopperModelTest.h @@ -279,8 +276,8 @@ set ( TEST_FILES GroupDetectorsTest.h ISISDataArchiveTest.h InstrumentRayTracerTest.h - LoadAsciiTest.h LoadAscii2Test.h + LoadAsciiTest.h LoadCalFileTest.h LoadCanSAS1dTest.h LoadDaveGrpTest.h @@ -304,8 +301,8 @@ set ( TEST_FILES LoadLogTest.h LoadMappingTableTest.h LoadMaskTest.h - LoadMcStasTest.h LoadMcStasNexusTest.h + LoadMcStasTest.h LoadMuonLogTest.h LoadMuonNexus1Test.h LoadMuonNexus2Test.h @@ -348,8 +345,8 @@ set ( TEST_FILES RotateInstrumentComponentTest.h SNSDataArchiveICAT2Test.h SNSDataArchiveTest.h - SaveAsciiTest.h SaveAscii2Test.h + SaveAsciiTest.h SaveCSVTest.h SaveCalFileTest.h SaveCanSAS1dTest.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ApplyGroupingFromMuonNexus.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ApplyGroupingFromMuonNexus.h deleted file mode 100644 index 4022af0d42df..000000000000 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ApplyGroupingFromMuonNexus.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef MANTID_DATAHANDLING_APPLYGROUPINGFROMMUONNEXUS_H_ -#define MANTID_DATAHANDLING_APPLYGROUPINGFROMMUONNEXUS_H_ - -#include "MantidKernel/System.h" -#include "MantidAPI/Algorithm.h" -#include "MantidDataObjects/Workspace2D.h" - -namespace Mantid -{ -namespace DataHandling -{ - using namespace DataObjects; - /** - Applies grouping information from Muon Nexus file to the workspace. - - @author Arturs Bekasovs - @date 10/10/2013 - - Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - - This file is part of Mantid. - - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - File change history is stored at: - Code Documentation is available at: - */ - class DLLExport ApplyGroupingFromMuonNexus : public API::Algorithm - { - public: - virtual const std::string name() const; - virtual int version() const; - virtual const std::string category() const; - - private: - virtual void initDocs(); - void init(); - void exec(); - - bool checkGroups(); - bool processGroups(); - - /// Applies grouping to a given workspace - Workspace2D_sptr applyGrouping(const std::vector& detectorGrouping, Workspace2D_const_sptr inputWs); - }; - - -} // namespace DataHandling -} // namespace Mantid - -#endif /* MANTID_DATAHANDLING_APPLYGROUPINGFROMMUONNEXUS_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/DataHandling/src/ApplyGroupingFromMuonNexus.cpp b/Code/Mantid/Framework/DataHandling/src/ApplyGroupingFromMuonNexus.cpp deleted file mode 100644 index 56dd105da425..000000000000 --- a/Code/Mantid/Framework/DataHandling/src/ApplyGroupingFromMuonNexus.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/*WIKI* -Given a workspace or workspace group and Muon Nexus file, retrieves grouping information stored in the file and groups input workspace accordingly. -*WIKI*/ - -#include "MantidAPI/FileProperty.h" -#include "MantidDataHandling/ApplyGroupingFromMuonNexus.h" -#include "MantidDataObjects/Workspace2D.h" - -#include -#include - -namespace Mantid -{ -namespace DataHandling -{ - using namespace Kernel; - using namespace API; - using namespace DataObjects; - - // Register the algorithm into the AlgorithmFactory - DECLARE_ALGORITHM(ApplyGroupingFromMuonNexus) - - //---------------------------------------------------------------------------------------------- - /// Algorithm's name for identification. @see Algorithm::name - const std::string ApplyGroupingFromMuonNexus::name() const { return "ApplyGroupingFromMuonNexus";}; - - /// Algorithm's version for identification. @see Algorithm::version - int ApplyGroupingFromMuonNexus::version() const { return 1;}; - - /// Algorithm's category for identification. @see Algorithm::category - const std::string ApplyGroupingFromMuonNexus::category() const { return "DataHandling\\Nexus;Muon";} - - //---------------------------------------------------------------------------------------------- - /// Sets documentation strings for this algorithm - void ApplyGroupingFromMuonNexus::initDocs() - { - this->setWikiSummary("Applies grouping information from Muon Nexus file to the [[workspace]]."); - this->setOptionalMessage("Applies grouping information from Muon Nexus file to the workspace."); - } - - //---------------------------------------------------------------------------------------------- - /** Initialize the algorithm's properties. - */ - void ApplyGroupingFromMuonNexus::init() - { - declareProperty(new WorkspaceProperty("InputWorkspace","",Direction::Input), - "Workspace to group."); - - declareProperty(new FileProperty("Filename", "", FileProperty::Load, ".nxs"), - "Nexus file to load grouping information from." ); - - declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), - "Workspace with grouping applied."); - } - - //---------------------------------------------------------------------------------------------- - /** Execute the algorithm. - */ - void ApplyGroupingFromMuonNexus::exec() - { - // Load grouping information from the Nexus file - std::string filename = getPropertyValue("Filename"); - - NeXus::File handle(filename, NXACC_READ); - - handle.openData("grouping"); // TODO: what if no? - size_t numDetectors = static_cast(handle.getInfo().dims[0]); - - boost::scoped_array detectorGrouping(new int[numDetectors]); - - handle.getData(detectorGrouping.get()); - handle.closeData(); - - Workspace_sptr inputWs = getProperty("InputWorkspace"); - - std::string outputWsName = getPropertyValue("OutputWorkspace"); - - if(Workspace2D_const_sptr inputWs2D = boost::dynamic_pointer_cast(inputWs)) - { - std::vector grouping(detectorGrouping.get(), detectorGrouping.get() + numDetectors); - - Workspace2D_sptr outputWs = applyGrouping(grouping, inputWs2D); - setProperty("OutputWorkspace", outputWs); - } - else if(WorkspaceGroup_const_sptr inputGroup = boost::dynamic_pointer_cast(inputWs)) - { - WorkspaceGroup_sptr outputWsGroup = WorkspaceGroup_sptr(new WorkspaceGroup); - - int currentOffset = 0; - - for(size_t i = 0; i < inputGroup->size(); i++) - { - Workspace2D_const_sptr memberWs2D = boost::dynamic_pointer_cast(inputGroup->getItem(i)); - - if(!memberWs2D) - throw std::invalid_argument("Specified group contains a workspace which is not a Workspace2D"); - - int* from = detectorGrouping.get() + currentOffset; - int* to = from + memberWs2D->getNumberHistograms(); - - std::vector grouping(from, to); - - Workspace2D_sptr outputWs = applyGrouping(grouping, memberWs2D); - outputWsGroup->addWorkspace(outputWs); - - std::string suffix = "_" + boost::lexical_cast(i + 1); - std::string outWsPropName = "OutputWorkspace" + suffix; - - declareProperty(new WorkspaceProperty(outWsPropName, outputWsName + suffix, Direction::Output)); - setProperty(outWsPropName, boost::dynamic_pointer_cast(outputWs)); - } - - setProperty("OutputWorkspace",boost::dynamic_pointer_cast(outputWsGroup)); - } - else - { - throw std::invalid_argument("Should be whether a Workspace2D or WorkspaceGroup"); - } - } - - bool ApplyGroupingFromMuonNexus::checkGroups() - { - return false; - } - - bool ApplyGroupingFromMuonNexus::processGroups() - { - return true; - } - - /** - * Applies grouping to a given workspace. - * - * @param detectorGrouping :: Grouping info, where index is detector id and value is group number - * @param inputWs :: Workspace to group - * @return Workspace with grouped detectors. All the unrelated parameters are left as in inputWs. - */ - Workspace2D_sptr ApplyGroupingFromMuonNexus::applyGrouping(const std::vector& detectorGrouping, - Workspace2D_const_sptr inputWs) - { - if(inputWs->getNumberHistograms() != detectorGrouping.size()) - throw std::invalid_argument("Invalid number of detectors."); - - std::map< int, std::vector > groups; - std::vector ungrouped; - - for (size_t i = 0; i < detectorGrouping.size(); ++i) - { - int group = detectorGrouping[i]; - - if(group == 0) - ungrouped.push_back(static_cast(i)); - else - groups[group].push_back(static_cast(i)); - } - - if(groups.empty()) - throw std::invalid_argument("No groups specified in the input file"); - - // Number of the last group we've met - int lastGroup = groups.rbegin()->first; - - // Add ungrouped detectors to separate groups - for(size_t i = 0; i < ungrouped.size(); i++) - groups[++lastGroup].push_back(ungrouped[i]); - - Workspace2D_sptr groupedWs = boost::dynamic_pointer_cast( - WorkspaceFactory::Instance().create(inputWs, groups.size(), inputWs->dataX(0).size(), inputWs->blocksize())); - - // Compile the groups - int groupIndex = 0; - for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) - { - std::vector& detectors = groupIt->second; - - for(auto detIt = detectors.begin(); detIt != detectors.end(); detIt++) - { - for(size_t j = 0; j < inputWs->blocksize(); j++) - { - // Sum the y values - groupedWs->dataY(groupIndex)[j] += inputWs->dataY(*detIt)[j]; - - // Sum the errors in quadrature - groupedWs->dataE(groupIndex)[j] = - sqrt(pow(groupedWs->dataE(groupIndex)[j], 2) + pow(inputWs->dataE(*detIt)[j], 2)); - } - - groupedWs->getSpectrum(groupIndex)->addDetectorID(static_cast(*detIt)); - } - - // Using the last detector X values for consistency with LoadMuonNexus1 AutoGroup behavior - groupedWs->dataX(groupIndex) = inputWs->dataX(detectors.back()); - - groupedWs->getSpectrum(groupIndex)->setSpectrumNo(groupIndex+1); - - g_log.information() << "Group " << groupIt->first << ": " - << Kernel::Strings::join(detectors.begin(), detectors.end(), ", ") - << std::endl; - - groupIndex++; - } - - // Set Y axis values - for(size_t i = 0; i < groupedWs->getNumberHistograms(); i++) - groupedWs->getAxis(1)->setValue(i, static_cast(i + 1)); - - return groupedWs; - } - -} // namespace DataHandling -} // namespace Mantid \ No newline at end of file diff --git a/Code/Mantid/Framework/DataHandling/test/ApplyGroupingFromMuonNexusTest.h b/Code/Mantid/Framework/DataHandling/test/ApplyGroupingFromMuonNexusTest.h deleted file mode 100644 index 813db4e3ac01..000000000000 --- a/Code/Mantid/Framework/DataHandling/test/ApplyGroupingFromMuonNexusTest.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef MANTID_DATAHANDLING_ApplyGroupingFromMuonNexusTEST_H_ -#define MANTID_DATAHANDLING_ApplyGroupingFromMuonNexusTEST_H_ - -#include - -#include "MantidAPI/AnalysisDataService.h" -#include "MantidDataHandling/ApplyGroupingFromMuonNexus.h" -#include "MantidDataHandling/LoadMuonNexus1.h" -#include "MantidDataObjects/Workspace2D.h" -#include - -#include // std::accumulate - -using namespace Mantid::API; -using namespace Mantid::Kernel; -using namespace Mantid::DataHandling; -using namespace Mantid::DataObjects; - -class ApplyGroupingFromMuonNexusTest : public CxxTest::TestSuite -{ -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static ApplyGroupingFromMuonNexusTest *createSuite() { return new ApplyGroupingFromMuonNexusTest(); } - static void destroySuite( ApplyGroupingFromMuonNexusTest *suite ) { delete suite; } - - - void test_init() - { - ApplyGroupingFromMuonNexus alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - } - - void test_execSingle() - { - AnalysisDataService::Instance().clear(); - - // Name of the output workspace. - std::string loadedWsName("ApplyGroupingFromMuonNexusTest_LoadedWS"); - std::string outWsName("ApplyGroupingFromMuonNexusTest_OutputWS"); - std::string dataFileName("emu00006473.nxs"); - - // Load the data we will group - LoadMuonNexus1 loadAlg; - loadAlg.initialize(); - loadAlg.setPropertyValue("Filename", dataFileName); - loadAlg.setPropertyValue("OutputWorkspace", loadedWsName); - loadAlg.execute(); - - ApplyGroupingFromMuonNexus alg; - alg.initialize(); - - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", loadedWsName) ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", dataFileName) ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWsName) ); - TS_ASSERT_THROWS_NOTHING( alg.execute(); ); - TS_ASSERT( alg.isExecuted() ); - - // Retrieve the workspace from data service. - Workspace2D_sptr ws; - TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWsName) ); - TS_ASSERT(ws); - - TS_ASSERT_EQUALS(ws->getNumberHistograms(), 2); - TS_ASSERT_EQUALS(ws->readY(0).size(), 2000); - - TS_ASSERT_EQUALS(ws->readX(0), ws->readX(1)); - TS_ASSERT_DELTA(std::accumulate(ws->readX(0).begin(), ws->readX(0).end(), 0.0), 31507.736, 0.001); - - TS_ASSERT_EQUALS(std::accumulate(ws->readY(0).begin(), ws->readY(0).end(), 0), 32571161); - TS_ASSERT_EQUALS(std::accumulate(ws->readY(1).begin(), ws->readY(1).end(), 0), 18184711); - - TS_ASSERT_DELTA(std::accumulate(ws->readE(0).begin(), ws->readE(0).end(), 0.0), 133292.1, 0.1); - TS_ASSERT_DELTA(std::accumulate(ws->readE(1).begin(), ws->readE(1).end(), 0.0), 101157.1, 0.1); - - AnalysisDataService::Instance().clear(); - } - - void test_execGroup() - { - AnalysisDataService::Instance().clear(); - - // Name of the output workspace. - std::string loadedWsName("ApplyGroupingFromMuonNexusTest_LoadedWS"); - std::string outWsName("ApplyGroupingFromMuonNexusTest_OutputWS"); - std::string dataFileName("MUSR00015189.nxs"); - - // Load the data we will group - LoadMuonNexus1 loadAlg; - loadAlg.initialize(); - loadAlg.setPropertyValue("Filename", dataFileName); - loadAlg.setPropertyValue("OutputWorkspace", loadedWsName); - loadAlg.execute(); - - ApplyGroupingFromMuonNexus alg; - alg.initialize(); - - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", loadedWsName) ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", dataFileName) ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWsName) ); - TS_ASSERT_THROWS_NOTHING( alg.execute(); ); - TS_ASSERT( alg.isExecuted() ); - - // Retrieve the workspace from data service. - WorkspaceGroup_sptr ws; - TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWsName) ); - TS_ASSERT(ws); - - TS_ASSERT_EQUALS(ws->size(), 2); - - // Check the first workspace in group ---------------------------------------------------------- - - Workspace2D_sptr ws1 = boost::dynamic_pointer_cast(ws->getItem(0)); - TS_ASSERT(ws1); - - TS_ASSERT_EQUALS(ws1->getNumberHistograms(), 2); - TS_ASSERT_EQUALS(ws1->readY(0).size(), 2000); - - TS_ASSERT_EQUALS(ws1->readX(0), ws1->readX(1)); - TS_ASSERT_DELTA(std::accumulate(ws1->readX(0).begin(), ws1->readX(0).end(), 0.0), 30915.451, 0.001); - - TS_ASSERT_EQUALS(std::accumulate(ws1->readY(0).begin(), ws1->readY(0).end(), 0), 355655); - TS_ASSERT_EQUALS(std::accumulate(ws1->readY(1).begin(), ws1->readY(1).end(), 0), 262852); - - TS_ASSERT_DELTA(std::accumulate(ws1->readE(0).begin(), ws1->readE(0).end(), 0.0), 14046.9, 0.1); - TS_ASSERT_DELTA(std::accumulate(ws1->readE(1).begin(), ws1->readE(1).end(), 0.0), 12079.8, 0.1); - - // Check the second workspace in group --------------------------------------------------------- - - Workspace2D_sptr ws2 = boost::dynamic_pointer_cast(ws->getItem(1)); - TS_ASSERT(ws2); - - TS_ASSERT_EQUALS(ws2->getNumberHistograms(), 2); - TS_ASSERT_EQUALS(ws2->readY(0).size(), 2000); - - TS_ASSERT_EQUALS(ws1->readX(0), ws2->readX(0)); - TS_ASSERT_EQUALS(ws2->readX(0), ws2->readX(1)); - - TS_ASSERT_EQUALS(std::accumulate(ws2->readY(0).begin(), ws2->readY(0).end(), 0), 359076); - TS_ASSERT_EQUALS(std::accumulate(ws2->readY(1).begin(), ws2->readY(1).end(), 0), 258629); - - TS_ASSERT_DELTA(std::accumulate(ws2->readE(0).begin(), ws2->readE(0).end(), 0.0), 14054.2, 0.1); - TS_ASSERT_DELTA(std::accumulate(ws2->readE(1).begin(), ws2->readE(1).end(), 0.0), 11976.0, 0.1); - - AnalysisDataService::Instance().clear(); - } - -}; - - -#endif /* MANTID_DATAHANDLING_ApplyGroupingFromMuonNexusTEST_H_ */ From 355be9efe880fcc83334d7bf30f356f0db497fe2 Mon Sep 17 00:00:00 2001 From: Ricardo Leal Date: Fri, 6 Dec 2013 13:46:34 +0100 Subject: [PATCH 089/403] Re #8526 Cleaning up before closing the ticket. --- .../Framework/DataHandling/src/LoadILL.cpp | 101 +++++++++--------- .../Framework/DataHandling/test/LoadILLTest.h | 40 +++---- 2 files changed, 72 insertions(+), 69 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp b/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp index df203d840d8f..1e7ac2758a10 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadILL.cpp @@ -9,8 +9,6 @@ The property FilenameVanadium is optional. If it is present the EPP will be load To date this algorithm only supports: IN4, IN5 and IN6 - - *WIKI*/ //--------------------------------------------------- // Includes @@ -122,36 +120,6 @@ namespace Mantid } - /** - * - */ - int LoadILL::validateVanadium(const std::string &filenameVanadium) { - NeXus::NXRoot vanaRoot(filenameVanadium); - NXEntry vanaFirstEntry = vanaRoot.openFirstEntry(); - - double wavelength = vanaFirstEntry.getFloat("wavelength"); - - // read in the data - NXData dataGroup = vanaFirstEntry.openNXData("data"); - NXInt data = dataGroup.openIntData(); - - size_t numberOfTubes = static_cast(data.dim0()); - size_t numberOfPixelsPerTube = static_cast(data.dim1()); - size_t numberOfChannels = static_cast(data.dim2()); - - if (wavelength != m_wavelength || numberOfTubes != m_numberOfTubes - || numberOfPixelsPerTube != m_numberOfPixelsPerTube - || numberOfChannels != m_numberOfChannels) { - throw std::runtime_error( - "Vanadium and Data were not collected in the same conditions!"); - } - - data.load(); - int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition( - data); - return calculatedDetectorElasticPeakPosition; - } - /** * Execute the algorithm @@ -467,6 +435,43 @@ namespace Mantid return calculatedDetectorElasticPeakPosition; } + + /** + * It loads the vanadium nexus file and cross checks it against the + * data file already loaded (same wavelength and same instrument configuration). + * If matches looks for the elastic peak in the vanadium file and returns + * it position. + * + * @param filenameVanadium :: The path for the vanadium nexus file. + * @return The elastic peak position inside the tof channels. + */ + int LoadILL::validateVanadium(const std::string &filenameVanadium) { + NeXus::NXRoot vanaRoot(filenameVanadium); + NXEntry vanaFirstEntry = vanaRoot.openFirstEntry(); + + double wavelength = vanaFirstEntry.getFloat("wavelength"); + + // read in the data + NXData dataGroup = vanaFirstEntry.openNXData("data"); + NXInt data = dataGroup.openIntData(); + + size_t numberOfTubes = static_cast(data.dim0()); + size_t numberOfPixelsPerTube = static_cast(data.dim1()); + size_t numberOfChannels = static_cast(data.dim2()); + + if (wavelength != m_wavelength || numberOfTubes != m_numberOfTubes + || numberOfPixelsPerTube != m_numberOfPixelsPerTube + || numberOfChannels != m_numberOfChannels) { + throw std::runtime_error( + "Vanadium and Data were not collected in the same conditions!"); + } + + data.load(); + int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition( + data); + return calculatedDetectorElasticPeakPosition; + } + /** * Loads all the spectra into the workspace, including that from the monitor * @@ -550,29 +555,23 @@ namespace Mantid /** * Run the Child Algorithm LoadInstrument. */ - void LoadILL::runLoadInstrument() - { + void LoadILL::runLoadInstrument() { - IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); - - // Now execute the Child Algorithm. Catch and log any error, but don't stop. - try - { - - // TODO: depending on the m_numberOfPixelsPerTube we might need to load a different IDF - - loadInst->setPropertyValue("InstrumentName", m_instrumentName); - loadInst->setProperty("Workspace", - m_localWorkspace); - loadInst->execute(); - } catch (...) - { - g_log.information("Cannot load the instrument definition."); - } - } + IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); + // Now execute the Child Algorithm. Catch and log any error, but don't stop. + try { + // TODO: depending on the m_numberOfPixelsPerTube we might need to load a different IDF + loadInst->setPropertyValue("InstrumentName", m_instrumentName); + loadInst->setProperty("Workspace", + m_localWorkspace); + loadInst->execute(); + } catch (...) { + g_log.information("Cannot load the instrument definition."); + } + } diff --git a/Code/Mantid/Framework/DataHandling/test/LoadILLTest.h b/Code/Mantid/Framework/DataHandling/test/LoadILLTest.h index 5c1ae4558c38..17de7adb578b 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadILLTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadILLTest.h @@ -17,8 +17,7 @@ class LoadILLTest: public CxxTest::TestSuite static void destroySuite( LoadILLTest *suite ) { delete suite; } LoadILLTest() : - m_testFile("ILLIN5_104007.nxs") - { + m_dataFile("ILLIN5_104007.nxs") { } void testName() { @@ -37,35 +36,32 @@ class LoadILLTest: public CxxTest::TestSuite TS_ASSERT( loader.isInitialized()); } -// void testFileCheck() { -// std::cerr << loader.fileCheck(testFile); -// } - - void testExec() { + /* + * This test only loads the Sample Data + * The elastic peak is obtained on the fly from the sample data. + */ + void testExecJustSample() { LoadILL loader; loader.initialize(); - loader.setPropertyValue("Filename", m_testFile); + loader.setPropertyValue("Filename", m_dataFile); std::string outputSpace = "LoadILLTest_out"; loader.setPropertyValue("OutputWorkspace", outputSpace); TS_ASSERT_THROWS_NOTHING( loader.execute()); - // test workspace, copied from LoadMuonNexusTest.h - MatrixWorkspace_sptr output; - - (output = AnalysisDataService::Instance().retrieveWS( - outputSpace)); - MatrixWorkspace_sptr output2D = boost::dynamic_pointer_cast< - MatrixWorkspace>(output); + MatrixWorkspace_sptr output = AnalysisDataService::Instance().retrieveWS(outputSpace); + MatrixWorkspace_sptr output2D = boost::dynamic_pointer_cast(output); TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 98304); AnalysisDataService::Instance().clear(); } + + private: + std::string m_dataFile; - std::string m_testFile; }; //------------------------------------------------------------------------------ @@ -74,13 +70,21 @@ class LoadILLTest: public CxxTest::TestSuite class LoadILLTestPerformance: public CxxTest::TestSuite { public: + LoadILLTestPerformance() : + m_dataFile("ILLIN5_104007.nxs"){ + } + void testDefaultLoad() { Mantid::DataHandling::LoadILL loader; loader.initialize(); - loader.setPropertyValue("Filename", "ILLIN5_104007.nxs"); + loader.setPropertyValue("Filename", m_dataFile); loader.setPropertyValue("OutputWorkspace", "ws"); - TS_ASSERT( loader.execute()); + TS_ASSERT(loader.execute()); } + +private: + std::string m_dataFile; + }; #endif /*LoadILLTEST_H_*/ From 86a24a86f8cabf34c3627daf56017a6210e72451 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Fri, 6 Dec 2013 16:10:19 +0000 Subject: [PATCH 090/403] Extend parameterXML code (still inactive) re #8546 Signed-off-by: Karl Palmen --- .../DataHandling/src/LoadParameterFile.cpp | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index 760a42894900..805a32141161 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -115,17 +115,35 @@ void LoadParameterFile::execManually(bool useString, std::string filename, std:: // Set up the DOM parser and parse xml file DOMParser pParser; AutoPtr pDoc; - try - { - pDoc = pParser.parse(filename); - } - catch(Poco::Exception& exc) - { - throw Kernel::Exception::FileError(exc.displayText() + ". Unable to parse File:", filename); - } - catch(...) + + if(useString){ + try + { + pDoc = pParser.parseString(parameterXML); + } + catch(Poco::Exception& exc) + { + throw Kernel::Exception::FileError (exc.displayText() + ". Unable to parse parameter XML string","ParameterXML"); + } + catch(...) + { + throw Kernel::Exception::FileError("Unable to parse parameter XML string","ParameterXML"); + } + } + else { - throw Kernel::Exception::FileError("Unable to parse File:" , filename); + try + { + pDoc = pParser.parse(filename); + } + catch(Poco::Exception& exc) + { + throw Kernel::Exception::FileError(exc.displayText() + ". Unable to parse File:", filename); + } + catch(...) + { + throw Kernel::Exception::FileError("Unable to parse File:" , filename); + } } // Get pointer to root element From 8179d5b8746426b5064ee710492cb9ec5cd640ee Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Fri, 6 Dec 2013 14:35:28 -0500 Subject: [PATCH 091/403] Refs #8251 Everything in file but width and height for WISH --- .../Crystal/inc/MantidCrystal/SaveIsawPeaks.h | 5 +- .../Framework/Crystal/src/SaveIsawPeaks.cpp | 85 ++++++++++++++++--- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveIsawPeaks.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveIsawPeaks.h index ebf119811442..a591ab07cba2 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveIsawPeaks.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveIsawPeaks.h @@ -34,7 +34,10 @@ namespace Crystal void init(); /// Run the algorithm void exec(); - + /// find position for rectangular and non-rectangular + Kernel::V3D findPixelPos(std::string bankName, int col, int row); + void sizeBanks(std::string bankName, int& NCOLS, int& NROWS, double& xsize, double& ysize); + Geometry::Instrument_const_sptr inst; }; diff --git a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp index 60f62816606f..0d712a29f087 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp @@ -117,7 +117,8 @@ namespace Crystal // Save the "bank" part once to check whether it really is a bank if( bankPart == "?") bankPart = bankName.substr(0,4); // Take out the "bank" part of the bank name and convert to an int - bankName = bankName.substr(4, bankName.size()-4); + if( bankPart == "bank")bankName = bankName.substr(4, bankName.size()-4); + else if( bankPart == "WISH")bankName = bankName.substr(9, bankName.size()-9); Strings::convert(bankName, bank); // Save in the map @@ -126,10 +127,10 @@ namespace Crystal uniqueBanks.insert(bank); } - Instrument_const_sptr inst = ws->getInstrument(); + inst = ws->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace. Cannot save peaks file."); - if( bankPart != "bank" && bankPart != "?" ) { + if( bankPart != "bank" && bankPart != "WISH" && bankPart != "?" ) { std::ostringstream mess; mess << "Detector module of type " << bankPart << " not supported in ISAWPeaks. Cannot save peaks file"; throw std::runtime_error( mess.str() ); } @@ -180,10 +181,12 @@ namespace Crystal // Build up the bank name int bank = *it; std::ostringstream mess; - mess << "bank" << bank; + if( bankPart == "bank")mess << "bank" << bank; + else if( bankPart == "WISH")mess << "WISHpanel0" << bank; + std::string bankName = mess.str(); // Retrieve it - RectangularDetector_const_sptr det = boost::dynamic_pointer_cast(inst->getComponentByName(bankName)); + boost::shared_ptr det = inst->getComponentByName(bankName); if (det) { // Center of the detector @@ -192,19 +195,22 @@ namespace Crystal double detd = (center - inst->getSample()->getPos()).norm(); // Base unit vector (along the horizontal, X axis) - V3D base = det->getAtXY(det->xpixels()-1,0)->getPos() - det->getAtXY(0,0)->getPos(); + V3D base = findPixelPos(bankName,1,0) - findPixelPos(bankName,0,0); base.normalize(); // Up unit vector (along the vertical, Y axis) - V3D up = det->getAtXY(0,det->ypixels()-1)->getPos() - det->getAtXY(0,0)->getPos(); + V3D up = findPixelPos(bankName,0,1) - findPixelPos(bankName,0,0); up.normalize(); + int NCOLS, NROWS; + double xsize, ysize; + sizeBanks(bankName, NCOLS, NROWS, xsize, ysize); // Write the line out << "5 " << std::setw(6) << std::right << bank << " " - << std::setw(6) << std::right << det->xpixels() << " " - << std::setw(6) << std::right << det->ypixels() << " " - << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->xsize() << " " - << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->ysize() << " " + << std::setw(6) << std::right << NCOLS << " " + << std::setw(6) << std::right << NROWS << " " + << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*xsize << " " + << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*ysize << " " << " 0.2000 " << std::setw(6) << std::right << std::fixed << std::setprecision(2) << 100.0*detd << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.X() << " " @@ -376,8 +382,61 @@ namespace Crystal } - - + V3D SaveIsawPeaks::findPixelPos(std::string bankName, int col, int row) + { + boost::shared_ptr parent = inst->getComponentByName(bankName); + if (parent->type().compare("RectangularDetector") == 0) + { + boost::shared_ptr RDet = boost::dynamic_pointer_cast< + const RectangularDetector>(parent); + + boost::shared_ptr pixel = RDet->getAtXY(col, row); + return pixel->getPos(); + } + else + { + std::string bankName0 = bankName; + //Only works for WISH + bankName0.erase(0,4); + std::ostringstream pixelString; + pixelString << inst->getName() << "/" << bankName0 << "/" < component = inst->getComponentByName(pixelString.str()); + boost::shared_ptr pixel = boost::dynamic_pointer_cast(component); + return pixel->getPos(); + } + } + void SaveIsawPeaks::sizeBanks(std::string bankName, int& NCOLS, int& NROWS, double& xsize, double& ysize) + { + if (bankName.compare("None") == 0) return; + boost::shared_ptr parent = inst->getComponentByName(bankName); + if (parent->type().compare("RectangularDetector") == 0) + { + boost::shared_ptr RDet = boost::dynamic_pointer_cast< + const RectangularDetector>(parent); + + NCOLS = RDet->xpixels(); + NROWS = RDet->ypixels(); + xsize = RDet->xsize(); + ysize = RDet->ysize(); + } + else + { + std::vector children; + boost::shared_ptr asmb = boost::dynamic_pointer_cast(parent); + asmb->getChildren(children, false); + boost::shared_ptr asmb2 = boost::dynamic_pointer_cast(children[0]); + std::vector grandchildren; + asmb2->getChildren(grandchildren,false); + NROWS = static_cast(grandchildren.size()); + NCOLS = static_cast(children.size()); + //Geometry::IComponent_const_sptr first = children[0]; + //Geometry::IComponent_const_sptr last = children[NCOLS-1]; + //xsize = (first.getPos() - last.getPos()).norm(); + //ysize = (grandchildren[0].getPos() - grandchildren[NROWS-1].getPos()).norm(); + } + } } // namespace Mantid From a079a281305a8478a8d50441ad4ff62a64c89290 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Fri, 6 Dec 2013 17:21:15 -0500 Subject: [PATCH 092/403] Re #8573. Avoid a crash by recursing up the tree if necessary. Rather than just assuming it's the top level that's selected. --- Code/Mantid/MantidPlot/src/ConfigDialog.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/MantidPlot/src/ConfigDialog.cpp b/Code/Mantid/MantidPlot/src/ConfigDialog.cpp index b400b248f472..567357452db8 100644 --- a/Code/Mantid/MantidPlot/src/ConfigDialog.cpp +++ b/Code/Mantid/MantidPlot/src/ConfigDialog.cpp @@ -863,11 +863,18 @@ void ConfigDialog::addDialog() //Edit a program void ConfigDialog::editDialog() { - QList selectedItems = treePrograms->selectedItems(); - - std::map programKeysAndDetails = m_sendToSettings.find(selectedItems[0]->text(0).toStdString())->second; + auto firstSelectedItem = treePrograms->selectedItems()[0]; + auto selectedProgram = m_sendToSettings.find(firstSelectedItem->text(0).toStdString()); + // If the program name itself isn't initially selected, recurse up. + while ( selectedProgram == m_sendToSettings.end() ) + { + firstSelectedItem = treePrograms->itemAbove(firstSelectedItem); + // It shouldn't happen that we get to the top without finding anything, but should this happen just return + if ( firstSelectedItem == treePrograms->invisibleRootItem() ) return; + selectedProgram = m_sendToSettings.find(firstSelectedItem->text(0).toStdString()); + } - SendToProgramDialog* editProgram = new SendToProgramDialog(this, selectedItems[0]->text(0), programKeysAndDetails); + SendToProgramDialog* editProgram = new SendToProgramDialog(this, firstSelectedItem->text(0), selectedProgram->second); editProgram->setWindowTitle(tr("Edit a Program")); editProgram->setModal(true); From 577d7634e028b366168c022b265088b0ab1a0729 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Fri, 6 Dec 2013 17:22:32 -0500 Subject: [PATCH 093/403] Re #8573. Avoid a bunch of warnings while typing algorithm name. Just ask the algorithm factory if the algorithm exists rather than trying to create it on every keystroke (which as well as being expensive gave a warning log message until the algorithm name was complete). --- .../MantidPlot/src/SendToProgramDialog.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/MantidPlot/src/SendToProgramDialog.cpp b/Code/Mantid/MantidPlot/src/SendToProgramDialog.cpp index 5752e7869a3d..e6214c369f68 100644 --- a/Code/Mantid/MantidPlot/src/SendToProgramDialog.cpp +++ b/Code/Mantid/MantidPlot/src/SendToProgramDialog.cpp @@ -157,21 +157,9 @@ void SendToProgramDialog::validateTarget() */ void SendToProgramDialog::validateSaveUsing() { - validSaveUsing = true; - try - { - Mantid::API::AlgorithmManager::Instance().create(m_uiform.saveUsingText->text().toStdString() ); - } - catch(std::exception&) - { - m_uiform.validateSaveUsing->setVisible(true); - validSaveUsing = false; - } - - if (validSaveUsing == true) - { - m_uiform.validateSaveUsing->setVisible(false); - } + validSaveUsing = Mantid::API::AlgorithmFactory::Instance().exists( m_uiform.saveUsingText->text().toStdString() ); + m_uiform.validateSaveUsing->setVisible( ! validSaveUsing ); + validateAll(); } From 8308628fd4015cd41cc8b864e1684e6a92bfbf9a Mon Sep 17 00:00:00 2001 From: Roman Tolchenov Date: Mon, 9 Dec 2013 10:05:17 +0000 Subject: [PATCH 094/403] Re #8555. Test received period number to be in valid range. --- .../ISISLiveEventDataListener.h | 30 ++++++++++- .../src/ISISLiveEventDataListener.cpp | 50 +++++-------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h index ec5631ccd653..31f1de36311a 100644 --- a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h +++ b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h @@ -127,7 +127,7 @@ namespace Mantid // Initialize the event buffer void initEventBuffer(const TCPStreamEventDataSetup& setup); // Save received event data in the buffer workspace - void saveEvents(const std::vector &data, const Kernel::DateAndTime &pulseTime, const size_t period); + void saveEvents(const std::vector &data, const Kernel::DateAndTime &pulseTime, size_t period); // Set the spectra-detector map void loadSpectraMap(); // Load the instrument @@ -137,6 +137,31 @@ namespace Mantid // Get an integer array ising the IDC interface void getIntArray(const std::string& par, std::vector& arr, const size_t dim); + // receive a header and check if it's valid + template + void Receive(T buffer, const std::string& head, const std::string &msg) + { + long timeout = 0; + while( m_socket.available() < static_cast(sizeof(buffer)) ) + { + Poco::Thread::sleep(RECV_WAIT); + timeout += RECV_WAIT; + if ( timeout > RECV_TIMEOUT * 1000 ) throw std::runtime_error("Operation of receiving " + head + " timed out."); + } + m_socket.receiveBytes(&buffer, sizeof(buffer)); + if ( !buffer.isValid() ) + { + throw std::runtime_error(msg); + } + } + + // receive data that cannot be processed + template + void CollectJunk(T head) + { + m_socket.receiveBytes(junk_buffer, head.length - static_cast(sizeof(head))); + } + /// The socket communicating with the DAE Poco::Net::StreamSocket m_socket; /// Keep connection status @@ -166,6 +191,9 @@ namespace Mantid /// number of spectra int m_numberOfSpectra; + /// buffer to collect data that cannot be processed + char* junk_buffer[1000]; + /// reference to the logger class static Kernel::Logger& g_log; diff --git a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp index 3713a9101df9..6fd34e6ad5fb 100644 --- a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp +++ b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp @@ -17,6 +17,8 @@ const long RECV_TIMEOUT = 30; // Sleep time in case we need to wait for the data to become available (in milliseconds) const long RECV_WAIT = 100; +const char* PROTON_CHARGE_PROPERTY = "proton_charge"; +const char* RUN_NUMBER_PROPERTY = "run_number"; namespace Mantid { @@ -25,34 +27,6 @@ namespace LiveData DECLARE_LISTENER(ISISLiveEventDataListener) -// receive a header and check if it's valid -#define RECEIVE(buffer,msg) \ -{\ - long timeout = 0;\ - while( m_socket.available() < static_cast(sizeof(buffer)) )\ - {\ - Poco::Thread::sleep(RECV_WAIT);\ - timeout += RECV_WAIT;\ - if ( timeout > RECV_TIMEOUT * 1000 ) throw std::runtime_error("Receive operation timed out.");\ - }\ - m_socket.receiveBytes(&buffer, sizeof(buffer));\ - if ( !buffer.isValid() )\ - {\ - throw std::runtime_error(msg);\ - }\ -} - -namespace { -// buffer to collect data that cannot be processed -static char* junk_buffer[10000]; -} - -// receive data that cannot be processed -#define COLLECT_JUNK(head) m_socket.receiveBytes(junk_buffer, head.length - static_cast(sizeof(head))); - -#define PROTON_CHARGE_PROPERTY "proton_charge" -#define RUN_NUMBER_PROPERTY "run_number" - // Get a reference to the logger Kernel::Logger& ISISLiveEventDataListener::g_log = Kernel::Logger::get("ISISLiveEventDataListener"); @@ -140,11 +114,8 @@ bool ISISLiveEventDataListener::connect(const Poco::Net::SocketAddress &address) m_numberOfPeriods = getInt("NPER"); m_numberOfSpectra = getInt("NSP1"); - std::cerr << "number of periods " << m_numberOfPeriods << std::endl; - std::cerr << "number of spectra " << m_numberOfSpectra << std::endl; - TCPStreamEventDataSetup setup; - RECEIVE(setup,"Wrong version"); + Receive(setup, "Setup", "Wrong version"); m_startTime.set_from_time_t(setup.head_setup.start_time); // initialize the buffer workspace @@ -235,17 +206,17 @@ void ISISLiveEventDataListener::run() while (m_stopThread == false) { // get the header with the type of the packet - RECEIVE(events.head,"Corrupt stream - you should reconnect."); + Receive(events.head, "Events header","Corrupt stream - you should reconnect."); if ( !(events.head.type == TCPStreamEventHeader::Neutron) ) { // don't know what to do with it - stop throw std::runtime_error("Unknown packet type."); } - COLLECT_JUNK( events.head ); + CollectJunk( events.head ); // get the header with the sream size - RECEIVE(events.head_n,"Corrupt stream - you should reconnect."); - COLLECT_JUNK( events.head_n ); + Receive(events.head_n, "Neutrons header","Corrupt stream - you should reconnect."); + CollectJunk( events.head_n ); // absolute pulse (frame) time Mantid::Kernel::DateAndTime pulseTime = m_startTime + static_cast( events.head_n.frame_time_zero ); @@ -365,10 +336,15 @@ void ISISLiveEventDataListener::initEventBuffer(const TCPStreamEventDataSetup &s * Save received event data in the buffer workspace. * @param data :: A vector with events. */ -void ISISLiveEventDataListener::saveEvents(const std::vector &data, const Kernel::DateAndTime &pulseTime, const size_t period) +void ISISLiveEventDataListener::saveEvents(const std::vector &data, const Kernel::DateAndTime &pulseTime, size_t period) { Poco::ScopedLock scopedLock(m_mutex); + if ( period >= m_numberOfPeriods ) + { + period = 0; + } + for(auto it = data.begin(); it != data.end(); ++it) { Mantid::DataObjects::TofEvent event( it->time_of_flight, pulseTime ); From a5dd0cb32241d818cd05a3d0a0abb34935297aee Mon Sep 17 00:00:00 2001 From: Roman Tolchenov Date: Mon, 9 Dec 2013 10:39:24 +0000 Subject: [PATCH 095/403] Re #8555. Fixing the linux builds. --- .../LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h | 6 +++++- .../Framework/LiveData/src/ISISLiveEventDataListener.cpp | 6 +----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h index 31f1de36311a..69434c0ccc40 100644 --- a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h +++ b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/ISISLiveEventDataListener.h @@ -13,10 +13,14 @@ #include #include +// Time we'll wait on a receive call (in seconds) +const long RECV_TIMEOUT = 30; +// Sleep time in case we need to wait for the data to become available (in milliseconds) +const long RECV_WAIT = 100; + //---------------------------------------------------------------------- // Forward declarations //---------------------------------------------------------------------- - struct idc_info; typedef struct idc_info* idc_handle_t; diff --git a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp index 6fd34e6ad5fb..1d60def9e0f0 100644 --- a/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp +++ b/Code/Mantid/Framework/LiveData/src/ISISLiveEventDataListener.cpp @@ -13,10 +13,6 @@ #include "LoadDAE/idc.h" -// Time we'll wait on a receive call (in seconds) -const long RECV_TIMEOUT = 30; -// Sleep time in case we need to wait for the data to become available (in milliseconds) -const long RECV_WAIT = 100; const char* PROTON_CHARGE_PROPERTY = "proton_charge"; const char* RUN_NUMBER_PROPERTY = "run_number"; @@ -340,7 +336,7 @@ void ISISLiveEventDataListener::saveEvents(const std::vector scopedLock(m_mutex); - if ( period >= m_numberOfPeriods ) + if ( period >= static_cast(m_numberOfPeriods) ) { period = 0; } From 1c99e7bb4e75c89a019681ae94d123eba56f80a8 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 9 Dec 2013 11:34:54 +0000 Subject: [PATCH 096/403] Fix saving a WorkspaceGroup in SANSBatchMode It previously just saved the last thing in the group with the group name. Now the group is unrolled and each workspace save individually. Refs #8575 --- Code/Mantid/scripts/SANS/SANSBatchMode.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/scripts/SANS/SANSBatchMode.py b/Code/Mantid/scripts/SANS/SANSBatchMode.py index cd0962887faa..2586dd28a0ac 100644 --- a/Code/Mantid/scripts/SANS/SANSBatchMode.py +++ b/Code/Mantid/scripts/SANS/SANSBatchMode.py @@ -30,6 +30,7 @@ #Make the reduction module available from ISISCommandInterface import * from mantid.simpleapi import * +from mantid.api import WorkspaceGroup from mantid.kernel import Logger sanslog = Logger.get("SANS") import copy @@ -217,8 +218,15 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'}, file = run['output_as'] #saving if optional and doesn't happen if the result workspace is left blank. Is this feature used? if file: + save_names = [] + for n in names: + w = mtd[n] + if isinstance(w,WorkspaceGroup): + save_names.extend(w.getNames()) + else: + save_names.append(n) for algor in saveAlgs.keys(): - for workspace_name in names: + for workspace_name in save_names: #add the file extension, important when saving different types of file so they don't over-write each other ext = saveAlgs[algor] if not ext.startswith('.'): From 726d568fdacb61971d0786867346b065cd2f94f1 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 13:03:40 +0000 Subject: [PATCH 097/403] Refs #8550. Changes table structure. We don't actually need to store pairs/names/etc. This is all for GUI so that it's easier for user to select what they want to plot. When grouping we only care about which spectra goes to which group. --- .../Algorithms/src/MuonGroupDetectors.cpp | 44 +++++++------------ .../Algorithms/test/MuonGroupDetectorsTest.h | 14 ++---- .../DataHandling/src/LoadMuonNexus1.cpp | 8 ++-- .../DataHandling/test/LoadMuonNexus1Test.h | 33 +++++--------- 4 files changed, 34 insertions(+), 65 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp index 86c796e861e7..bf5b2b211cbe 100644 --- a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp @@ -76,50 +76,40 @@ namespace Algorithms { TableWorkspace_sptr table = getProperty("DetectorGroupingTable"); - // Check that table does have expected format + // Check that table does have expected format + if ( table->columnCount() != 1 ) + throw std::invalid_argument("Grouping table should have one column only"); - if ( table->columnCount() != 3 ) - throw std::invalid_argument("Detector Grouping Table should have 3 columns"); - - if ( table->getColumn(0)->type() != "str" ) - throw std::invalid_argument("Invalid type of the first column. Should be string."); - - if ( table->getColumn(1)->type() != "str" ) - throw std::invalid_argument("Invalid type of the second column. Should be string."); - - if ( table->getColumn(2)->type() != "vector_int" ) - throw std::invalid_argument("Invalid type of the third column. Should be vector of ints."); - - std::vector groupRows; // Rows with non-empty groups - groupRows.reserve(table->rowCount()); // Most of rows will be groups + if ( table->getColumn(0)->type() != "vector_int" ) + throw std::invalid_argument("Column should be of integer vector type"); + + std::vector nonEmptyRows; // Rows with non-empty groups + nonEmptyRows.reserve(table->rowCount()); // Most of rows will be non-empty // First pass to determine how many non-empty groups we have for ( size_t row = 0; row < table->rowCount(); ++row ) { - std::string& itemName = table->cell(row, 0); - std::vector& elements = table->cell< std::vector >(row, 2); - - if ( itemName == "Group" && elements.size() != 0 ) - groupRows.push_back(row); - + if ( table->cell< std::vector >(row, 0).size() != 0 ) + nonEmptyRows.push_back(row); } - if ( groupRows.size() == 0 ) + if ( nonEmptyRows.size() == 0 ) throw std::invalid_argument("Detector Grouping Table doesn't contain any non-empty groups"); MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); // Create output workspace with all the same parameters as an input one except number of histograms - MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create( inWS, groupRows.size() ); + MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create( inWS, nonEmptyRows.size() ); // Compile the groups - for ( auto groupIt = groupRows.begin(); groupIt != groupRows.end(); ++groupIt ) + for ( auto rowIt = nonEmptyRows.begin(); rowIt != nonEmptyRows.end(); ++rowIt ) { - size_t groupIndex = static_cast( std::distance(groupRows.begin(),groupIt) ); - // Not "detectors" as such, but workspace indices. For Muons there is only one detector for // workspace index in the data before grouping. - std::vector& detectors = table->cell< std::vector >(*groupIt,2); + std::vector& detectors = table->cell< std::vector >(*rowIt, 0); + + // Group index in the output workspace + size_t groupIndex = static_cast( std::distance(nonEmptyRows.begin(), rowIt) ); // We will be setting them anew outWS->getSpectrum(groupIndex)->clearDetectorIDs(); diff --git a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h index 8d1bce31171d..0cd76a890b22 100644 --- a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h @@ -89,25 +89,17 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite { auto t = boost::make_shared(); - t->addColumn("str", "ItemType"); - t->addColumn("str", "ItemName"); - t->addColumn("vector_int", "Elements"); + t->addColumn("vector_int", "Detectors"); std::vector group1; group1.push_back(0); group1.push_back(1); TableRow row1 = t->appendRow(); - row1 << "Group" << "1" << group1; + row1 << group1; std::vector group2; group2.push_back(2); group2.push_back(3); group2.push_back(4); TableRow row2 = t->appendRow(); - row2 << "Group" << "2" << group2; - - // Just to make sure groups are used only - std::vector pair; - pair.push_back(0); pair.push_back(1); - TableRow row3 = t->appendRow(); - row3 << "Pair" << "ThePair" << pair; + row2 << group2; return t; } diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 1e89a0c0f330..1c2d9e6f4079 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -621,9 +621,7 @@ namespace Mantid auto detectorGroupingTable = boost::dynamic_pointer_cast( WorkspaceFactory::Instance().createTable("TableWorkspace") ); - detectorGroupingTable->addColumn("str", "ItemType"); - detectorGroupingTable->addColumn("str", "ItemName"); - detectorGroupingTable->addColumn("vector_int", "Elements"); + detectorGroupingTable->addColumn("vector_int", "Detectors"); std::map> grouping; @@ -634,8 +632,8 @@ namespace Mantid for ( auto it = grouping.begin(); it != grouping.end(); ++it ) { - TableRow newRow = detectorGroupingTable->appendRow(); - newRow << "Group" << boost::lexical_cast(it->first) << it->second; + TableRow newRow = detectorGroupingTable->appendRow(); + newRow << it->second; } return detectorGroupingTable; diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h index cab5da8b8679..073681a385b8 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h @@ -519,26 +519,15 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite if ( detectorGrouping ) { - TS_ASSERT_EQUALS( detectorGrouping->columnCount(), 3 ); + TS_ASSERT_EQUALS( detectorGrouping->columnCount(), 1 ); TS_ASSERT_EQUALS( detectorGrouping->rowCount(), 2 ); - TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->type(), "str" ); - TS_ASSERT_EQUALS( detectorGrouping->getColumn(1)->type(), "str" ); - TS_ASSERT_EQUALS( detectorGrouping->getColumn(2)->type(), "vector_int" ); - - TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->name(), "ItemType" ); - TS_ASSERT_EQUALS( detectorGrouping->getColumn(1)->name(), "ItemName" ); - TS_ASSERT_EQUALS( detectorGrouping->getColumn(2)->name(), "Elements" ); - - TS_ASSERT_EQUALS( detectorGrouping->cell(0,0), "Group" ); - TS_ASSERT_EQUALS( detectorGrouping->cell(1,0), "Group" ); - - TS_ASSERT_EQUALS( detectorGrouping->cell(0,1), "1" ); - TS_ASSERT_EQUALS( detectorGrouping->cell(1,1), "2" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->type(), "vector_int" ); + TS_ASSERT_EQUALS( detectorGrouping->getColumn(0)->name(), "Detectors" ); std::vector e1, e2; - TS_ASSERT_THROWS_NOTHING( e1 = detectorGrouping->cell< std::vector >(0,2) ); - TS_ASSERT_THROWS_NOTHING( e2 = detectorGrouping->cell< std::vector >(1,2) ); + TS_ASSERT_THROWS_NOTHING( e1 = detectorGrouping->cell< std::vector >(0,0) ); + TS_ASSERT_THROWS_NOTHING( e2 = detectorGrouping->cell< std::vector >(1,0) ); TS_ASSERT_EQUALS( e1.size(), 16); TS_ASSERT_EQUALS( e2.size(), 16); @@ -587,12 +576,12 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite if ( table1 ) { - TS_ASSERT_EQUALS( table1->columnCount(), 3 ); + TS_ASSERT_EQUALS( table1->columnCount(), 1 ); TS_ASSERT_EQUALS( table1->rowCount(), 2 ); std::vector e1, e2; - TS_ASSERT_THROWS_NOTHING( e1 = table1->cell< std::vector >(0,2) ); - TS_ASSERT_THROWS_NOTHING( e2 = table1->cell< std::vector >(1,2) ); + TS_ASSERT_THROWS_NOTHING( e1 = table1->cell< std::vector >(0,0) ); + TS_ASSERT_THROWS_NOTHING( e2 = table1->cell< std::vector >(1,0) ); TS_ASSERT_EQUALS( e1.size(), 32); TS_ASSERT_EQUALS( e2.size(), 32); @@ -609,12 +598,12 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite if ( table2 ) { - TS_ASSERT_EQUALS( table2->columnCount(), 3 ); + TS_ASSERT_EQUALS( table2->columnCount(), 1 ); TS_ASSERT_EQUALS( table2->rowCount(), 2 ); std::vector e1, e2; - TS_ASSERT_THROWS_NOTHING( e1 = table2->cell< std::vector >(0,2) ); - TS_ASSERT_THROWS_NOTHING( e2 = table2->cell< std::vector >(1,2) ); + TS_ASSERT_THROWS_NOTHING( e1 = table2->cell< std::vector >(0,0) ); + TS_ASSERT_THROWS_NOTHING( e2 = table2->cell< std::vector >(1,0) ); TS_ASSERT_EQUALS( e1.size(), 32); TS_ASSERT_EQUALS( e2.size(), 32); From 958d00f74cba963f2f55e6941a183d94b8db76bb Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 13:06:30 +0000 Subject: [PATCH 098/403] Refs #8550. Handle zero groups better. --- .../Framework/DataHandling/src/LoadMuonNexus1.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 1c2d9e6f4079..04f357208c35 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -557,7 +557,9 @@ namespace Mantid { // Simpliest case - one grouping entry per spectra TableWorkspace_sptr table = createDetectorGroupingTable( grouping.begin(), grouping.end() ); - setProperty("DetectorGroupingTable", table); + + if ( table->rowCount() != 0 ) + setProperty("DetectorGroupingTable", table); } else { @@ -573,9 +575,15 @@ namespace Mantid for ( auto it = grouping.begin(); it != grouping.end(); it += m_numberOfSpectra ) { - tableGroup->addWorkspace( createDetectorGroupingTable(it, it + m_numberOfSpectra) ); + TableWorkspace_sptr table = createDetectorGroupingTable(it, it + m_numberOfSpectra); + + if ( table->rowCount() != 0 ) + tableGroup->addWorkspace(table); } + if ( tableGroup->size() != static_cast(m_numberOfPeriods) ) + throw Exception::FileError("Zero grouping for some of the periods", m_filename); + setProperty("DetectorGroupingTable", tableGroup); } } @@ -632,8 +640,11 @@ namespace Mantid for ( auto it = grouping.begin(); it != grouping.end(); ++it ) { + if ( it->first != 0) // Skip 0 group + { TableRow newRow = detectorGroupingTable->appendRow(); newRow << it->second; + } } return detectorGroupingTable; From a51dcb9bd5bd656235650d11e055c6e139c2e916 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Mon, 9 Dec 2013 10:23:07 -0500 Subject: [PATCH 099/403] Refs #8251 output size of banks for WISH --- .../Framework/Crystal/src/SaveIsawPeaks.cpp | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp index 0d712a29f087..e25d46fa32f2 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp @@ -366,20 +366,6 @@ namespace Crystal out.flush(); out.close(); -// //REMOVE: -// std::string line; -// std::ifstream myfile (filename.c_str()); -// if (myfile.is_open()) -// { -// while ( myfile.good() ) -// { -// getline (myfile,line); -// std::cout << line << std::endl; -// } -// myfile.close(); -// } - - } V3D SaveIsawPeaks::findPixelPos(std::string bankName, int col, int row) @@ -431,10 +417,12 @@ namespace Crystal asmb2->getChildren(grandchildren,false); NROWS = static_cast(grandchildren.size()); NCOLS = static_cast(children.size()); - //Geometry::IComponent_const_sptr first = children[0]; - //Geometry::IComponent_const_sptr last = children[NCOLS-1]; - //xsize = (first.getPos() - last.getPos()).norm(); - //ysize = (grandchildren[0].getPos() - grandchildren[NROWS-1].getPos()).norm(); + Geometry::IComponent_const_sptr first = children[0]; + Geometry::IComponent_const_sptr last = children[NCOLS-1]; + xsize = first->getDistance(*last); + first = grandchildren[0]; + last = grandchildren[NROWS-1]; + ysize = first->getDistance(*last); } } From 4a96bab3ca8dfb21b515c65ae038eea91dba8b4f Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Mon, 9 Dec 2013 15:39:18 +0000 Subject: [PATCH 100/403] Activate new code and remove unneeded AutoPtr re #8546 Signed-off-by: Karl Palmen --- Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index 805a32141161..a654ebc6865b 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -99,12 +99,13 @@ void LoadParameterFile::exec() std::string filename = getPropertyValue("Filename"); // Retrieve the parameter XML string from the properties + const Property * const parameterXMLProperty = getProperty("ParameterXML"); // to check whether it is default std::string parameterXML = getPropertyValue("ParameterXML"); // Get the input workspace const MatrixWorkspace_sptr localWorkspace = getProperty("Workspace"); - execManually(false, filename, parameterXML, localWorkspace); + execManually(!parameterXMLProperty->isDefault(), filename, parameterXML, localWorkspace); } void LoadParameterFile::execManually(bool useString, std::string filename, std::string parameterXML, Mantid::API::ExperimentInfo_sptr localWorkspace) @@ -147,7 +148,7 @@ void LoadParameterFile::execManually(bool useString, std::string filename, std:: } // Get pointer to root element - AutoPtr pRootElem = pDoc->documentElement(); + Element* pRootElem = pDoc->documentElement(); if ( !pRootElem->hasChildNodes() ) { throw Kernel::Exception::InstrumentDefinitionError("No root element in XML Parameter file", filename); From 7fc14c6e7b5db84f696921867a305a667fdd597c Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Mon, 9 Dec 2013 16:49:45 +0000 Subject: [PATCH 101/403] Check file and string property re #8546 At least one of these two properties must be set. Signed-off-by: Karl Palmen --- Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index a654ebc6865b..d95efb1e5085 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -102,6 +102,11 @@ void LoadParameterFile::exec() const Property * const parameterXMLProperty = getProperty("ParameterXML"); // to check whether it is default std::string parameterXML = getPropertyValue("ParameterXML"); + // Check the two properties (at least one must be set) + if( filename.empty() && parameterXMLProperty->isDefault()){ + throw Kernel::Exception::FileError("Either the Filename or ParameterXML property of LoadInstrument most be specified to load an IDF" , filename); + } + // Get the input workspace const MatrixWorkspace_sptr localWorkspace = getProperty("Workspace"); From 917635047d601767a5869debc5ea367b5b75ce29 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 17:54:28 +0000 Subject: [PATCH 102/403] Refs #8550. Use detector IDs for grouping instead of spectra indices. This is consistent to how GroupDetectors works and how information is stored in the files. --- .../Algorithms/src/MuonGroupDetectors.cpp | 17 ++++++++----- .../Algorithms/test/MuonGroupDetectorsTest.h | 11 +++++---- .../DataHandling/src/LoadMuonNexus1.cpp | 4 +++- .../DataHandling/test/LoadMuonNexus1Test.h | 24 +++++++++---------- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp index bf5b2b211cbe..c1cdc3e12c47 100644 --- a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp @@ -104,17 +104,22 @@ namespace Algorithms // Compile the groups for ( auto rowIt = nonEmptyRows.begin(); rowIt != nonEmptyRows.end(); ++rowIt ) { - // Not "detectors" as such, but workspace indices. For Muons there is only one detector for - // workspace index in the data before grouping. - std::vector& detectors = table->cell< std::vector >(*rowIt, 0); - // Group index in the output workspace size_t groupIndex = static_cast( std::distance(nonEmptyRows.begin(), rowIt) ); + std::vector& detectorIDs = table->cell< std::vector >(*rowIt, 0); + + // Recieve detector IDs, but need workspace indices to group, so convert + std::vector wsIndices; + inWS->getIndicesFromDetectorIDs(detectorIDs, wsIndices); + + if ( wsIndices.size() != detectorIDs.size() ) + throw std::invalid_argument("Some of the detector IDs were not found"); + // We will be setting them anew outWS->getSpectrum(groupIndex)->clearDetectorIDs(); - for(auto detIt = detectors.begin(); detIt != detectors.end(); detIt++) + for(auto detIt = wsIndices.begin(); detIt != wsIndices.end(); detIt++) { for( size_t i = 0; i < inWS->blocksize(); ++i ) { @@ -131,7 +136,7 @@ namespace Algorithms } // Using the first detector X values - outWS->dataX(groupIndex) = inWS->dataX(detectors.front()); + outWS->dataX(groupIndex) = inWS->dataX(wsIndices.front()); outWS->getSpectrum(groupIndex)->setSpectrumNo( static_cast(groupIndex + 1) ); } diff --git a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h index 0cd76a890b22..2603c3905712 100644 --- a/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MuonGroupDetectorsTest.h @@ -38,6 +38,9 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite MatrixWorkspace_sptr inWS = WorkspaceCreationHelper::Create2DWorkspace123(5,3); + for ( size_t i = 0; i < inWS->getNumberHistograms(); ++i ) + inWS->getSpectrum(i)->setDetectorID( static_cast(i + 1) ); // To be consistent with how LoadMuonNexus works + TableWorkspace_sptr grouping = createDetectorGroupingTable(); MuonGroupDetectors alg; @@ -71,11 +74,11 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( ws->getSpectrum(1)->getSpectrumNo(), 2); std::set d1; - d1.insert(0); d1.insert(1); + d1.insert(1); d1.insert(2); TS_ASSERT_EQUALS( ws->getSpectrum(0)->getDetectorIDs(), d1 ); std::set d2; - d2.insert(2); d2.insert(3); d2.insert(4); + d2.insert(3); d2.insert(4); d2.insert(5); TS_ASSERT_EQUALS( ws->getSpectrum(1)->getDetectorIDs(), d2 ); } @@ -92,12 +95,12 @@ class MuonGroupDetectorsTest : public CxxTest::TestSuite t->addColumn("vector_int", "Detectors"); std::vector group1; - group1.push_back(0); group1.push_back(1); + group1.push_back(1); group1.push_back(2); TableRow row1 = t->appendRow(); row1 << group1; std::vector group2; - group2.push_back(2); group2.push_back(3); group2.push_back(4); + group2.push_back(3); group2.push_back(4); group2.push_back(5); TableRow row2 = t->appendRow(); row2 << group2; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 04f357208c35..62afd0347ba1 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -635,7 +635,9 @@ namespace Mantid for ( auto it = begin; it != end; ++it ) { - grouping[*it].push_back( static_cast( std::distance(begin,it) ) ); + // Add detector ID to the list of group detectors. Detector ID is always + // spectra index + 1 + grouping[*it].push_back( static_cast( std::distance(begin,it) ) + 1 ); } for ( auto it = grouping.begin(); it != grouping.end(); ++it ) diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h index 073681a385b8..931a036e2344 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h @@ -532,11 +532,11 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite TS_ASSERT_EQUALS( e1.size(), 16); TS_ASSERT_EQUALS( e2.size(), 16); - TS_ASSERT_EQUALS( e1[0], 0 ); - TS_ASSERT_EQUALS( e1[15], 15); + TS_ASSERT_EQUALS( e1[0], 1 ); + TS_ASSERT_EQUALS( e1[15], 16); - TS_ASSERT_EQUALS( e2[0], 16 ); - TS_ASSERT_EQUALS( e2[15], 31 ); + TS_ASSERT_EQUALS( e2[0], 17 ); + TS_ASSERT_EQUALS( e2[15], 32 ); } AnalysisDataService::Instance().remove(outWSName); @@ -586,11 +586,11 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite TS_ASSERT_EQUALS( e1.size(), 32); TS_ASSERT_EQUALS( e2.size(), 32); - TS_ASSERT_EQUALS( e1[0], 32 ); - TS_ASSERT_EQUALS( e1[31], 63 ); + TS_ASSERT_EQUALS( e1[0], 33 ); + TS_ASSERT_EQUALS( e1[31], 64 ); - TS_ASSERT_EQUALS( e2[0], 0 ); - TS_ASSERT_EQUALS( e2[31], 31 ); + TS_ASSERT_EQUALS( e2[0], 1 ); + TS_ASSERT_EQUALS( e2[31], 32 ); } TableWorkspace_sptr table2 = boost::dynamic_pointer_cast( detectorGrouping->getItem(1) ); @@ -608,11 +608,11 @@ class LoadMuonNexus1Test : public CxxTest::TestSuite TS_ASSERT_EQUALS( e1.size(), 32); TS_ASSERT_EQUALS( e2.size(), 32); - TS_ASSERT_EQUALS( e1[0], 32 ); - TS_ASSERT_EQUALS( e1[31], 63 ); + TS_ASSERT_EQUALS( e1[0], 33 ); + TS_ASSERT_EQUALS( e1[31], 64 ); - TS_ASSERT_EQUALS( e2[0], 0 ); - TS_ASSERT_EQUALS( e2[31], 31); + TS_ASSERT_EQUALS( e2[0], 1 ); + TS_ASSERT_EQUALS( e2[31], 32); } } From 3bec92b0d735420bbd9a6b132fbc7c7f396686f5 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:06:52 +0000 Subject: [PATCH 103/403] Refs #8550. MuonAnalysis: some new functions for grouping. Plus updating the old ones a bit. --- .../MantidQtCustomInterfaces/MuonAnalysis.h | 38 +++-- .../CustomInterfaces/src/MuonAnalysis.cpp | 145 ++++++++++++++---- 2 files changed, 145 insertions(+), 38 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index c3ce58c0a195..2522e7a2355e 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -5,12 +5,16 @@ // Includes //---------------------- #include "ui_MuonAnalysis.h" -#include "MantidQtAPI/UserSubWindow.h" -#include "MantidQtMantidWidgets/pythonCalc.h" -#include "MantidQtMantidWidgets/MWDiag.h" #include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/ITableWorkspace.h" + +#include "MantidGeometry/Instrument.h" + +#include "MantidQtAPI/UserSubWindow.h" +#include "MantidQtMantidWidgets/pythonCalc.h" +#include "MantidQtMantidWidgets/MWDiag.h" #include @@ -26,6 +30,9 @@ namespace Muon class MuonAnalysisResultTableTab; } +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace Mantid::Geometry; /** This is the main class for the MuonAnalysis interface @@ -327,9 +334,12 @@ private slots: /// The last directory that was viewed QString m_last_dir; - /// name of workspace + /// Name of the loaded workspace std::string m_workspace_name; + /// Name of the loaded AND grouped workspace + std::string m_grouped_name; + /// name of the loaded data QString m_currentDataName; @@ -392,11 +402,6 @@ private slots: /// set grouping in table from information from nexus raw file void setGroupingFromNexus(const QString& nexusFile); - /// - void setDummyGrouping(const int numDetectors); - - /// - void setGroupingFromIDF(const std::string& mainFieldDirection, Mantid::API::MatrixWorkspace_sptr matrix_workspace); /// title of run std::string m_title; @@ -446,6 +451,21 @@ private slots: /// Saves the value of the widget which called the slot void loadWidgetValue(QWidget* target, const QVariant& defaultValue); + // Groups loaded workspace (m_workspace_name) + void groupLoadedWorkspace(ITableWorkspace_sptr detGroupingTable = ITableWorkspace_sptr()); + + /// Parses grouping information from the UI table. + ITableWorkspace_sptr parseGrouping(); + + /// Updated UI table using the grouping information provided. + void setGrouping(ITableWorkspace_sptr detGroupingTable); + + /// Updates UI grouping table - creates dummy grouping + void setDummyGrouping(Instrument_const_sptr instrument); + + /// Updates UI grouping table using default grouping of the instrument + void setGroupingFromIDF(Instrument_const_sptr instrument, const std::string& mainFieldDirection); + /// handles option tab work MantidQt::CustomInterfaces::Muon::MuonAnalysisOptionTab* m_optionTab; /// handles fit data work diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 94ef254f3ca6..1ad960d214c6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -2893,62 +2893,50 @@ void MuonAnalysis::setGroupingFromNexus(const QString& nexusFile) /** * If nothing else work set dummy grouping and display comment to user */ -void MuonAnalysis::setDummyGrouping(const int numDetectors) +void MuonAnalysis::setDummyGrouping(Instrument_const_sptr instrument) { // if no grouping in nexus then set dummy grouping and display warning to user std::stringstream idstr; - idstr << "1-" << numDetectors; - m_uiForm.groupTable->setItem(0, 0, new QTableWidgetItem("NoGroupingDetected")); - m_uiForm.groupTable->setItem(0, 1, new QTableWidgetItem(idstr.str().c_str())); + idstr << "1-" << instrument->getNumberDetectors(); + m_uiForm.groupTable->setItem( 0, 0, new QTableWidgetItem("NoGroupingDetected") ); + m_uiForm.groupTable->setItem( 0, 1, new QTableWidgetItem( QString::fromStdString(idstr.str()) ) ); updateFrontAndCombo(); - - QMessageBox::warning(this, "MantidPlot - MuonAnalysis", QString("No grouping detected in Nexus file.\n") - + "and no default grouping file specified in IDF\n" - + "therefore dummy grouping created."); } /** * Try to load default grouping file specified in IDF */ -void MuonAnalysis::setGroupingFromIDF(const std::string& mainFieldDirection, MatrixWorkspace_sptr matrix_workspace) +void MuonAnalysis::setGroupingFromIDF(Instrument_const_sptr instrument, const std::string& mainFieldDirection) { - Instrument_const_sptr inst = matrix_workspace->getInstrument(); - - QString instname = m_uiForm.instrSelector->currentText().toUpper(); + std::string parameterName = "Default grouping file"; - QString groupParameter = "Default grouping file"; - // for now hard coded in the special case of MUSR - if (instname == "MUSR") + // Special case for MUSR, because it has two possible groupings + if (instrument->getName() == "MUSR") { - if ( mainFieldDirection == "Transverse" ) - groupParameter += " - Transverse"; - else - groupParameter += " - Longitudinal"; + parameterName.append(" - " + mainFieldDirection); } - std::vector groupFile = inst->getStringParameter(groupParameter.toStdString()); + std::vector groupingFiles = instrument->getStringParameter(parameterName); - // get search directory for XML instrument definition files (IDFs) + // Get search directory for XML instrument definition files (IDFs) std::string directoryName = ConfigService::Instance().getInstrumentDirectory(); - if ( groupFile.size() == 1 ) + if ( groupingFiles.size() == 1 ) { - Grouping loadedGrouping; + const std::string groupingFile = groupingFiles[0]; try { - loadGroupingFromXML(directoryName+groupFile[0], loadedGrouping); + Grouping loadedGrouping; + loadGroupingFromXML(directoryName + groupingFile, loadedGrouping); + fillGroupingTable(loadedGrouping, m_uiForm); } catch (...) { - QMessageBox::warning(this, "MantidPlot - MuonAnalysis", - QString("Can't load default grouping file in IDF. \n With name: ") + groupFile[0].c_str()); - return; + g_log.error("Can't load default grouping file: " + groupingFile); } - - fillGroupingTable(loadedGrouping, m_uiForm); } } @@ -3896,5 +3884,104 @@ void MuonAnalysis::setFirstGoodDataState(int checkBoxState) } } +/** + * Groups loaded workspace (m_workspace_name). Grouped workspace is stored under m_grouped_name. + * @param detGroupingTable :: Grouping information to use. If null - info from table widget is used + */ +void MuonAnalysis::groupLoadedWorkspace(ITableWorkspace_sptr detGroupingTable) +{ + if ( ! detGroupingTable ) + { + auto groupingFromUI = parseGrouping(); + + if ( ! groupingFromUI ) + throw std::invalid_argument("Unable to parse grouping information from the table, or it is empty."); + + detGroupingTable = groupingFromUI; + } + + try + { + IAlgorithm_sptr groupAlg = AlgorithmManager::Instance().createUnmanaged("MuonGroupDetectors"); + groupAlg->initialize(); + groupAlg->setRethrows(true); + groupAlg->setPropertyValue("InputWorkspace", m_workspace_name); + groupAlg->setPropertyValue("OutputWorkspace", m_grouped_name); + + if ( detGroupingTable->name().empty() ) + { + ScopedWorkspace table(detGroupingTable); + groupAlg->setPropertyValue("DetectorGroupingTable", table.name()); + groupAlg->execute(); + } + else + { + groupAlg->setPropertyValue("DetectorGroupingTable", detGroupingTable->name()); + groupAlg->execute(); + } + } + catch(std::exception& e) + { + throw std::runtime_error( "Unable to group loaded workspace:\n\n" + std::string(e.what()) ); + } +} + +/** + * Parses grouping information from the UI table. + * @return ITableWorkspace of the format returned by LoadMuonNexus + */ +ITableWorkspace_sptr MuonAnalysis::parseGrouping() +{ + std::vector groupRows; + whichGroupToWhichRow(m_uiForm, groupRows); + + if ( groupRows.size() == 0 ) + return ITableWorkspace_sptr(); + + auto newTable = boost::dynamic_pointer_cast( + WorkspaceFactory::Instance().createTable("TableWorkspace") ); + + newTable->addColumn("vector_int", "Detectors"); + + for ( auto it = groupRows.begin(); it != groupRows.end(); ++it ) + { + const std::string detectorsString = m_uiForm.groupTable->item(*it,1)->text().toStdString(); + + TableRow newRow = newTable->appendRow(); + newRow << spectrumIDs(detectorsString); + } + + return newTable; +} + +/** + * Updated UI table using the grouping information provided. + * @param detGroupingTable :: Grouping information in the format as returned by LoadMuonNexus + */ +void MuonAnalysis::setGrouping(ITableWorkspace_sptr detGroupingTable) +{ + for ( size_t row = 0; row < detGroupingTable->rowCount(); ++row ) + { + const std::vector& detectors = detGroupingTable->cell< std::vector >(row,0); + + const std::string& detectorRange = Strings::join(detectors.begin(), detectors.end(), ","); + + m_uiForm.groupTable->setItem( static_cast(row), 0, + new QTableWidgetItem( QString::number(row + 1) ) ); + + m_uiForm.groupTable->setItem( static_cast(row), 1, + new QTableWidgetItem( QString::fromStdString(detectorRange) ) ); + } + + if ( numGroups() == 2 && numPairs() <= 0 ) + { + m_uiForm.pairTable->setItem( 0, 0, new QTableWidgetItem("long") ); + m_uiForm.pairTable->setItem( 0, 3, new QTableWidgetItem("1.0") ); + } + + updatePairTable(); + updateFrontAndCombo(); +} + }//namespace MantidQT }//namespace CustomInterfaces From 3c5c2a01bb435da44551d23335dee03f5c62c97e Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:07:38 +0000 Subject: [PATCH 104/403] Refs #8550. Minor code clean-up. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 1ad960d214c6..bc632859daf8 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -2,9 +2,9 @@ // Includes //---------------------- #include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/FrameworkManager.h" #include "MantidAPI/IAlgorithm.h" +#include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/Run.h" #include "MantidAPI/ScopedWorkspace.h" #include "MantidAPI/TableRow.h" @@ -80,11 +80,17 @@ const QString MuonAnalysis::NOT_AVAILABLE("N/A"); //---------------------- ///Constructor MuonAnalysis::MuonAnalysis(QWidget *parent) : - UserSubWindow(parent), m_last_dir(), m_workspace_name("MuonAnalysis"), m_currentDataName(), - m_groupTableRowInFocus(0), m_pairTableRowInFocus(0), m_currentTab(NULL), - m_groupNames(), m_settingsGroup("CustomInterfaces/MuonAnalysis/"), - m_updating(false), m_loaded(false), m_deadTimesChanged(false), m_textToDisplay(""), m_dataTimeZero(0.0), - m_dataFirstGoodData(0.0) + UserSubWindow(parent), + m_last_dir(), + m_workspace_name("MuonAnalysis"), m_grouped_name(m_workspace_name + "Grouped"), + m_currentDataName(), + m_groupTableRowInFocus(0), m_pairTableRowInFocus(0), + m_currentTab(NULL), + m_groupNames(), + m_settingsGroup("CustomInterfaces/MuonAnalysis/"), + m_updating(false), m_loaded(false), m_deadTimesChanged(false), + m_textToDisplay(""), + m_dataTimeZero(0.0), m_dataFirstGoodData(0.0) {} /** @@ -1716,6 +1722,8 @@ void MuonAnalysis::clearTablesAndCombo() m_uiForm.pairTable->setCellWidget(i,1, new QComboBox); m_uiForm.pairTable->setCellWidget(i,2, new QComboBox); } + + m_uiForm.groupDescription->clear(); } From 9581300f79d33e2a645fba047db03581ab0c8eda Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:08:53 +0000 Subject: [PATCH 105/403] Refs #8550. Loading grouping using LoadMuonNexus. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index bc632859daf8..a282f541c350 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -1053,7 +1053,9 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) std::string mainFieldDirection(""); double timeZero(0.0); double firstGoodData(0.0); + ScopedWorkspace loadedDeadTimes; + ScopedWorkspace loadedDetGrouping; for (int i=0; isetPropertyValue("Filename", filename.toStdString() ); - loadMuonAlg->setPropertyValue("DeadTimeTable", loadedDeadTimes.name()); + loadMuonAlg->setProperty("AutoGroup", false); - if (i > 0) + if ( i == 0 ) { - QString tempRangeNum; - tempRangeNum.setNum(i); - loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name + tempRangeNum.toStdString() ); + // Get dead times/grouping from first file only + loadMuonAlg->setPropertyValue( "DeadTimeTable", loadedDeadTimes.name() ); + loadMuonAlg->setPropertyValue( "DetectorGroupingTable", loadedDetGrouping.name() ); + + loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name); } else { - loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name); + QString tempRangeNum; + tempRangeNum.setNum(i); + loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name + tempRangeNum.toStdString() ); } - loadMuonAlg->setProperty("AutoGroup", false); + if (loadMuonAlg->execute() ) { From d55eb1ec20d4a9a85001281360a8635c7576fd3c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:09:37 +0000 Subject: [PATCH 106/403] Refs #8550. Changed grouping logic. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 94 ++++++++++++------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index a282f541c350..27dbed2f6ee3 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -625,16 +625,9 @@ void MuonAnalysis::runLoadCurrent() } if ( !isGroupingSet() ) - { - std::stringstream idstr; - idstr << "1-" << matrix_workspace->getNumberHistograms(); - m_uiForm.groupTable->setItem(0, 0, new QTableWidgetItem("NoGroupingDetected")); - m_uiForm.groupTable->setItem(0, 1, new QTableWidgetItem(idstr.str().c_str())); - updateFrontAndCombo(); - } + setDummyGrouping( matrix_workspace->getInstrument() ); - if ( !applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped") ) - return; + groupLoadedWorkspace(); // Populate instrument fields std::stringstream str; @@ -823,9 +816,11 @@ void MuonAnalysis::groupTableChanged(int row, int column) } } whichGroupToWhichRow(m_uiForm, m_groupToRow); - applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped"); updatePairTable(); updateFrontAndCombo(); + + if ( m_loaded && ! m_updating ) + groupLoadedWorkspace(); } @@ -1194,39 +1189,68 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) } } - // Make the options available - m_optionTab->nowDataAvailable(); - - // Get hold of a pointer to a matrix workspace and apply grouping if applicatable - Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name); - WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast(workspace_ptr); + // Get hold of a pointer to a matrix workspace MatrixWorkspace_sptr matrix_workspace; - int numPeriods = 1; // 1 may mean either a group with one period or simply just 1 normal matrix workspace - if (wsPeriods) + int numPeriods; + + Workspace_sptr loadedWS = AnalysisDataService::Instance().retrieve(m_workspace_name); + + if ( auto group = boost::dynamic_pointer_cast(loadedWS) ) + { + numPeriods = static_cast( group->size() ); + matrix_workspace = boost::dynamic_pointer_cast( group->getItem(0) ); + } + else { - numPeriods = wsPeriods->getNumberOfEntries(); + numPeriods = 1; + matrix_workspace = boost::dynamic_pointer_cast(loadedWS); + } - Workspace_sptr workspace_ptr1 = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1"); - matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr1); + if ( isGroupingSet() ) + { + // If grouping set already - it means it wasn't reset and we can use it + g_log.information("Using custom grouping"); + groupLoadedWorkspace(); } else { - matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr); - } + setGroupingFromIDF( matrix_workspace->getInstrument(), mainFieldDirection ); - // if grouping not set, first see if grouping defined in Nexus - if ( !isGroupingSet() ) - setGroupingFromNexus(files[0]); - // if grouping still not set, then take grouping from IDF - if ( !isGroupingSet() ) - setGroupingFromIDF(mainFieldDirection, matrix_workspace); - // finally if nothing else works set dummy grouping and display - // message to user - if ( !isGroupingSet() ) - setDummyGrouping(static_cast(matrix_workspace->getInstrument()->getDetectorIDs().size())); + if ( isGroupingSet() ) + { + g_log.information("Using grouping loaded from IDF"); + groupLoadedWorkspace(); + } + else if ( loadedDetGrouping ) + { + g_log.information("Using grouping loaded from Nexus file"); + + Workspace_sptr groupingWS = loadedDetGrouping.retrieve(); + ITableWorkspace_sptr groupingTable; + + if ( auto table = boost::dynamic_pointer_cast(groupingWS) ) + { + groupingTable = table; + } + else if ( auto group = boost::dynamic_pointer_cast(groupingWS) ) + { + g_log.information("Multi-period grouping loaded from the Nexus file. Using the first one."); + groupingTable = boost::dynamic_pointer_cast( group->getItem(0) ); + } + + setGrouping(groupingTable); + groupLoadedWorkspace(groupingTable); + } + else + { + g_log.information("Using dummy grouping"); + setDummyGrouping( matrix_workspace->getInstrument() ); + groupLoadedWorkspace(); + } + } - if ( !applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped") ) - throw std::runtime_error("Couldn't apply grouping"); + // Make the options available + m_optionTab->nowDataAvailable(); // Populate instrument fields std::stringstream str; From 432974f1d7cc39e39c8d9f0a25e944200d878200 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:20:50 +0000 Subject: [PATCH 107/403] Refs #8550. Removed unused functions. --- .../MantidQtCustomInterfaces/MuonAnalysis.h | 7 - .../CustomInterfaces/src/MuonAnalysis.cpp | 244 ------------------ 2 files changed, 251 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index 2522e7a2355e..2d4280b6b208 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -247,9 +247,6 @@ private slots: void createPlotWS(const std::string& groupName, const std::string& inputWS, const std::string& outWS); - /// Apply whatever grouping is specified in GUI tables to workspace - bool applyGroupingToWS( const std::string& inputWS, const std::string& outputWS); - /// Update front void updateFront(); @@ -399,10 +396,6 @@ private slots: /// Get the new plot name QString getNewPlotName(const QString & cropWSfirstPart); - /// set grouping in table from information from nexus raw file - void setGroupingFromNexus(const QString& nexusFile); - - /// title of run std::string m_title; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 27dbed2f6ee3..3dc2213b4db2 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -2475,89 +2475,6 @@ bool MuonAnalysis::isGroupingSet() return true; } -/** - * Apply whatever grouping is specified in GUI tables to workspace. - */ -bool MuonAnalysis::applyGroupingToWS( const std::string& inputWsName, const std::string& outputWsName) -{ - if (!isGroupingSet() || !AnalysisDataService::Instance().doesExist(inputWsName)) - return false; - - std::string complaint = isGroupingAndDataConsistent(); - if (!( complaint.empty() ) ) - { - if (m_uiForm.frontPlotButton->isEnabled() ) - QMessageBox::warning(this, "MantidPlot - MuonAnalysis", complaint.c_str()); - m_optionTab->noDataAvailable(); - return false; - } - else - { - if (!m_uiForm.frontPlotButton->isEnabled() ) - m_optionTab->nowDataAvailable(); - } - - // If output workspace exists, remove explicitly, so even if something goes wrong - old data - // is not used - if(AnalysisDataService::Instance().doesExist(outputWsName)) - { - // Using DeleteWorkspace algorithm so if outputWs is a group - it is fully removed - Mantid::API::IAlgorithm_sptr rmWs = AlgorithmManager::Instance().create("DeleteWorkspace"); - rmWs->initialize(); - rmWs->setPropertyValue("Workspace", outputWsName); - rmWs->execute(); - } - - Grouping tableGrouping; - parseGroupingTable(m_uiForm, tableGrouping); - - // Retrieve input workspace - Workspace_sptr inputWs = AnalysisDataService::Instance().retrieve(inputWsName); - - Workspace_sptr outputWs; - - try // ... to group - { - // Single workspace - if(MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast(inputWs)) - { - outputWs = groupWorkspace(ws, tableGrouping); - } - // Workspace group - else if(WorkspaceGroup_sptr group = boost::dynamic_pointer_cast(inputWs)) - { - // Create output group - WorkspaceGroup_sptr outputGroup = boost::make_shared(); - - for(size_t i = 0; i < group->size(); i++) - { - if(MatrixWorkspace_sptr member = boost::dynamic_pointer_cast(group->getItem(i))) - { - MatrixWorkspace_sptr groupedMember = groupWorkspace(member, tableGrouping); - - outputGroup->addWorkspace(groupedMember); - } - else - throw std::invalid_argument("Group contains unsupported workspace type"); - } - - outputWs = outputGroup; - } - else - throw std::invalid_argument("Unsupported workspace type"); - } - catch(std::exception& e) - { - m_optionTab->noDataAvailable(); - g_log.error(e.what()); - return false; - } - - AnalysisDataService::Instance().add(outputWsName, outputWs); - - return true; -} - /** * Calculate number of detectors from string of type 1-3, 5, 10-15 * @@ -2767,167 +2684,6 @@ void MuonAnalysis::startUpLook() } } -/** -* set grouping in table from information from nexus raw file -*/ -void MuonAnalysis::setGroupingFromNexus(const QString& nexusFile) -{ - if ( isGroupingSet() ) - return; - - std::string groupedWS = m_workspace_name+"Grouped"; - - // Setup Load Nexus Algorithm - Mantid::API::IAlgorithm_sptr loadMuonAlg = Mantid::API::AlgorithmManager::Instance().create("LoadMuonNexus"); - loadMuonAlg->setPropertyValue("Filename", nexusFile.toStdString()); - loadMuonAlg->setPropertyValue("OutputWorkspace", groupedWS); - loadMuonAlg->setProperty("AutoGroup", true); - if (! (loadMuonAlg->execute() ) ) - { - QMessageBox::warning(this,"Mantid - MuonAnalysis", "Problem when executing LoadMuonNexus algorithm."); - } - - // get hold of a matrix-workspace. If period data assume each period has - // the same grouping - Workspace_sptr ws_ptr = AnalysisDataService::Instance().retrieve(groupedWS); - WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast(ws_ptr); - MatrixWorkspace_sptr matrix_workspace; - if (wsPeriods) - { - Workspace_sptr ws_ptr1 = AnalysisDataService::Instance().retrieve(groupedWS + "_1"); - matrix_workspace = boost::dynamic_pointer_cast(ws_ptr1); - } - else - { - matrix_workspace = boost::dynamic_pointer_cast(ws_ptr); - } - - // check if there is any grouping in file - bool thereIsGrouping = false; - int numOfHist = static_cast(matrix_workspace->getNumberHistograms()); //Qt has no size_t understanding - for (int wsIndex = 0; wsIndex < numOfHist; wsIndex++) - { - IDetector_const_sptr det; - try // for some bizarry reason when reading EMUautorun_A.tmp this - // underlying nexus file think there are more histogram than there is - // hence the reason for this try/catch here - { - det = matrix_workspace->getDetector(wsIndex); - } - catch (...) - { - break; - } - - if( boost::dynamic_pointer_cast(det) ) - { - // prepare IDs string - - boost::shared_ptr detG = boost::dynamic_pointer_cast(det); - std::vector detIDs = detG->getDetectorIDs(); - if (detIDs.size() > 1) - { - thereIsGrouping = true; - break; - } - } - } - - // if no grouping in nexus then return - if ( thereIsGrouping == false ) - { - return; - } - - // Add info about grouping from Nexus file to group table - for (int wsIndex = 0; wsIndex < numOfHist; wsIndex++) - { - IDetector_const_sptr det = matrix_workspace->getDetector(wsIndex); - - if( boost::dynamic_pointer_cast(det) ) - { - // prepare IDs string - - boost::shared_ptr detG = boost::dynamic_pointer_cast(det); - std::vector detIDs = detG->getDetectorIDs(); - std::stringstream idstr; - int leftInt = detIDs[0]; // meaning left as in the left number of the range 8-18 for instance - int numIDs = static_cast(detIDs.size()); - idstr << detIDs[0]; - for (int i = 1; i < numIDs; i++) - { - if (detIDs[i] != detIDs[i-1]+1 ) - { - if (detIDs[i-1] == leftInt) - { - idstr << ", " << detIDs[i]; - leftInt = detIDs[i]; - } - else - { - idstr << "-" << detIDs[i-1] << ", " << detIDs[i]; - leftInt = detIDs[i]; - } - } - else if ( i == numIDs-1 ) - { - idstr << "-" << detIDs[i]; - } - } - - // prepare group name string - - std::stringstream gName; - gName << wsIndex; - - // create table row - QTableWidgetItem* it = m_uiForm.groupTable->item(wsIndex, 0); - if (it) - it->setText(gName.str().c_str()); - else - { - m_uiForm.groupTable->setItem(wsIndex, 0, new QTableWidgetItem(gName.str().c_str())); - } - - it = m_uiForm.groupTable->item(wsIndex, 1); - if (it) - it->setText(idstr.str().c_str()); - else - m_uiForm.groupTable->setItem(wsIndex, 1, new QTableWidgetItem(idstr.str().c_str())); - } - } // end loop over wsIndex - - // check if exactly two groups added in which case assume these are forward/backward groups - // and automatically then create a pair from which, where the first group is assumed to be - // the forward group - - updatePairTable(); - if ( numGroups() == 2 && numPairs() <= 0 ) - { - QTableWidgetItem* it = m_uiForm.pairTable->item(0, 0); - if (it) - it->setText("pair"); - else - { - m_uiForm.pairTable->setItem(0, 0, new QTableWidgetItem("long")); - } - it = m_uiForm.pairTable->item(0, 3); - if (it) - it->setText("1.0"); - else - { - m_uiForm.pairTable->setItem(0, 3, new QTableWidgetItem("1.0")); - } - updatePairTable(); - updateFrontAndCombo(); - m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(2); - runFrontGroupGroupPairComboBox(2); - } - updatePairTable(); - updateFrontAndCombo(); -} - - /** * If nothing else work set dummy grouping and display comment to user */ From 0589c2fdb793fc2c6255effd4868fff519d163fa Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 19:21:24 +0000 Subject: [PATCH 108/403] Refs #8550. spectrumIDs duplicates String::parseRange - replaced. --- .../MantidQtCustomInterfaces/MuonAnalysis.h | 3 - .../CustomInterfaces/src/MuonAnalysis.cpp | 77 +------------------ 2 files changed, 4 insertions(+), 76 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index 2d4280b6b208..3219f3be4791 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -259,9 +259,6 @@ private slots: /// Calculate number of detectors from string of type 1-3, 5, 10-15 int numOfDetectors(const std::string& str) const; - /// Return a vector of IDs for row number from string of type 1-3, 5, 10-15 - std::vector spectrumIDs(const std::string& str) const; - void changeCurrentRun(std::string& workspaceGroupName); /// is string a number? diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 3dc2213b4db2..23fa4f213acd 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -2483,78 +2483,9 @@ bool MuonAnalysis::isGroupingSet() */ int MuonAnalysis::numOfDetectors(const std::string& str) const { - return static_cast(spectrumIDs(str).size()); + return static_cast(Strings::parseRange(str).size()); } - -/** - * Return a vector of IDs for row number from string of type 1-3, 5, 10-15 - * - * @param str :: String of type "1-3, 5, 10-15" - * @return Vector of IDs - */ -std::vector MuonAnalysis::spectrumIDs(const std::string& str) const -{ - std::vector retVal; - - if (str.empty()) - return retVal; - - typedef Poco::StringTokenizer tokenizer; - tokenizer values(str, ",", tokenizer::TOK_TRIM); - - for (int i = 0; i < static_cast(values.count()); i++) - { - std::size_t found= values[i].find("-"); - if (found!=std::string::npos) - { - tokenizer aPart(values[i], "-", tokenizer::TOK_TRIM); - - if ( aPart.count() != 2 ) - { - retVal.clear(); - return retVal; - } - else - { - if ( !(isNumber(aPart[0]) && isNumber(aPart[1])) ) - { - retVal.clear(); - return retVal; - } - } - - int leftInt; - std::stringstream leftRead(aPart[0]); - leftRead >> leftInt; - int rightInt; - std::stringstream rightRead(aPart[1]); - rightRead >> rightInt; - - if (leftInt > rightInt) - { - retVal.clear(); - return retVal; - } - for (int step = leftInt; step <= rightInt; step++) - retVal.push_back(step); - } - else - { - - if (isNumber(values[i])) - retVal.push_back(boost::lexical_cast(values[i].c_str())); - else - { - retVal.clear(); - return retVal; - } - } - } - return retVal; -} - - /** * Change the workspace group name to the instrument and run number if load current run was pressed. * @@ -2902,7 +2833,7 @@ void MuonAnalysis::checkIf_ID_dublicatesInTable(const int row) QTableWidgetItem *item = m_uiForm.groupTable->item(row,1); // row of IDs to compare against - std::vector idsNew = spectrumIDs(item->text().toStdString()); + std::vector idsNew = Strings::parseRange(item->text().toStdString()); int numG = numGroups(); int rowInFocus = getGroupNumberFromRow(row); @@ -2910,7 +2841,7 @@ void MuonAnalysis::checkIf_ID_dublicatesInTable(const int row) { if (iG != rowInFocus) { - std::vector ids = spectrumIDs(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString()); + std::vector ids = Strings::parseRange(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString()); for (unsigned int i = 0; i < ids.size(); i++) { @@ -3742,7 +3673,7 @@ ITableWorkspace_sptr MuonAnalysis::parseGrouping() const std::string detectorsString = m_uiForm.groupTable->item(*it,1)->text().toStdString(); TableRow newRow = newTable->appendRow(); - newRow << spectrumIDs(detectorsString); + newRow << Strings::parseRange(detectorsString); } return newTable; From 50a5b0275f0f25f0ad790361dbdf67861990e92b Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 20:10:58 +0000 Subject: [PATCH 109/403] Refs #8550. ScopedWorkspace: explicit remove method. Plus fixed setting logic and test for it. --- .../API/inc/MantidAPI/ScopedWorkspace.h | 3 ++ .../Framework/API/src/ScopedWorkspace.cpp | 41 ++++++++++++------- .../Framework/API/test/ScopedWorkspaceTest.h | 17 ++++++++ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/ScopedWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/ScopedWorkspace.h index c6f6feeb7d58..5069047a2b80 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/ScopedWorkspace.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/ScopedWorkspace.h @@ -60,6 +60,9 @@ namespace API /// Retrieve workspace from the ADS Workspace_sptr retrieve() const; + /// Removes the workspace entry from the ADS + void remove(); + /// Operator for conversion to boolean operator bool() const; diff --git a/Code/Mantid/Framework/API/src/ScopedWorkspace.cpp b/Code/Mantid/Framework/API/src/ScopedWorkspace.cpp index 5dd0012c8b5a..b0a6130ff8e7 100644 --- a/Code/Mantid/Framework/API/src/ScopedWorkspace.cpp +++ b/Code/Mantid/Framework/API/src/ScopedWorkspace.cpp @@ -32,21 +32,7 @@ namespace API */ ScopedWorkspace::~ScopedWorkspace() { - AnalysisDataServiceImpl& ads = AnalysisDataService::Instance(); - - // When destructed, remove workspace from the ADS if was added and still exists - if ( ads.doesExist(m_name) ) - { - if ( ads.retrieveWS(m_name) ) - { - // If is a group, need to remove all the members as well - ads.deepRemoveGroup(m_name); - } - else - { - ads.remove(m_name); - } - } + remove(); } /** @@ -73,6 +59,28 @@ namespace API return Workspace_sptr(); } + + /** + * Removes the workspace entry from the ADS. + */ + void ScopedWorkspace::remove() + { + AnalysisDataServiceImpl& ads = AnalysisDataService::Instance(); + + // When destructed, remove workspace from the ADS if was added and still exists + if ( ads.doesExist(m_name) ) + { + if ( ads.retrieveWS(m_name) ) + { + // If is a group, need to remove all the members as well + ads.deepRemoveGroup(m_name); + } + else + { + ads.remove(m_name); + } + } + } /** * Make ADS entry to point to the given workspace. @@ -84,6 +92,9 @@ namespace API if ( ! newWS->name().empty() && ads.doesExist( newWS->name() ) ) throw std::invalid_argument( "Workspace is already in the ADS under the name " + newWS->name() ); + // Remove previous workspace entry + remove(); + ads.add(m_name, newWS); } diff --git a/Code/Mantid/Framework/API/test/ScopedWorkspaceTest.h b/Code/Mantid/Framework/API/test/ScopedWorkspaceTest.h index 234dc6337541..245f6bf364f9 100644 --- a/Code/Mantid/Framework/API/test/ScopedWorkspaceTest.h +++ b/Code/Mantid/Framework/API/test/ScopedWorkspaceTest.h @@ -161,6 +161,23 @@ class ScopedWorkspaceTest : public CxxTest::TestSuite TS_ASSERT( test ); } + void test_settingTwice() + { + ScopedWorkspace test; + + MockWorkspace_sptr ws1 = MockWorkspace_sptr(new MockWorkspace); + test.set(ws1); + + TS_ASSERT_EQUALS( ws1->name(), test.name() ); + + MockWorkspace_sptr ws2 = MockWorkspace_sptr(new MockWorkspace); + test.set(ws2); + + TS_ASSERT_EQUALS( ws2->name(), test.name() ); + TS_ASSERT( ws1->name().empty() ); + TS_ASSERT_EQUALS( m_ads.getObjectNamesInclHidden().size(), 1 ); + } + private: AnalysisDataServiceImpl& m_ads; }; From 8f3586ff3643e8bda22fcd0f43f9184fa587fa3c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Mon, 9 Dec 2013 20:11:15 +0000 Subject: [PATCH 110/403] Refs #8550. Minor refactoring. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 3e715fbdbc01..f278d697fb90 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -1468,7 +1468,9 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) throw std::runtime_error("Muon file " + filename.toStdString() + " not recognised."); // Setup Load Nexus Algorithm - Mantid::API::IAlgorithm_sptr loadMuonAlg = Mantid::API::AlgorithmManager::Instance().create("LoadMuonNexus"); + Mantid::API::IAlgorithm_sptr loadMuonAlg = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); + loadMuonAlg->initialize(); + loadMuonAlg->setLogging(false); loadMuonAlg->setPropertyValue("Filename", filename.toStdString() ); loadMuonAlg->setProperty("AutoGroup", false); @@ -1607,6 +1609,8 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) g_log.information("Using grouping loaded from Nexus file"); Workspace_sptr groupingWS = loadedDetGrouping.retrieve(); + loadedDetGrouping.remove(); // Don't need it in the ADS any more + ITableWorkspace_sptr groupingTable; if ( auto table = boost::dynamic_pointer_cast(groupingWS) ) @@ -3587,25 +3591,19 @@ void MuonAnalysis::groupLoadedWorkspace(ITableWorkspace_sptr detGroupingTable) detGroupingTable = groupingFromUI; } + // Make sure grouping table is in the ADS + ScopedWorkspace table(detGroupingTable); + try { IAlgorithm_sptr groupAlg = AlgorithmManager::Instance().createUnmanaged("MuonGroupDetectors"); groupAlg->initialize(); + groupAlg->setLogging(false); // Don't want to clutter the log groupAlg->setRethrows(true); groupAlg->setPropertyValue("InputWorkspace", m_workspace_name); groupAlg->setPropertyValue("OutputWorkspace", m_grouped_name); - - if ( detGroupingTable->name().empty() ) - { - ScopedWorkspace table(detGroupingTable); - groupAlg->setPropertyValue("DetectorGroupingTable", table.name()); - groupAlg->execute(); - } - else - { - groupAlg->setPropertyValue("DetectorGroupingTable", detGroupingTable->name()); - groupAlg->execute(); - } + groupAlg->setPropertyValue("DetectorGroupingTable", table.name()); + groupAlg->execute(); } catch(std::exception& e) { From 47a75daf9fd6571662f8001ce9d5e5fcf4bf423a Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 9 Dec 2013 15:35:30 -0500 Subject: [PATCH 111/403] Removed tabs. Refs #8089. --- .../plugins/algorithms/SeqRefineProfile.py | 712 +++++++++--------- 1 file changed, 339 insertions(+), 373 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py index ddb86f80aae8..aecd48524c34 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SeqRefineProfile.py @@ -27,136 +27,136 @@ class RefinePowderDiffProfileSeq(PythonAlgorithm): """ Refine powder diffractometer profile by Le Bail algorithm sequentially """ def category(self): - """ Category - """ - return "Diffraction" + """ Category + """ + return "Diffraction" def name(self): - """ Algorithm name - """ - return "RefinePowderDiffProfileSeq" + """ Algorithm name + """ + return "RefinePowderDiffProfileSeq" def PyInit(self): - """ Declare properties - """ - self.setWikiSummary("""Refine powder diffractomer profile parameters sequentially.""") + """ Declare properties + """ + self.setWikiSummary("""Refine powder diffractomer profile parameters sequentially.""") self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, PropertyMode.Optional), "Name of data workspace containing the diffraction pattern in .prf file. ") - self.declareProperty("WorkspaceIndex", 0, "Spectrum (workspace index starting from 0) of the data to refine against in input workspace.") - - self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional), - "Name of table workspace containing sequential refinement information.") - - self.declareProperty(ITableWorkspaceProperty("InputProfileWorkspace", "", Direction.Input, PropertyMode.Optional), - "Name of table workspace containing starting profile parameters.") - - self.declareProperty(ITableWorkspaceProperty("InputBraggPeaksWorkspace", "", Direction.Input, PropertyMode.Optional), - "Name of table workspace containing a list of reflections. ") - - self.declareProperty(ITableWorkspaceProperty("InputBackgroundParameterWorkspace", "", Direction.Input, - PropertyMode.Optional), "Name of table workspace containing a list of reflections. ") - - self.declareProperty("StartX", -0., "Start X (TOF) to refine diffraction pattern.") - self.declareProperty("EndX", -0., "End X (TOF) to refine diffraction pattern.") - - funcoptions = ["Setup", "Refine", "Save", "Load"] - self.declareProperty("FunctionOption", "Refine", StringListValidator(funcoptions), "Options of functionality") - - #refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] - refoptions = ["Random Walk"] - self.declareProperty("RefinementOption", "Random Walk", StringListValidator(refoptions), - "Options of algorithm to refine. ") - - self.declareProperty(StringArrayProperty("ParametersToRefine", values=[], direction=Direction.Input), - "List of parameters to refine.") - - self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") + self.declareProperty("WorkspaceIndex", 0, "Spectrum (workspace index starting from 0) of the data to refine against in input workspace.") + self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional), + "Name of table workspace containing sequential refinement information.") + + self.declareProperty(ITableWorkspaceProperty("InputProfileWorkspace", "", Direction.Input, PropertyMode.Optional), + "Name of table workspace containing starting profile parameters.") + + self.declareProperty(ITableWorkspaceProperty("InputBraggPeaksWorkspace", "", Direction.Input, PropertyMode.Optional), + "Name of table workspace containing a list of reflections. ") + + self.declareProperty(ITableWorkspaceProperty("InputBackgroundParameterWorkspace", "", Direction.Input, + PropertyMode.Optional), "Name of table workspace containing a list of reflections. ") + + self.declareProperty("StartX", -0., "Start X (TOF) to refine diffraction pattern.") + self.declareProperty("EndX", -0., "End X (TOF) to refine diffraction pattern.") + + funcoptions = ["Setup", "Refine", "Save", "Load"] + self.declareProperty("FunctionOption", "Refine", StringListValidator(funcoptions), "Options of functionality") + + #refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"] + refoptions = ["Random Walk"] + self.declareProperty("RefinementOption", "Random Walk", StringListValidator(refoptions), + "Options of algorithm to refine. ") + + self.declareProperty(StringArrayProperty("ParametersToRefine", values=[], direction=Direction.Input), + "List of parameters to refine.") + + self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.") + peaktypes = ["", "Neutron Back-to-back exponential convoluted with pseudo-voigt", "Thermal neutron Back-to-back exponential convoluted with pseudo-voigt"] self.declareProperty("ProfileType", "", StringListValidator(peaktypes), "Type of peak profile function.") - - bkgdtypes = ["", "Polynomial", "Chebyshev", "FullprofPolynomial"] - self.declareProperty("BackgroundType", "", StringListValidator(bkgdtypes), "Type of background function.") - - self.declareProperty("FromStep", -1, "If non-negative, the previous code is not set from last step, but the step specified.") - - # Property for save project + + bkgdtypes = ["", "Polynomial", "Chebyshev", "FullprofPolynomial"] + self.declareProperty("BackgroundType", "", StringListValidator(bkgdtypes), "Type of background function.") + + self.declareProperty("FromStep", -1, "If non-negative, the previous code is not set from last step, but the step specified.") + + # Property for save project self.declareProperty(FileProperty("OutputProjectFilename","", FileAction.OptionalSave, ['.nxs']), "Name of sequential project file.") - - # Property for save project + + # Property for save project self.declareProperty(FileProperty("InputProjectFilename","", FileAction.OptionalLoad, ['.nxs']), "Name of sequential project file.") - + # Project ID self.declareProperty("ProjectID", "", "Project ID.") - - return + + return def PyExec(self): - """ Main - """ - # Process input - self._processInputProperties() - - # Instantiaze sequential refinement - seqrefine = SeqRefineProfile(self._projectID, self.log()) - - # Execute - if self.functionoption == "Setup": - # Set up - if seqrefine.isSetup() is True: - raise NotImplementedError("Impossible to have it set up already.") - - seqrefine.initSetup(self.dataws, self.wsindex, self.peaktype, self.profilews, self.braggpeakws, self.bkgdtype, self.bkgdparws, - self.startx, self.endx) - - elif self.functionoption == "Refine": - # Refine - if seqrefine.isSetup() is False: - raise NotImplementedError("Exception because sequential refinement is not set up.") - seqrefine.refine(self.dataws, self.wsindex, self.paramstofit, self.numcycles, self.startx, self.endx, self._lastStep) - - elif self.functionoption == "Save": - # Save the current state to a project file - seqrefine.saveProject(str(self.dataws), self.wsindex, self.outprojectfilename) - - elif self.functionoption == "Load": - # Set up from an exiting project file - if seqrefine.isSetup() is True: - raise NotImplementedError("Impossible to have it set up already.") - - seqrefine.loadProject(self.inprojectfilename) - - else: - # None-support - raise NotImplementedError("Function is not supported.") - - return + """ Main + """ + # Process input + self._processInputProperties() + + # Instantiaze sequential refinement + seqrefine = SeqRefineProfile(self._projectID, self.log()) + + # Execute + if self.functionoption == "Setup": + # Set up + if seqrefine.isSetup() is True: + raise NotImplementedError("Impossible to have it set up already.") + + seqrefine.initSetup(self.dataws, self.wsindex, self.peaktype, self.profilews, self.braggpeakws, self.bkgdtype, + self.bkgdparws, self.startx, self.endx) + + elif self.functionoption == "Refine": + # Refine + if seqrefine.isSetup() is False: + raise NotImplementedError("Exception because sequential refinement is not set up.") + seqrefine.refine(self.dataws, self.wsindex, self.paramstofit, self.numcycles, self.startx, self.endx, self._lastStep) + + elif self.functionoption == "Save": + # Save the current state to a project file + seqrefine.saveProject(str(self.dataws), self.wsindex, self.outprojectfilename) + + elif self.functionoption == "Load": + # Set up from an exiting project file + if seqrefine.isSetup() is True: + raise NotImplementedError("Impossible to have it set up already.") + + seqrefine.loadProject(self.inprojectfilename) + + else: + # None-support + raise NotImplementedError("Function is not supported.") + + return def _processInputProperties(self): - """ Process input properties - """ - # Input data workspace and related + """ Process input properties + """ + # Input data workspace and related self.dataws = self.getProperty("InputWorkspace").value - self.wsindex = self.getProperty("WorkspaceIndex").value - - self.startx = self.getProperty("StartX").value - self.endx = self.getProperty("EndX").value - - self._lastStep = self.getProperty("FromStep").value - + self.wsindex = self.getProperty("WorkspaceIndex").value + + self.startx = self.getProperty("StartX").value + self.endx = self.getProperty("EndX").value + + self._lastStep = self.getProperty("FromStep").value + self._projectID = self.getProperty("ProjectID").value if len(self._projectID) == 0: raise NotImplementedError("User must specify project ID.") - - self.functionoption = self.getProperty("FunctionOption").value - if self.functionoption == "Setup": + + self.functionoption = self.getProperty("FunctionOption").value + if self.functionoption == "Setup": # Request on 'Setup' ptype = self.getProperty("ProfileType").value if ptype == "Neutron Back-to-back exponential convoluted with pseudo-voigt": @@ -165,33 +165,33 @@ def _processInputProperties(self): self.peaktype = "ThermalNeutronBk2BkExpConvPVoigt" else: raise NotImplementedError("Peak profile is not supported.") - - self.bkgdtype = self.getProperty("BackgroundType").value - self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value - self.profilews = self.getProperty("InputProfileWorkspace").value - self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value - - elif self.functionoption == "Refine": - self.paramstofit = self.getProperty("ParametersToRefine").value - self.numcycles = self.getProperty("NumRefineCycles").value - - elif self.functionoption == "Save": - self.outprojectfilename = self.getProperty("OutputProjectFilename").value - - elif self.functionoption == "Load": - self.inprojectfilename = self.getProperty("InputProjectFilename").value - + self.bkgdtype = self.getProperty("BackgroundType").value + self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value + self.profilews = self.getProperty("InputProfileWorkspace").value + self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value + + + elif self.functionoption == "Refine": + self.paramstofit = self.getProperty("ParametersToRefine").value + self.numcycles = self.getProperty("NumRefineCycles").value + + elif self.functionoption == "Save": + self.outprojectfilename = self.getProperty("OutputProjectFilename").value + + elif self.functionoption == "Load": + self.inprojectfilename = self.getProperty("InputProjectFilename").value + else: raise NotImplementedError("Unsupported function mode %s. " % (self.functionoption)) - + if self.functionoption != "Load": self.datawsname = str(self.dataws) - if self.wsindex < 0 or self.wsindex >= self.dataws.getNumberHistograms(): - raise NotImplementedError("Input workspace index %d is out of range (0, %d)." % + if self.wsindex < 0 or self.wsindex >= self.dataws.getNumberHistograms(): + raise NotImplementedError("Input workspace index %d is out of range (0, %d)." % (self.wsindex, self.dataws.getNumberHistograms())) - - return + + return #-------------------------------------------------------------------- @@ -209,121 +209,121 @@ class SeqRefineProfile: the input/starting values should be from the last """ def __init__(self, ID, glog): - """ - """ + """ + """ # Set up log self.glog = glog # Set up ID - self._ID = str(ID) + self._ID = str(ID) self.glog.information("SeqRefineProfile is initialized with ID = %s" % (str(ID))) - + # Standard record table and check its existence - self._recordwsname = "Record%sTable" % (str(ID)) + self._recordwsname = "Record%sTable" % (str(ID)) self.glog.notice("Using record table %s" % (self._recordwsname)) - - if AnalysisDataService.doesExist(self._recordwsname): - # Record workspace exists: has been set up - self._isSetup = True - else: - # Record workspace does not exist: first time or need to load from file - self._isSetup = False - + + if AnalysisDataService.doesExist(self._recordwsname): + # Record workspace exists: has been set up + self._isSetup = True + else: + # Record workspace does not exist: first time or need to load from file + self._isSetup = False + self._recordWSLastRowInvalid = False - + # Result workspace group - self._wsgroupName = self._ID + "_Group" + self._wsgroupName = self._ID + "_Group" if AnalysisDataService.doesExist(self._wsgroupName): self._wsgroupCreated = True else: self._wsgroupCreated = False - - return + + return def initSetup(self, dataws, wsindex, peaktype, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx): - """ Set up the properties for LeBailFit as the first time including - do a Le bail calculation based on the input parameters - including profilews, braggpeakws, and etc - """ + """ Set up the properties for LeBailFit as the first time including + do a Le bail calculation based on the input parameters + including profilews, braggpeakws, and etc + """ # Data and data range self._datawsname = str(dataws) - if startx <= 0.: - startx = dataws.readX(wsindex)[0] - if endx <= 0.: - endx = dataws.readX(wsindex)[-1] - - # Profile + if startx <= 0.: + startx = dataws.readX(wsindex)[0] + if endx <= 0.: + endx = dataws.readX(wsindex)[-1] + + # Profile self._peakType = peaktype - self._profileWS = profilews - self._braggpeakws = braggpeakws - self._bkgdtype = bkgdtype - self._bkgdparws = bkgdparws - - # Generate record table - self._genRecordTable() - - # Check input parameters, i.e., verification/examine input parameters - runner = RefineProfileParameters(self.glog) - + self._profileWS = profilews + self._braggpeakws = braggpeakws + self._bkgdtype = bkgdtype + self._bkgdparws = bkgdparws + + # Generate record table + self._genRecordTable() + + # Check input parameters, i.e., verification/examine input parameters + runner = RefineProfileParameters(self.glog) + outwsname = self._datawsname+"_Init" - + runner.setInputs(self._datawsname, self._peakType, self._profileWS, self._braggpeakws, self._bkgdtype, self._bkgdparws) # FIXME - Need to verify whether input and output background parameter ws name can be same runner.setOutputs(outwsname, self._profileWS, self._braggpeakws, self._bkgdparws) - - self._recordPreRefineInfo(runner, -1) - runner.calculate(startx, endx) - self._recordPostRefineInfo(runner) - - # Group the newly generated workspace and do some record - api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, self._profileWS, self._braggpeakws, self._bkgdparws), + + self._recordPreRefineInfo(runner, -1) + runner.calculate(startx, endx) + self._recordPostRefineInfo(runner) + + # Group the newly generated workspace and do some record + api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, self._profileWS, self._braggpeakws, self._bkgdparws), OutputWorkspace=self._wsgroupName) self._wsgroupCreated = True - - # Repository - - # Replace 'Refine' of step 0 to ID (it is always empty) - self._recordws.setCell(0, 5, self._ID) - # Replace 'InputProfileWorkspace' by profile type (it is alwasy same as output) - self._recordws.setCell(0, 9, self._peakType) - + + # Repository + + # Replace 'Refine' of step 0 to ID (it is always empty) + self._recordws.setCell(0, 5, self._ID) + # Replace 'InputProfileWorkspace' by profile type (it is alwasy same as output) + self._recordws.setCell(0, 9, self._peakType) + self._isSetup = True - - return + + return def loadProject(self, projectfilename): - """ Load the project from a saved project file - """ - # Load workspace group - api.LoadNexusProcessed(Filename=projectfilename, OutputWorkspace=self._wsgroupName) + """ Load the project from a saved project file + """ + # Load workspace group + api.LoadNexusProcessed(Filename=projectfilename, OutputWorkspace=self._wsgroupName) self._wsgroup = AnalysisDataService.retrieve(self._wsgroupName) - - if self._wsgroup.__class__.__name__ != "WorkspaceGroup": - raise NotImplementedError("Input is not a workspace group but a %s" % (self._wsgroup.__class__.__name__)) + + if self._wsgroup.__class__.__name__ != "WorkspaceGroup": + raise NotImplementedError("Input is not a workspace group but a %s" % (self._wsgroup.__class__.__name__)) else: self._wsgroupCreated = True - - # Parse README - wsnames = self._wsgroup.getNames() - readmewsname = None - for wsname in wsnames: - if wsname.startswith("READ"): - readmewsname = wsname - break - if readmewsname is None: - raise NotImplementedError("No README workspace is found in loaded workspace group.") - - readmews = AnalysisDataService.retrieve(readmewsname) - infodict = {} - numrows = readmews.rowCount() + + # Parse README + wsnames = self._wsgroup.getNames() + readmewsname = None + for wsname in wsnames: + if wsname.startswith("READ"): + readmewsname = wsname + break + if readmewsname is None: + raise NotImplementedError("No README workspace is found in loaded workspace group.") + + readmews = AnalysisDataService.retrieve(readmewsname) + infodict = {} + numrows = readmews.rowCount() self.glog.information("Found %d rows in workspace %s" % (numrows, str(readmews))) - for r in xrange(numrows): - functioncat = str(readmews.cell(r, 0)).strip() - functiontype = str(readmews.cell(r, 1)).strip() - infodict[functioncat] = functiontype.strip() + for r in xrange(numrows): + functioncat = str(readmews.cell(r, 0)).strip() + functiontype = str(readmews.cell(r, 1)).strip() + infodict[functioncat] = functiontype.strip() self.glog.information("README keys: %s" % (infodict.keys())) - self._peakType = infodict["Peak"] + self._peakType = infodict["Peak"] self.datawsname = infodict["Data"] self.wsindex = infodict["Spectrum"] if self._ID != infodict["ID"]: @@ -333,27 +333,27 @@ def loadProject(self, projectfilename): self._isSetup = True - return + return def refine(self, dataws, wsindex, parametersToFit, numcycles, startx, endx, laststepindex): - """ Refine parameters - """ - # Range of fit - if startx <= 0.: - startx = dataws.readX(wsindex)[0] - if endx <= 0.: - endx = dataws.readX(wsindex)[-1] - - # Set up RefineProfileParameters object - runner = RefineProfileParameters(self.glog) - - # Locate refinement record table - profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname, laststep = self._parseRecordTable(laststepindex) - - # Set up runner and refine - runner.setupMonteCarloRefine(numcycles, parametersToFit) - - outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(str(dataws), profilewsname, braggpeakwsname) + """ Refine parameters + """ + # Range of fit + if startx <= 0.: + startx = dataws.readX(wsindex)[0] + if endx <= 0.: + endx = dataws.readX(wsindex)[-1] + + # Set up RefineProfileParameters object + runner = RefineProfileParameters(self.glog) + + # Locate refinement record table + profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname, laststep = self._parseRecordTable(laststepindex) + + # Set up runner and refine + runner.setupMonteCarloRefine(numcycles, parametersToFit) + + outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(str(dataws), profilewsname, braggpeakwsname) # Set up input and output runner.setInputs(str(dataws), self._peakType, profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname) @@ -361,12 +361,12 @@ def refine(self, dataws, wsindex, parametersToFit, numcycles, startx, endx, last runner.setOutputs(outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname) - # Refine and record pre and post refinement information - self._recordPreRefineInfo(runner, laststep) - runner.refine(numcycles, parametersToFit, startx, endx) - self._recordPostRefineInfo(runner) - - # Group newly generated workspaces and add name to reposiotry + # Refine and record pre and post refinement information + self._recordPreRefineInfo(runner, laststep) + runner.refine(numcycles, parametersToFit, startx, endx) + self._recordPostRefineInfo(runner) + + # Group newly generated workspaces and add name to reposiotry if self._wsgroupCreated is True: api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname, self._wsgroupName), OutputWorkspace=self._wsgroupName) @@ -382,7 +382,7 @@ def refine(self, dataws, wsindex, parametersToFit, numcycles, startx, endx, last else: raise NotImplementedError("Impossible to have 1 workspace appeared twice in a workspace group.") - return + return def isSetup(self): """ Status whether refinement is set up. @@ -391,9 +391,9 @@ def isSetup(self): def saveProject(self, datawsname, wsindex, projectfname): - """ Save current to a project file - Note: MC setup table workspace is not generated in this class. So it won't be saved - """ + """ Save current to a project file + Note: MC setup table workspace is not generated in this class. So it won't be saved + """ import os # FIXME - Find out a good way to remove existing files/directories @@ -408,76 +408,76 @@ def saveProject(self, datawsname, wsindex, projectfname): except OSError: shutil.rmtree(projectfname) - api.SaveNexusProcessed(InputWorkspace=self._wsgroupName, Filename=projectfname, Append=False) - - # Add data workspace, tracking record table to workspaces - # api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (datawsname, self._recordwsname, self._wsgroupName), + api.SaveNexusProcessed(InputWorkspace=self._wsgroupName, Filename=projectfname, Append=False) + + # Add data workspace, tracking record table to workspaces + # api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (datawsname, self._recordwsname, self._wsgroupName), # OutputWorkspace=self._wsgroupName) self.glog.notice("Append record workspace %s" % (self._recordwsname)) - api.SaveNexusProcessed(InputWorkspace=self._recordwsname, Filename=projectfname, Append=True) - + api.SaveNexusProcessed(InputWorkspace=self._recordwsname, Filename=projectfname, Append=True) + self.glog.notice("Append data workspace %s" % (datawsname)) - api.SaveNexusProcessed(InputWorkspace=datawsname, Filename=projectfname, Append=True) - - # Create a new README table workspace for some other information - readmewsname = "READ_%s" % (self._ID) - readmews = api.CreateEmptyTableWorkspace(OutputWorkspace=readmewsname) - readmews.addColumn("str", "Function") - readmews.addColumn("str", "Type") - - readmews.addRow(["Peak", "Not Important"]) - readmews.addRow(["Background", "Not Important"]) + api.SaveNexusProcessed(InputWorkspace=datawsname, Filename=projectfname, Append=True) + + # Create a new README table workspace for some other information + readmewsname = "READ_%s" % (self._ID) + readmews = api.CreateEmptyTableWorkspace(OutputWorkspace=readmewsname) + readmews.addColumn("str", "Function") + readmews.addColumn("str", "Type") + + readmews.addRow(["Peak", "Not Important"]) + readmews.addRow(["Background", "Not Important"]) readmews.addRow(["ID", str(self._ID)]) readmews.addRow(["Record", self._recordwsname]) readmews.addRow(["Data", str(datawsname)]) readmews.addRow(["Spectrum", str(wsindex)]) - api.SaveNexusProcessed(InputWorkspace=readmewsname, Filename=projectfname, Append=True) - - return + api.SaveNexusProcessed(InputWorkspace=readmewsname, Filename=projectfname, Append=True) + + return def _genRecordTable(self): - """ Generate record table - """ - tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname) - - tablews.addColumn("int", "Step") - tablews.addColumn("str", "OutProfile") - tablews.addColumn("str", "OutReflection") - tablews.addColumn("str", "OutBackgroud") - tablews.addColumn("str", "OutBckgroundParam") - tablews.addColumn("str", "Refine") - tablews.addColumn("double", "RwpOut") - tablews.addColumn("int", "LastStep") - tablews.addColumn("double", "RwpIn") - tablews.addColumn("str", "InProfile") - tablews.addColumn("str", "InReflection") - tablews.addColumn("str", "InBackgroud") - tablews.addColumn("str", "InBckgroundParam") + """ Generate record table + """ + tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname) + + tablews.addColumn("int", "Step") + tablews.addColumn("str", "OutProfile") + tablews.addColumn("str", "OutReflection") + tablews.addColumn("str", "OutBackgroud") + tablews.addColumn("str", "OutBckgroundParam") + tablews.addColumn("str", "Refine") + tablews.addColumn("double", "RwpOut") + tablews.addColumn("int", "LastStep") + tablews.addColumn("double", "RwpIn") + tablews.addColumn("str", "InProfile") + tablews.addColumn("str", "InReflection") + tablews.addColumn("str", "InBackgroud") + tablews.addColumn("str", "InBckgroundParam") self._recordws = tablews - return + return def _parseRecordTable(self, laststep): - """ Parse record table and return the last refinement result + """ Parse record table and return the last refinement result Notice that 'last row' in record table might not be a valid row (incomplete). It might be caused by an exception raised in refinement or its setup. Class variable _recordWSLastRowInvalid is used to indicate this - """ + """ # Retrieve record workspace - self._recordws = AnalysisDataService.retrieve(str(self._recordwsname)) - numrows = self._recordws.rowCount() - if numrows == 0: - raise NotImplementedError("Empty record table workspace. ") - + self._recordws = AnalysisDataService.retrieve(str(self._recordwsname)) + numrows = self._recordws.rowCount() + if numrows == 0: + raise NotImplementedError("Empty record table workspace. ") + # Find last valid row lastvalidrow = -1 lastrow = numrows-1 self._recordwsLastRowValid = False while self._recordwsLastRowValid is False and lastrow >= 0: - profilewsname = self._recordws.cell(lastrow, 1) - if profilewsname == "": + profilewsname = self._recordws.cell(lastrow, 1) + if profilewsname == "": self.glog.warning("Profile workspace name is emtpy in row %d!" % (lastrow)) lastrow -= 1 else: @@ -508,11 +508,11 @@ def _parseRecordTable(self, laststep): if step != laststep: lastvalidrow -= 1 else: - profilewsname = self._recordws.cell(lastvalidrow, 1).strip() - reflectwsname = self._recordws.cell(lastvalidrow, 2).strip() - bkgdtype = self._recordws.cell(lastrow, 3).strip() - bkgdparamwsname = self._recordws.cell(lastrow, 4).strip() - if profilewsname == "": + profilewsname = self._recordws.cell(lastvalidrow, 1).strip() + reflectwsname = self._recordws.cell(lastvalidrow, 2).strip() + bkgdtype = self._recordws.cell(lastrow, 3).strip() + bkgdparamwsname = self._recordws.cell(lastrow, 4).strip() + if profilewsname == "": raise NotImplementedError("Profile workspace name is emtpy in row %d. It is not supposed to happen." % (lastvalidrow)) break @@ -528,16 +528,16 @@ def _parseRecordTable(self, laststep): # Set up for other informatin # Peak type self._peakType = self._recordws.cell(0, 9).strip() - # Background type - self._bkgdType = bkgdtype.strip() - - return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname, laststep) + # Background type + self._bkgdType = bkgdtype.strip() + + return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname, laststep) def _recordPreRefineInfo(self, refiner, laststep): """ Record pre-refinement information """ - rectablews = mtd[self._recordwsname] + rectablews = mtd[self._recordwsname] numrows = rectablews.rowCount() if self._recordWSLastRowInvalid is False: @@ -557,7 +557,7 @@ def _recordPreRefineInfo(self, refiner, laststep): rectablews.setCell(self._currstep, 11, str(refiner.bkgdtype)) rectablews.setCell(self._currstep, 12, str(refiner.bkgdtablewsname)) - return + return def _recordPostRefineInfo(self, refiner): """ Record post-refinement information, i.e., refinement result @@ -576,7 +576,7 @@ def _recordPostRefineInfo(self, refiner): break # Set the record table workspace - rectablews = mtd[self._recordwsname] + rectablews = mtd[self._recordwsname] numrows = rectablews.rowCount() # currstep = numrows-1 @@ -587,7 +587,7 @@ def _recordPostRefineInfo(self, refiner): if rwp is not None: rectablews.setCell(self._currstep, 6, rwp) - return + return def _genOutputWorkspace(self, datawsname, profilewsname, braggpeakwsname): """ @@ -727,41 +727,7 @@ class RefineProfileParameters: def __init__(self, glog): """ Initialization """ - # bankid, calibDict = importCalibrationInformation(globalsfname) - - # self.bankid = int(bankid) - # bankid = self.bankid - - # self.sample = calibDict[bankid]["Sample"] - - # self.datafilename = calibDict["DataFileDir"] + calibDict[bankid]["DataFileName"] - # hklfilename = calibDict["HKLFileDir"] + calibDict[bankid]["HKLFileName"] - # irffilename = calibDict["IrfFileDir"] + calibDict[bankid]["IrfFileName"] - - # self.startx = float(calibDict[bankid]["LeBailFitMinTOF"]) - # self.endx = float(calibDict[bankid]["LeBailFitMaxTOF"]) - # - # self.run = calibDict[bankid]["Run"] - - # # Name of workspaces - # self.datawsname = calibDict[bankid]["DataWorkspace"] - # instrparamwsname = "Bank%sInstrumentParameterTable" % (bankid) - # braggpeakparamwsname = 'BraggPeakParameterTable' - - # # Background related - # usrbkgdpoints = calibDict[bankid]["UserSpecifiedBkgdPts"] - # self.bkgdwsname = self.datawsname+"_Background" - # backgroundtype = calibDict["BackgroundType"] - # backgroundorder = int(calibDict["BackgroundOrder"]) - # self.bkgdfilename = calibDict["WorkingDir"] + self.datawsname + "_Parameters.bak'" - # bkgdwsname = self.datawsname + "_Background" - # self.bkgdtablewsname = self.datawsname + "_Background_Parameters" - - # # Other constants - # latticesize = calibDict[bankid]["LatticeSize"] - self.peaktype = "NOSETUP" - # Output self.outwsname = None @@ -773,59 +739,59 @@ def __init__(self, glog): # Refine self.paramToFit = [] - # Flags - self._inputIsSetup = False - self._outputIsSetup = False + # Flags + self._inputIsSetup = False + self._outputIsSetup = False return def setInputs(self, datawsname, peaktype, profilewsname, braggpeakwsname, bkgdtype, bkgdparwsname): - """ - """ - self.datawsname = datawsname + """ + """ + self.datawsname = datawsname self.peaktype = peaktype - self.inprofilewsname = profilewsname - self.inreflectionwsname = braggpeakwsname - self.bkgdtype = bkgdtype - self.bkgdtablewsname = bkgdparwsname - - self._inputIsSetup = True - - return + self.inprofilewsname = profilewsname + self.inreflectionwsname = braggpeakwsname + self.bkgdtype = bkgdtype + self.bkgdtablewsname = bkgdparwsname + + self._inputIsSetup = True + + return def setOutputs(self, outwsname, profilewsname, braggpeakwsname, bkgdparwsname): - """ Set up the variables for output - """ - self.outwsname = outwsname - self.outprofilewsname = profilewsname - self.outreflectionwsname = braggpeakwsname - self.outbkgdtablewsname = bkgdparwsname - - self._outputIsSetup = True - - return + """ Set up the variables for output + """ + self.outwsname = outwsname + self.outprofilewsname = profilewsname + self.outreflectionwsname = braggpeakwsname + self.outbkgdtablewsname = bkgdparwsname + + self._outputIsSetup = True + + return def setupMonteCarloRefine(self, numcycles, parametersToFit): - """ Set up refinement parameters - """ - if numcycles <= 0: - raise NotImplementedError("It is not allowed to set up a 0 or a negative number to MonteCarloRefine") - else: - self.numsteps = numcycles - - self.paramToFit = parametersToFit - - return + """ Set up refinement parameters + """ + if numcycles <= 0: + raise NotImplementedError("It is not allowed to set up a 0 or a negative number to MonteCarloRefine") + else: + self.numsteps = numcycles + + self.paramToFit = parametersToFit + + return def calculate(self, startx, endx): """ Do Le bail calculation """ - if (self._inputIsSetup and self._outputIsSetup) is False: + if (self._inputIsSetup and self._outputIsSetup) is False: raise NotImplementedError("Either input or output is not setup: inputIsStepUp = %s, outputIsSetup = %s" % (str(self._inputIsSetup), str(self._outputIsSetup))) self.glog.information("**** Calculate: DataWorksapce = %s" % (str(self.datawsname))) - self.glog.information("**** Fit range: %f, %f" % (startx, endx)) + self.glog.information("**** Fit range: %f, %f" % (startx, endx)) self.glog.information("**** Profile workspace = %s, Reflection workspace = %s" % ( self.inprofilewsname, self.inreflectionwsname)) @@ -837,7 +803,7 @@ def calculate(self, startx, endx): OutputParameterWorkspace= self.outprofilewsname, InputHKLWorkspace = self.inreflectionwsname, OutputPeaksWorkspace = self.outreflectionwsname, - FitRegion = '%f, %f' % (startx, endx), + FitRegion = '%f, %f' % (startx, endx), PeakType = self.peaktype, BackgroundType = self.bkgdtype, UseInputPeakHeights = False, @@ -851,13 +817,13 @@ def calculate(self, startx, endx): def refine(self, numsteps, parameternames, startx, endx): """ Main execution body (doStep4) """ - # Check validity - if (self._inputIsSetup and self._outputIsSetup) is False: - raise NotImplementedError("Either input or output is not setup.") - - self.glog.debug("[Refine] Input profile workspace = %s" % (self.inprofilewsname)) - - # Update parameters' fit table + # Check validity + if (self._inputIsSetup and self._outputIsSetup) is False: + raise NotImplementedError("Either input or output is not setup.") + + self.glog.debug("[Refine] Input profile workspace = %s" % (self.inprofilewsname)) + + # Update parameters' fit table if numsteps > 0: # Set up the default parameters to refine @@ -911,7 +877,7 @@ def refine(self, numsteps, parameternames, startx, endx): Function = 'MonteCarlo', NumberMinimizeSteps = numsteps, PeakType = self.peaktype, - BackgroundType = self.bkgdtype, + BackgroundType = self.bkgdtype, BackgroundParametersWorkspace = self.bkgdtablewsname, UseInputPeakHeights = False, PeakRadius ='8', @@ -920,7 +886,7 @@ def refine(self, numsteps, parameternames, startx, endx): Damping = '5.0', RandomSeed = 0, AnnealingTemperature = 100.0, - DrunkenWalk = True) + DrunkenWalk = True) # ENDIF (step) From fbb3bad30a0ba95045db22b24ba551ae22567d63 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Tue, 10 Dec 2013 09:16:31 +0000 Subject: [PATCH 112/403] Refs #8512 Updated error message. --- Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp index 0d7d64069ac6..a0f224ed15cb 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp @@ -1671,7 +1671,7 @@ void Indirect::calPlotEnergy() //something went wrong in the python if(pyOutput == "None") { - showInformationBox("Failed to plot energy. See log for details."); + showInformationBox("Failed to convert to energy. See log for details."); return; } From 522aaa9668c2a0b558a23de524bd176fe1eb182b Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 10:53:22 +0000 Subject: [PATCH 113/403] Refs #8550. Grouping loading improvement. Plus removal of duplicated code. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index f278d697fb90..561d6863436e 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -794,6 +794,7 @@ void MuonAnalysis::runSaveGroupButton() void MuonAnalysis::runLoadGroupButton() { m_updating = true; + // Get grouping file QSettings prevValues; prevValues.beginGroup(m_settingsGroup + "LoadGroupFile"); @@ -829,30 +830,12 @@ void MuonAnalysis::runLoadGroupButton() clearTablesAndCombo(); fillGroupingTable(loadedGrouping, m_uiForm); - - // add number of detectors column to group table - int numRows = m_uiForm.groupTable->rowCount(); - for (int i = 0; i < numRows; i++) - { - QTableWidgetItem *item = m_uiForm.groupTable->item(i,1); - if (!item) - break; - if ( item->text().isEmpty() ) - break; - - std::stringstream detNumRead; - try - { - detNumRead << numOfDetectors(item->text().toStdString()); - m_uiForm.groupTable->setItem(i, 2, new QTableWidgetItem(detNumRead.str().c_str())); - } - catch (...) - { - m_uiForm.groupTable->setItem(i, 2, new QTableWidgetItem("Invalid")); - } - } updateFront(); + m_updating = false; + + if ( m_loaded ) + groupLoadedWorkspace(); } /** From 76c7b7e96243e9a14ea8178c882cca77213bf6dc Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 10:53:44 +0000 Subject: [PATCH 114/403] Refs #8550. Human-readable ranges when loading from nexus. --- .../Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 561d6863436e..b00acd81fbde 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -3630,9 +3630,13 @@ void MuonAnalysis::setGrouping(ITableWorkspace_sptr detGroupingTable) { for ( size_t row = 0; row < detGroupingTable->rowCount(); ++row ) { - const std::vector& detectors = detGroupingTable->cell< std::vector >(row,0); + std::vector detectors = detGroupingTable->cell< std::vector >(row,0); - const std::string& detectorRange = Strings::join(detectors.begin(), detectors.end(), ","); + // toString() expects the sequence to be sorted + std::sort( detectors.begin(), detectors.end() ); + + // Convert to a range string, i.e. 1-5,6-8,9 + const std::string& detectorRange = Strings::toString(detectors); m_uiForm.groupTable->setItem( static_cast(row), 0, new QTableWidgetItem( QString::number(row + 1) ) ); From 4bf4a575eaaf92580196bc45b5b8510cadf37940 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 11:01:34 +0000 Subject: [PATCH 115/403] Refs #8550. Improved error handling a bit. Still a lot of work in that regard though. Worth a separate ticket to make sure all the possible causes of errors are handled. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index b00acd81fbde..19397c9e2a32 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -835,7 +835,18 @@ void MuonAnalysis::runLoadGroupButton() m_updating = false; if ( m_loaded ) - groupLoadedWorkspace(); + { + try + { + groupLoadedWorkspace(); + } + catch(std::exception& e) + { + g_log.error( e.what() ); + QMessageBox::critical(this, "MantidPlot - MuonAnalysis", + "Unable to group the workspace. See log for details."); + } + } } /** @@ -1184,7 +1195,19 @@ void MuonAnalysis::groupTableChanged(int row, int column) updateFrontAndCombo(); if ( m_loaded && ! m_updating ) - groupLoadedWorkspace(); + { + try + { + groupLoadedWorkspace(); + } + catch(std::exception& e) + { + g_log.error( e.what() ); + + QMessageBox::critical(this, "MantidPlot - MuonAnalysis", + "Unable to group the workspace. See log for details"); + } + } } From 8bd2127fb8af55726abca95f180d33be7499eee6 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 11:18:12 +0000 Subject: [PATCH 116/403] Refs #8550. Documentation. --- Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp | 4 +++- Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp | 3 +++ .../DataObjects/inc/MantidDataObjects/VectorColumn.h | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp index c1cdc3e12c47..f860e6e63fb5 100644 --- a/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MuonGroupDetectors.cpp @@ -1,7 +1,9 @@ /*WIKI* Applies detector grouping to a workspace. (Muon version). -TODO: Table format description +Expect the DetectorGroupingTable to contain one column only. It should be of type vector_int (std::vector). Every row corresponds to a group, and the values in the only column are IDs (not indices!) of the detectors which spectra should be contained in the group. Name of the column is not used. + +One detector might be in more than one group. Empty groups are ignored. std::invalid_argument exceptions are thrown if table format is not correct, there are no non-empty groups or one of the detector IDs does not exist in the workspace. *WIKI*/ #include "MantidAlgorithms/MuonGroupDetectors.h" diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 62afd0347ba1..9908591e2dd4 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -32,6 +32,9 @@ To determine if a file contains data from more than one period the field ''switc If this value is greater than one it is taken to be the number of periods, N_p of the data. In this case the N_s spectra in the ''histogram_data'' field are split with N_s/N_p assigned to each period. +===Dead times and detector grouping=== +Muon Nexus v1 files might contain dead time and detector grouping informationl. These are loaded as TableWorkspaces of the format accepted by ApplyDeadTimeCorr and MuonGroupDetectors accordingly. These are returned if and only if names are specified for the properties. For multi-period data workspace groups might be returned, if information in the Nexus files contains this information for each period. + ===ChildAlgorithms used=== The ChildAlgorithms used by LoadMuonNexus are: diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h index 367250b959ec..47f4de4b7c6e 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/VectorColumn.h @@ -17,7 +17,10 @@ namespace DataObjects using namespace Kernel; using namespace API; - /** VectorColumn : TODO: DESCRIPTION + /** VectorColumn : table column type capable of storing vectors of primitive types. + + Plese add more specializations to VectorColumn.cpp as you need them. I don't guarantee + it will work correctly with complex or user types, but it might. Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory From 2ebcec5aaeff7e9a9172f083939c5d8dba37eb65 Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 13:48:11 +0000 Subject: [PATCH 117/403] List available facility in login algorithm. Refs #8581. --- Code/Mantid/Framework/ICat/src/CatalogLogin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp index 4e3a14c7da72..ccc677d16013 100644 --- a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp +++ b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp @@ -8,6 +8,7 @@ This algorithm connects the logged in user to the information catalog. #include "MantidICat/CatalogAlgorithmHelper.h" #include "MantidKernel/MandatoryValidator.h" #include "MantidKernel/MaskedProperty.h" +#include "MantidKernel/ListValidator.h" namespace Mantid { @@ -29,6 +30,8 @@ namespace Mantid declareProperty("Username","", requireValue,"The username to log into the catalog."); declareProperty(new Kernel::MaskedProperty("Password","", requireValue), "The password of the related username to use."); + declareProperty("FacilityName", "", boost::make_shared(Kernel::ConfigService::Instance().getFacilityNames()), + "Select a facility to log in to."); } /// execute the algorithm From 5551c1b2827287bf6fb2e1408c1e6e3f4d64c6dd Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 13:49:17 +0000 Subject: [PATCH 118/403] Obtain the soapEndPoint based on facility on login. Refs #8581. - Use username/password properties directly in the login algorithm. --- Code/Mantid/Framework/ICat/src/CatalogLogin.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp index ccc677d16013..4600892e70ab 100644 --- a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp +++ b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp @@ -37,12 +37,14 @@ namespace Mantid /// execute the algorithm void CatalogLogin::exec() { - std::string username = getProperty("Username"); - std::string password = getProperty("Password"); + // Obtain the soapEndPoint based on the name of the facility the user has selected. + std::string soapEndPoint = Kernel::ConfigService::Instance().getFacility(getProperty("FacilityName")).catalogInfo().soapEndPoint(); + if (soapEndPoint.empty()) throw std::runtime_error("There is no soap end-point for the facility you have selected."); + g_log.notice() << "Attempting to verify user credentials against " << Mantid::Kernel::ConfigService::Instance().getFacility().catalogInfo().catalogName() << std::endl; progress(0.5, "Verifying user credentials..."); - CatalogAlgorithmHelper().createCatalog()->login(username, password, ""); + CatalogAlgorithmHelper().createCatalog()->login(getProperty("Username"), getProperty("Password"), soapEndPoint); } } From 1d0dfef7615062c88bd5f2a4fa23b88508951e85 Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 13:50:30 +0000 Subject: [PATCH 119/403] Added soapEndPoint methods to session. Refs #8581. - Removed a "zero width space" from soapendpoint in `Facilities.xml`. --- Code/Mantid/Framework/ICat/inc/MantidICat/Session.h | 6 ++++++ Code/Mantid/instrument/Facilities.xml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/ICat/inc/MantidICat/Session.h b/Code/Mantid/Framework/ICat/inc/MantidICat/Session.h index bd089562e516..6cae0713864a 100644 --- a/Code/Mantid/Framework/ICat/inc/MantidICat/Session.h +++ b/Code/Mantid/Framework/ICat/inc/MantidICat/Session.h @@ -45,6 +45,10 @@ namespace Mantid const std::string & getUserName() const { return m_userName; } ///set username void setUserName(const std::string& userName) { m_userName=userName; } + /// Get the soap end-point. + const std::string & getSoapEndPoint() const { return m_soapEndPoint; } + /// Set the soap end-point. + void setSoapEndPoint(const std::string& soapEndPoint) { m_soapEndPoint = soapEndPoint; } private: /// used to create singleton @@ -61,6 +65,8 @@ namespace Mantid std::string m_sessionId; /// user name std::string m_userName; + /// Cache soap end-point + std::string m_soapEndPoint; }; #ifdef _WIN32 diff --git a/Code/Mantid/instrument/Facilities.xml b/Code/Mantid/instrument/Facilities.xml index fc6af65a4a50..c052b6a9f946 100644 --- a/Code/Mantid/instrument/Facilities.xml +++ b/Code/Mantid/instrument/Facilities.xml @@ -7,7 +7,7 @@ - + From bc5750bae36c334c755af7725da1634697772068 Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 13:58:49 +0000 Subject: [PATCH 120/403] Created convenience method to set endpoint & SSLContext. Refs #8581. --- .../ICat/inc/MantidICat/ICat4/ICat4Catalog.h | 3 ++ .../Framework/ICat/src/ICat4/ICat4Catalog.cpp | 49 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h index 28f771da40e2..2523525a4360 100644 --- a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h +++ b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h @@ -86,6 +86,9 @@ namespace Mantid std::string bytesToString(int64_t &fileSize); // Helper method that formats a given timestamp. std::string formatDateTime(const time_t ×tamp, const std::string &format); + // Sets the soap-endpoint & SSL context for the proxy being returned. + ICat4::ICATPortBindingProxy getICATProxy(); + // Reference to the logger class. Kernel::Logger& g_log; diff --git a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp index cc77ba64e267..622ea983345f 100644 --- a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp @@ -28,11 +28,10 @@ namespace Mantid */ void ICat4Catalog::login(const std::string& username, const std::string& password, const std::string& url) { - UNUSED_ARG(url) - ICat4::ICATPortBindingProxy icat; - - // Define ssl authentication scheme - setSSLContext(icat); + // Store the soap end-point in the session for use later. + ICat::Session::Instance().setSoapEndPoint(url); + // Obtain the ICAT proxy that has been securely set, including soap-endpoint. + ICat4::ICATPortBindingProxy icat = getICATProxy(); // Used to authenticate the user. ns1__login login; @@ -86,8 +85,7 @@ namespace Mantid */ void ICat4Catalog::logout() { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__logout request; ns1__logoutResponse response; @@ -257,8 +255,7 @@ namespace Mantid g_log.debug() << "ICat4Catalog::search -> Query is: { " << query << " }" << std::endl; - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -285,8 +282,7 @@ namespace Mantid */ int64_t ICat4Catalog::getNumberOfSearchResults(const CatalogSearchParam& inputs) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -328,8 +324,7 @@ namespace Mantid */ void ICat4Catalog::myData(Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -434,8 +429,7 @@ namespace Mantid */ void ICat4Catalog::getDataSets(const long long& investigationId, Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -503,8 +497,7 @@ namespace Mantid */ void ICat4Catalog::getDataFiles(const long long& investigationId, Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -581,8 +574,7 @@ namespace Mantid */ void ICat4Catalog::listInstruments(std::vector& instruments) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -622,8 +614,7 @@ namespace Mantid */ void ICat4Catalog::listInvestigationTypes(std::vector& invstTypes) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__search request; ns1__searchResponse response; @@ -664,8 +655,7 @@ namespace Mantid */ void ICat4Catalog::getFileLocation(const long long & fileID, std::string & fileLocation) { - ICat4::ICATPortBindingProxy icat; - setSSLContext(icat); + ICat4::ICATPortBindingProxy icat = getICATProxy(); ns1__get request; ns1__getResponse response; @@ -817,5 +807,18 @@ namespace Mantid return (dateTime.toFormattedString(format)); } + /** + * Sets the soap-endpoint & SSL context for the proxy being returned. + * @return ICATPortBindingProxy :: The proxy with set endpoint & SSL context. + */ + ICat4::ICATPortBindingProxy ICat4Catalog::getICATProxy() + { + ICat4::ICATPortBindingProxy icat; + // Set the soap-endpoint of the catalog we want to use. + icat.soap_endpoint = ICat::Session::Instance().getSoapEndPoint().c_str(); + // Sets SSL authentication scheme + setSSLContext(icat); + return icat; + } } } From 86efd29bfa2917ae008a8038b251db831c1afcb9 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 14:09:48 +0000 Subject: [PATCH 121/403] Refs #6473. Initial functionality of running/stopping. Fitting itself is not done yet, is simulated by just loading files for now. --- .../MuonSequentialFitDialog.h | 32 ++++-- .../src/MuonSequentialFitDialog.cpp | 108 +++++++++++++----- 2 files changed, 105 insertions(+), 35 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 01ec2019017b..7ad68fca15e7 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -46,22 +46,24 @@ namespace MantidWidgets MuonSequentialFitDialog(MuonFitPropertyBrowser* parent); virtual ~MuonSequentialFitDialog(); - private: - enum ControlButtonType { - Start, - Stop + enum DialogState + { + Running, + Stopped }; + signals: + void stateChanged(DialogState newState); + + private: + // -- FUNCTIONS ----------------------------------------------------------- /// Check if all the input field are valid bool isInputValid(); - /// Set the type of the control button - void setControlButtonType(ControlButtonType type); - - /// Update enabled state off all the input widgets (except for control ones) - void setInputEnabled(bool enabled); + /// Set current dialog state + void setState(DialogState newState); /// Initialize diagnosis table void initDiagnosisTable(); @@ -74,6 +76,12 @@ namespace MantidWidgets /// Fit properties browser used to start the dialog MuonFitPropertyBrowser* m_fitPropBrowser; + /// Current state of the dialog + DialogState m_state; + + /// Whether user requested fitting to be stopped + bool m_stopRequested; + // -- STATIC MEMBERS ------------------------------------------------------ /// Checks if specified name is valid as a name for label. @@ -89,6 +97,12 @@ namespace MantidWidgets /// Enables/disables start button depending on wether we are allowed to start void updateControlButtonState(); + /// Sets control button to be start/stop depending on new dialog state + void updateControlButtonType(DialogState newState); + + /// Update enabled state off all the input widgets depending on new dialog state + void updateInputEnabled(DialogState newState); + /// Start fitting process void startFit(); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index b616ed96a55b..d3e6b6c5d12e 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -21,15 +21,16 @@ namespace MantidWidgets m_ui.setupUi(this); // TODO: set initial values - setControlButtonType(Start); - initDiagnosisTable(); + setState(Stopped); // After initial values are set, update depending elements accordingly. We don't rely on // slot/signal update, as element might be left with default values which means these will // never be called on initialication. updateLabelError( m_ui.labelInput->text() ); updateControlButtonState(); + updateControlButtonType(m_state); + updateInputEnabled(m_state); connect( m_ui.labelInput, SIGNAL( textChanged(const QString&) ), this, SLOT( updateLabelError(const QString&) ) ); @@ -38,8 +39,19 @@ namespace MantidWidgets this, SLOT( updateControlButtonState() ) ); connect( m_ui.runs, SIGNAL( fileFindingFinished() ), this, SLOT( updateControlButtonState() ) ); + + connect( this, SIGNAL( stateChanged(DialogState) ), + this, SLOT( updateControlButtonType(DialogState) ) ); + connect( this, SIGNAL( stateChanged(DialogState) ), + this, SLOT( updateInputEnabled(DialogState) ) ); } + /** + * Destructor + */ + MuonSequentialFitDialog::~MuonSequentialFitDialog() + {} + /** * Checks if specified name is valid as a name for label. * @param label :: The name to check @@ -73,8 +85,7 @@ namespace MantidWidgets m_ui.diagnosisTable->setHorizontalHeaderLabels(headerLabels); // Make the table fill all the available space - QHeaderView* header = m_ui.diagnosisTable->horizontalHeader(); - header->setResizeMode(QHeaderView::Stretch); + m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); } /** @@ -114,35 +125,45 @@ namespace MantidWidgets } /** - * Set the type of the control button. It is Start button when fitting has not been started, - * and Stop button when fitting is running. - * @param type :: New type of the button + * Sets control button to be start/stop depending on new dialog state. + * @param newState :: New state of the dialog */ - void MuonSequentialFitDialog::setControlButtonType(ControlButtonType type) + void MuonSequentialFitDialog::updateControlButtonType(DialogState newState) { // Disconnect everything connected to pressed() signal of the button disconnect( m_ui.controlButton, SIGNAL( pressed() ), 0, 0); // Connect to appropriate slot - auto buttonSlot = (type == Start) ? SLOT( startFit() ) : SLOT( stopFit() ); + auto buttonSlot = (newState == Stopped) ? SLOT( startFit() ) : SLOT( stopFit() ); connect( m_ui.controlButton, SIGNAL( pressed() ), this, buttonSlot ); // Set appropriate text - QString buttonText = (type == Start) ? "Start" : "Stop"; + QString buttonText = (newState == Stopped) ? "Start" : "Stop"; m_ui.controlButton->setText(buttonText); } - /** * Update enabled state off all the input widgets (except for control ones). - * @param enabled :: True if widgets should be enabled, false otherwise + /** + * Updates current state of the dialog. */ - void MuonSequentialFitDialog::setInputEnabled(bool enabled) + void MuonSequentialFitDialog::setState(DialogState newState) { + m_state = newState; + emit stateChanged(newState); + } + + /** + * Update enabled state off all the input widgets depending on new dialog state. + * @param newState :: New state of the dialog + */ + void MuonSequentialFitDialog::updateInputEnabled(DialogState newState) + { + bool enabled = (newState == Stopped); + m_ui.runs->setEnabled(enabled); m_ui.labelInput->setEnabled(enabled); foreach(QAbstractButton* button, m_ui.paramTypeGroup->buttons()) button->setEnabled(enabled); - } /** @@ -150,9 +171,49 @@ namespace MantidWidgets */ void MuonSequentialFitDialog::startFit() { - g_log.notice("Seq. fitting started"); - setControlButtonType(Stop); - setInputEnabled(false); + if ( m_state == Running ) + throw std::runtime_error("Couln't start: already running"); + + QStringList runFilenames = m_ui.runs->getFilenames(); + + // Tell progress bar how many iterations we will need to make and reset it + m_ui.progress->setRange( 0, runFilenames.size() ); + m_ui.progress->setValue(0); + + setState(Running); + m_stopRequested = false; + + for ( auto runIt = runFilenames.constBegin(); runIt != runFilenames.constEnd(); ++runIt ) + { + // Process events (so that Stop button press is processed) + QApplication::processEvents(); + + if ( m_stopRequested ) + { + setState(Stopped); + return; + } + + // Update progress + m_ui.progress->setValue( m_ui.progress->value() + 1 ); + + try + { + // TODO: should be MuonLoad here + IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); + loadAlg->initialize(); + loadAlg->setPropertyValue( "Filename", runIt->toStdString() ); + loadAlg->setPropertyValue( "OutputWorkspace", "Loaded" ); + loadAlg->execute(); + } + catch(std::exception) + { + // TODO: probably should show QMEssageBox + setState(Stopped); + } + } + + setState(Stopped); } /** @@ -160,16 +221,11 @@ namespace MantidWidgets */ void MuonSequentialFitDialog::stopFit() { - g_log.notice("Seq. fitting stopped"); - setControlButtonType(Start); - setInputEnabled(true); - } + if ( m_state != Running ) + throw std::runtime_error("Coulnd't stop: is not running"); - /** - * Destructor - */ - MuonSequentialFitDialog::~MuonSequentialFitDialog() - {} + m_stopRequested = true; + } } // namespace MantidWidgets } // namespace Mantid From 490bb22cfda2ce55873aa1f10169d5c854d6fd83 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Tue, 10 Dec 2013 14:48:45 +0000 Subject: [PATCH 122/403] Refs #8176 Fix outputting to log. --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index 3564da58a783..ffdbbc9f26a9 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -93,7 +93,7 @@ def PyExec(self): #build table of values for data in output: tableWs.addRow(list(data)) - logger.information(name + ": " + value) + logger.information(': '.join(list(data))) #remove idf/ipf workspace DeleteWorkspace(workspace) From 254d7579796c2120456b3c06917906f615ca2f64 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Tue, 10 Dec 2013 15:22:13 +0000 Subject: [PATCH 123/403] Add unit test to test new property re #8546 Signed-off-by: Karl Palmen --- .../DataHandling/test/LoadParameterFileTest.h | 101 +++++++++++++++--- 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h index 5c16406ed974..b92b1fdbf314 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h @@ -30,24 +30,9 @@ class LoadParameterFileTest : public CxxTest::TestSuite void testExecIDF_for_unit_testing2() // IDF stands for Instrument Definition File { - LoadInstrument loaderIDF2; - - TS_ASSERT_THROWS_NOTHING(loaderIDF2.initialize()); - - //create a workspace with some sample data - wsName = "LoadParameterFileTestIDF2"; - Workspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D",1,1,1); - Workspace2D_sptr ws2D = boost::dynamic_pointer_cast(ws); - - //put this workspace in the data service - TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add(wsName, ws2D)); - // Path to test input file assumes Test directory checked out from SVN - loaderIDF2.setPropertyValue("Filename", "IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml"); - //inputFile = loaderIDF2.getPropertyValue("Filename"); - loaderIDF2.setPropertyValue("Workspace", wsName); - TS_ASSERT_THROWS_NOTHING(loaderIDF2.execute()); - TS_ASSERT( loaderIDF2.isExecuted() ); + // Create workspace wsName + load_IDF2(); // load in additional parameters LoadParameterFile loaderPF; @@ -91,6 +76,88 @@ class LoadParameterFileTest : public CxxTest::TestSuite } + void testExec_withIDFString() // Test use of string instead of file + { + + // Create workspace + load_IDF2(); + + // Define parameter XML string + std::string parameterXML = + "" + "" + " " + " " + " " + " " + " " + " " + ""; + + // load in additional parameters + LoadParameterFile loaderPF; + TS_ASSERT_THROWS_NOTHING(loaderPF.initialize()); + loaderPF.setPropertyValue("ParameterXML", parameterXML); + loaderPF.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderPF.execute()); + TS_ASSERT( loaderPF.isExecuted() ); + + // Get back the saved workspace + MatrixWorkspace_sptr output; + TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieveWS(wsName)); + + ParameterMap& paramMap = output->instrumentParameters(); + boost::shared_ptr i = output->getInstrument(); + boost::shared_ptr ptrDet = i->getDetector(1008); + TS_ASSERT_EQUALS( ptrDet->getID(), 1008); + TS_ASSERT_EQUALS( ptrDet->getName(), "combined translation6"); + Parameter_sptr param = paramMap.get(&(*ptrDet), "fjols"); + TS_ASSERT_DELTA( param->value(), 20.0, 0.0001); + param = paramMap.get(&(*ptrDet), "nedtur"); + TS_ASSERT_DELTA( param->value(), 77.0, 0.0001); + param = paramMap.get(&(*ptrDet), "fjols-test-paramfile"); + TS_ASSERT_DELTA( param->value(), 52.0, 0.0001); + + std::vector dummy = paramMap.getDouble("nickel-holder", "klovn"); + TS_ASSERT_DELTA( dummy[0], 1.0, 0.0001); + dummy = paramMap.getDouble("nickel-holder", "pos"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "rot"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "taabe"); + TS_ASSERT_DELTA (dummy[0], 200.0, 0.0001); + dummy = paramMap.getDouble("nickel-holder", "mistake"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "fjols-test-paramfile"); + TS_ASSERT_DELTA (dummy[0], 2010.0, 0.0001); + + AnalysisDataService::Instance().remove(wsName); + + } + + void load_IDF2() + { + LoadInstrument loaderIDF2; + + TS_ASSERT_THROWS_NOTHING(loaderIDF2.initialize()); + + //create a workspace with some sample data + wsName = "LoadParameterFileTestIDF2"; + Workspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D",1,1,1); + Workspace2D_sptr ws2D = boost::dynamic_pointer_cast(ws); + + //put this workspace in the data service + TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add(wsName, ws2D)); + + // Path to test input file assumes Test directory checked out from git + loaderIDF2.setPropertyValue("Filename", "IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml"); + //inputFile = loaderIDF2.getPropertyValue("Filename"); + loaderIDF2.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderIDF2.execute()); + TS_ASSERT( loaderIDF2.isExecuted() ); + + } + private: std::string inputFile; From 9d5ea6ea5fea39d15816df2ef7fdffc3287b1681 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 10 Dec 2013 11:13:21 -0500 Subject: [PATCH 124/403] Re #841. Changed the Mutex raw pointer in Task to a boost::shared_ptr. --- .../DataHandling/src/LoadEventNexus.cpp | 6 ++-- .../Framework/Kernel/inc/MantidKernel/Task.h | 11 ++++--- .../inc/MantidKernel/ThreadSchedulerMutexes.h | 12 +++---- .../Kernel/src/ThreadPoolRunnable.cpp | 4 +-- Code/Mantid/Framework/Kernel/test/TaskTest.h | 3 +- .../Framework/Kernel/test/ThreadPoolTest.h | 4 +-- .../Kernel/test/ThreadSchedulerMutexesTest.h | 32 +++++++++---------- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp index e9ec91e827c9..4de40493faca 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp @@ -452,7 +452,7 @@ class LoadBankFromDiskTask : public Task */ LoadBankFromDiskTask(LoadEventNexus * alg, const std::string& entry_name, const std::string & entry_type, const std::size_t numEvents, const bool oldNeXusFileNames, - Progress * prog, Mutex * ioMutex, ThreadScheduler * scheduler) + Progress * prog, boost::shared_ptr ioMutex, ThreadScheduler * scheduler) : Task(), alg(alg), entry_name(entry_name), entry_type(entry_type), pixelID_to_wi_vector(alg->pixelID_to_wi_vector), pixelID_to_wi_offset(alg->pixelID_to_wi_offset), @@ -1606,7 +1606,7 @@ void LoadEventNexus::loadEvents(API::Progress * const prog, const bool monitors) // Make the thread pool ThreadScheduler * scheduler = new ThreadSchedulerMutexes(); ThreadPool pool(scheduler); - Mutex * diskIOMutex = new Mutex(); + boost::shared_ptr diskIOMutex(new Mutex()); size_t bank0 = 0; size_t bankn = bankNames.size(); @@ -1680,7 +1680,7 @@ void LoadEventNexus::loadEvents(API::Progress * const prog, const bool monitors) } // Start and end all threads pool.joinAll(); - delete diskIOMutex; + diskIOMutex.reset(); delete prog2; diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h index 7510a502883f..2446ff10feb4 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h @@ -1,6 +1,7 @@ #ifndef MANTID_KERNEL_TASK_H_ #define MANTID_KERNEL_TASK_H_ +#include #include "MantidKernel/DllConfig.h" #include "MantidKernel/Exception.h" #include "MantidKernel/MultiThreaded.h" @@ -27,7 +28,7 @@ namespace Kernel //--------------------------------------------------------------------------------------------- /** Default constructor */ Task() : - m_cost(1.0), m_mutex(NULL) + m_cost(1.0) { } //--------------------------------------------------------------------------------------------- @@ -36,7 +37,7 @@ namespace Kernel * @param cost :: computational cost */ Task(double cost) : - m_cost(cost), m_mutex(NULL) + m_cost(cost) { } /// Destructor @@ -73,7 +74,7 @@ namespace Kernel /** Get the mutex object for this Task * @return Mutex pointer, or NULL */ - Mutex * getMutex() + boost::shared_ptr getMutex() { return m_mutex; } @@ -82,7 +83,7 @@ namespace Kernel /** Set the mutex object for this Task * @param mutex :: Mutex pointer, or NULL */ - void setMutex(Mutex * mutex) + void setMutex( boost::shared_ptr &mutex) { m_mutex = mutex; } @@ -94,7 +95,7 @@ namespace Kernel double m_cost; /// Mutex associated with this task (can be NULL) - Mutex * m_mutex; + boost::shared_ptr m_mutex; }; diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ThreadSchedulerMutexes.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ThreadSchedulerMutexes.h index fe0b452f2723..d9257d81bfae 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ThreadSchedulerMutexes.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ThreadSchedulerMutexes.h @@ -45,7 +45,7 @@ namespace Kernel m_queueLock.lock(); m_cost += newTask->cost(); - Mutex * mut = newTask->getMutex(); + boost::shared_ptr mut = newTask->getMutex(); m_supermap[mut].insert( std::pair(newTask->cost(), newTask) ); m_queueLock.unlock(); } @@ -68,7 +68,7 @@ namespace Kernel for (; it != it_end; ++it) { // The key is the mutex associated with the inner map - Mutex * mapMutex = it->first; + boost::shared_ptr mapMutex = it->first; if ((!mapMutex) || (m_mutexes.empty()) || (m_mutexes.find(mapMutex) == m_mutexes.end())) { // The mutex of this map is free! @@ -112,7 +112,7 @@ namespace Kernel // --- Add the mutex (if any) to the list of "busy" ones --- if (temp) { - Mutex * mut = temp->getMutex(); + boost::shared_ptr mut = temp->getMutex(); if (mut) m_mutexes.insert(mut); } @@ -134,7 +134,7 @@ namespace Kernel virtual void finished(Task * task, size_t threadnum) { UNUSED_ARG(threadnum); - Mutex * mut = task->getMutex(); + boost::shared_ptr mut = task->getMutex(); if (mut) { m_queueLock.lock(); @@ -199,14 +199,14 @@ namespace Kernel /// Map to tasks, sorted by cost typedef std::multimap InnerMap; /// Map to maps, sorted by Mutex* - typedef std::map SuperMap; + typedef std::map, InnerMap> SuperMap; /** A super map; first key = a Mutex * * Inside it: second key = the cost. */ SuperMap m_supermap; /// Vector of currently used mutexes. - std::set m_mutexes; + std::set > m_mutexes; }; diff --git a/Code/Mantid/Framework/Kernel/src/ThreadPoolRunnable.cpp b/Code/Mantid/Framework/Kernel/src/ThreadPoolRunnable.cpp index f7864d35c234..472c33b2f0ba 100644 --- a/Code/Mantid/Framework/Kernel/src/ThreadPoolRunnable.cpp +++ b/Code/Mantid/Framework/Kernel/src/ThreadPoolRunnable.cpp @@ -64,8 +64,8 @@ namespace Kernel if (task) { //Task-specific mutex if specified? - Mutex * mutex = task->getMutex(); - if (mutex) + boost::shared_ptr mutex = task->getMutex(); + if (bool(mutex)) mutex->lock(); try diff --git a/Code/Mantid/Framework/Kernel/test/TaskTest.h b/Code/Mantid/Framework/Kernel/test/TaskTest.h index 8501325ef2bb..2ff51b38bcac 100644 --- a/Code/Mantid/Framework/Kernel/test/TaskTest.h +++ b/Code/Mantid/Framework/Kernel/test/TaskTest.h @@ -43,10 +43,9 @@ class TaskTest : public CxxTest::TestSuite void test_mutex() { MyTask t; - Mutex * mut = new Mutex(); + boost::shared_ptr mut(new Mutex()); t.setMutex(mut); TS_ASSERT_EQUALS( mut, t.getMutex() ); - delete mut; } diff --git a/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h b/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h index 5b1b174c630c..8406c3edc696 100644 --- a/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h +++ b/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h @@ -382,13 +382,13 @@ class ThreadPoolTest : public CxxTest::TestSuite TimeWaster mywaster; size_t num = 30000; mywaster.total = 0; - Mutex * lastMutex = NULL; + boost::shared_ptr lastMutex; for (size_t i=0; i<=num; i++) { Task * task = new FunctionTask( boost::bind(&TimeWaster::add_to_number, &mywaster, i), static_cast(i) ); // Create a new mutex every 1000 tasks. This is more relevant to the ThreadSchedulerMutexes; others ignore it. if (i % 1000 == 0) - lastMutex = new Mutex(); + lastMutex = boost::shared_ptr(new Mutex()); task->setMutex(lastMutex); p.schedule( task ); } diff --git a/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h b/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h index 19e78577ff7e..785aec542a0f 100644 --- a/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h +++ b/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h @@ -22,7 +22,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite class TaskWithMutex : public Task { public: - TaskWithMutex(Mutex * mutex, double cost) + TaskWithMutex(boost::shared_ptr mutex, double cost) { m_mutex = mutex; m_cost = cost; @@ -44,8 +44,8 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite void test_push() { ThreadSchedulerMutexes sc; - Mutex * mut1 = new Mutex(); - Mutex * mut2 = new Mutex(); + boost::shared_ptr mut1(new Mutex()); + boost::shared_ptr mut2(new Mutex()); TaskWithMutex * task1 = new TaskWithMutex(mut1, 10.0); TaskWithMutex * task2 = new TaskWithMutex(mut2, 9.0); @@ -56,23 +56,23 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite // delete task1; // delete task2; - delete mut1; - delete mut2; +// delete mut1; +// delete mut2; } void test_queue() { ThreadSchedulerMutexes sc; - Mutex * mut1 = new Mutex(); - Mutex * mut2 = new Mutex(); - Mutex * mut3 = new Mutex(); + boost::shared_ptr mut1(new Mutex()); + boost::shared_ptr mut2(new Mutex()); + boost::shared_ptr mut3(new Mutex()); TaskWithMutex * task1 = new TaskWithMutex(mut1, 10.0); TaskWithMutex * task2 = new TaskWithMutex(mut1, 9.0); TaskWithMutex * task3 = new TaskWithMutex(mut1, 8.0); TaskWithMutex * task4 = new TaskWithMutex(mut2, 7.0); TaskWithMutex * task5 = new TaskWithMutex(mut2, 6.0); TaskWithMutex * task6 = new TaskWithMutex(mut3, 5.0); - TaskWithMutex * task7 = new TaskWithMutex(NULL, 4.0); + TaskWithMutex * task7 = new TaskWithMutex(boost::shared_ptr(), 4.0); sc.push(task1); sc.push(task2); sc.push(task3); @@ -130,9 +130,9 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite // delete task5; // delete task6; // delete task7; - delete mut1; - delete mut2; - delete mut3; +// delete mut1; +// delete mut2; +// delete mut3; } void test_clear() @@ -140,7 +140,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite ThreadSchedulerMutexes sc; for (size_t i=0; i<10; i++) { - TaskWithMutex * task = new TaskWithMutex(new Mutex(), 10.0); + TaskWithMutex * task = new TaskWithMutex(boost::shared_ptr(new Mutex()), 10.0); sc.push(task); } TS_ASSERT_EQUALS(sc.size(), 10); @@ -155,7 +155,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite { ThreadSchedulerMutexes sc; Timer tim0; - Mutex * mut1 = new Mutex(); + boost::shared_ptr mut1(new Mutex()); size_t num = 500; for (size_t i=0; i < num; i++) { @@ -172,7 +172,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite //std::cout << tim1.elapsed() << " secs to pop." << std::endl; TS_ASSERT_EQUALS( sc.size(), 0); - delete mut1; +// delete mut1; } void test_performance_lotsOfMutexes() @@ -182,7 +182,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite size_t num = 500; for (size_t i=0; i < num; i++) { - sc.push(new TaskWithMutex(new Mutex(), 10.0)); + sc.push(new TaskWithMutex(boost::shared_ptr(new Mutex()), 10.0)); } //std::cout << tim0.elapsed() << " secs to push." << std::endl; TS_ASSERT_EQUALS( sc.size(), num); From f496828dd5bc5792f416635394ba42388b3e6557 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Tue, 10 Dec 2013 16:23:08 +0000 Subject: [PATCH 125/403] Add test for absence of file or string re #8546 Also correct the error message. Signed-off-by: Karl Palmen --- .../DataHandling/src/LoadParameterFile.cpp | 2 +- .../DataHandling/test/LoadParameterFileTest.h | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index d95efb1e5085..439e02a61f94 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -104,7 +104,7 @@ void LoadParameterFile::exec() // Check the two properties (at least one must be set) if( filename.empty() && parameterXMLProperty->isDefault()){ - throw Kernel::Exception::FileError("Either the Filename or ParameterXML property of LoadInstrument most be specified to load an IDF" , filename); + throw Kernel::Exception::FileError("Either the Filename or ParameterXML property of LoadParameterFile most be specified to load an IDF" , filename); } // Get the input workspace diff --git a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h index b92b1fdbf314..e6efa9b134b0 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h @@ -135,6 +135,19 @@ class LoadParameterFileTest : public CxxTest::TestSuite } + void test_failure_if_no_file_or_string() + { + // Create workspace + load_IDF2(); + + // Run algorithm without file or string properties set + LoadParameterFile loaderPF; + TS_ASSERT_THROWS_NOTHING(loaderPF.initialize()); + loaderPF.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderPF.execute()); + TS_ASSERT( ! loaderPF.execute() ) + } + void load_IDF2() { LoadInstrument loaderIDF2; From e64d67e8c09fa9d129e542568c3bb4e7ff1e13ca Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Tue, 10 Dec 2013 16:43:39 +0000 Subject: [PATCH 126/403] Remove TubeCalibDemoMaps_Simple.py re #8263 Signed-off-by: Karl Palmen --- .../Examples/TubeCalibDemoMaps_Simple.py | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMaps_Simple.py diff --git a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMaps_Simple.py b/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMaps_Simple.py deleted file mode 100644 index b975b9d991d8..000000000000 --- a/Code/Mantid/scripts/Calibration/Examples/TubeCalibDemoMaps_Simple.py +++ /dev/null @@ -1,72 +0,0 @@ -# -# TUBE CALIBRATION DEMONSTRATION PROGRAM FOR MAPS -# -# This is a simple example for running calibration for and calibration run of MAPS. -# It uses the CalibrateMaps function - -# -import tube -from tube_calib_fit_params import TubeCalibFitParams - -def CalibrateMaps( RunNumber ): - ''' - RunNumber is the run number for the calibration. - ''' - - # == Set parameters for calibration == - previousDefaultInstrument = config['default.instrument'] - config['default.instrument']="MAPS" - filename = str(RunNumber) # Name of calibration run - print "Filename",filename - rangeLower = 2000 # Integrate counts in each spectra from rangeLower to rangeUpper - rangeUpper = 10000 # - - # Set initial parameters for peak finding - ExpectedHeight = -1000.0 # Expected Height of Gaussian Peaks (initial value of fit parameter) - ExpectedWidth = 8.0 # Expected width of Gaussian peaks in pixels (initial value of fit parameter) - ExpectedPositions = [4.0, 85.0, 128.0, 165.0, 252.0] #Expected positions of the edges and Gaussian peaks in pixels (initial values of fit parameters) - - # Set what we want to calibrate (e.g whole intrument or one door ) - CalibratedComponent = 'MAPS' # Calibrate all - - - # Get calibration raw file and integrate it - rawCalibInstWS = Load(filename) #'raw' in 'rawCalibInstWS' means unintegrated. - print "Integrating Workspace" - CalibInstWS = Integration( rawCalibInstWS, RangeLower=rangeLower, RangeUpper=rangeUpper ) - DeleteWorkspace(rawCalibInstWS) - print "Created workspace (CalibInstWS) with integrated data from run and instrument to calibrate" - - # == Create Objects needed for calibration == - - # First array gives positions in Metres and second array gives type 1=Gaussian peak 2=edge. - # An intelligent guess is used here that is not correct for all tubes. - knownPos, funcForm = [-0.50,-0.16,-0.00, 0.16, 0.50 ],[2,1,1,1,2] - - # Get fitting parameters - fitPar = TubeCalibFitParams( ExpectedPositions, ExpectedHeight, ExpectedWidth) - fitPar.setAutomatic(True) - - print "Created objects needed for calibration." - - # == Get the calibration and put results into calibration table == - calibrationTable, peakTable = tube.calibrate(CalibInstWS, CalibratedComponent, - knownPos, funcForm, fitPar = fitPar, - outputPeak=True) - print "Got calibration (new positions of detectors) " - - # == Apply the Calibation == - ApplyCalibration( Workspace=CalibInstWS, PositionTable=calibrationTable) - print "Applied calibration" - - - # == Save workspace == - SaveNexusProcessed( CalibInstWS, 'TubeCalibDemoMapsResult.nxs',"Result of Running MAPS Calibration") - print "saved calibrated workspace (CalibInstWS) into Nexus file TubeCalibDemoMapsResult.nxs" - - # == Reset dafault instrument == - config['default.instrument'] = previousDefaultInstrument - - # ==== End of CalibrateMaps() ==== - -CalibrateMaps( 14919 ) #found at \\isis\inst$\NDXMAPS\Instrument\data\cycle_09_5 From d6b9b7694d9e54eb1f849ba96d6e32c4e9a86dd9 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:04:18 +0000 Subject: [PATCH 127/403] Refs #6473. FitPropertyBrowser: make method public. This is quite a useful method for leaving decision on which function exactly to use for fit to the property browser. --- .../inc/MantidQtMantidWidgets/FitPropertyBrowser.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h index 648f2aa8e44f..ab21560ff6de 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h @@ -96,8 +96,13 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS FitPropertyBrowser: public QDockWidget, /// Create a new function PropertyHandler* addFunction(const std::string& fnName); + /// Get Composite Function boost::shared_ptr compositeFunction()const{return m_compositeFunction;} + + /// Return the fitting function + Mantid::API::IFunction_sptr getFittingFunction() const; + /// Get the default function type std::string defaultFunctionType()const; /// Set the default function type @@ -209,6 +214,7 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS FitPropertyBrowser: public QDockWidget, /// Create a MatrixWorkspace from a TableWorkspace Mantid::API::Workspace_sptr createMatrixFromTableWorkspace()const; + public slots: virtual void fit(){ doFit(500); } virtual void sequentialFit(); @@ -337,8 +343,6 @@ private slots: void minimizerChanged(); /// Do the fitting void doFit(int maxIterations); - /// Return the fitting function - Mantid::API::IFunction_sptr getFittingFunction() const; /// Property managers: QtGroupPropertyManager *m_groupManager; From b0544f1d428cffa804ac769024be4c98299fe77b Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:05:45 +0000 Subject: [PATCH 128/403] Refs #6473. Function for getting run title from workspace. --- .../MuonSequentialFitDialog.h | 5 ++++ .../src/MuonSequentialFitDialog.cpp | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 7ad68fca15e7..1dde6aec89aa 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -14,6 +14,8 @@ namespace MantidQt { namespace MantidWidgets { + using namespace Mantid::Kernel; + using namespace Mantid::API; /** MuonSequentialFitDialog : TODO: DESCRIPTION @@ -87,6 +89,9 @@ namespace MantidWidgets /// Checks if specified name is valid as a name for label. static std::string isValidLabel(const std::string& label); + /// Returns displayable title for the given workspace + static std::string getRunTitle(Workspace_const_sptr ws); + /// Instance used to print log messages static Mantid::Kernel::Logger& g_log; diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index d3e6b6c5d12e..7e409dac1b35 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -65,6 +65,29 @@ namespace MantidWidgets return AnalysisDataService::Instance().isValid(label); } + /** + * Returns displayable title for the given workspace; + * @param ws :: Workpspace to get title from + * @return The title, or empty string if unable to get one + */ + std::string MuonSequentialFitDialog::getRunTitle(Workspace_const_sptr ws) + { + auto matrixWS = boost::dynamic_pointer_cast(ws); + + if ( ! matrixWS ) + return ""; + + const std::string& instrName = matrixWS->getInstrument()->getName(); + const int runNumber = matrixWS->getRunNumber(); + + if ( instrName.empty() || runNumber == 0 ) + return ""; + + std::ostringstream runTitle; + runTitle << instrName << runNumber; + return runTitle.str(); + } + /** * Initialize diagnosis table. */ From 15f02a8cd7f23c5718d7ef59c414a583bfdd1cb3 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:10:06 +0000 Subject: [PATCH 129/403] Refs #6473. Using better way to get fitting function. --- .../MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 7e409dac1b35..a439f7ca0d73 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -99,7 +99,7 @@ namespace MantidWidgets headerLabels << "Run" << "Fit quality"; // Add remaining columns - one for every fit function parameter - CompositeFunction_const_sptr fitFunc = m_fitPropBrowser->compositeFunction(); + IFunction_sptr fitFunc = m_fitPropBrowser->getFittingFunction(); for(size_t i = 0; i < fitFunc->nParams(); i++) headerLabels << QString::fromStdString( fitFunc->parameterName(i) ); From 8223861b79c36a82e913642c8800b455f7b301a2 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:10:27 +0000 Subject: [PATCH 130/403] Refs #6473. Setting initial values for inputs. --- .../MantidWidgets/src/MuonSequentialFitDialog.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index a439f7ca0d73..48a2ce2e3cb4 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -20,10 +20,17 @@ namespace MantidWidgets { m_ui.setupUi(this); - // TODO: set initial values - initDiagnosisTable(); setState(Stopped); + // Set initial runs text + Workspace_const_sptr fitWS = m_fitPropBrowser->getWorkspace(); + m_ui.runs->setText( QString::fromStdString( getRunTitle(fitWS) ) + "-" ); + + // TODO: find a better initial one, e.g. previously used + m_ui.labelInput->setText("Label"); + + initDiagnosisTable(); + // After initial values are set, update depending elements accordingly. We don't rely on // slot/signal update, as element might be left with default values which means these will // never be called on initialication. From e9e10a3f9661f1e3d672f2d7c9fd82abda9b7eab Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:14:05 +0000 Subject: [PATCH 131/403] Refs #6473. Minor refactoring. --- .../src/MuonSequentialFitDialog.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 48a2ce2e3cb4..3ff70aa4b177 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -213,17 +213,16 @@ namespace MantidWidgets setState(Running); m_stopRequested = false; - for ( auto runIt = runFilenames.constBegin(); runIt != runFilenames.constEnd(); ++runIt ) + for ( auto fileIt = runFilenames.constBegin(); fileIt != runFilenames.constEnd(); ++fileIt ) { // Process events (so that Stop button press is processed) QApplication::processEvents(); + // Stop if requested by user if ( m_stopRequested ) - { - setState(Stopped); - return; - } + break; + Workspace_sptr loadedWS; // Update progress m_ui.progress->setValue( m_ui.progress->value() + 1 ); @@ -231,15 +230,22 @@ namespace MantidWidgets { // TODO: should be MuonLoad here IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); + loadAlg->setChild(true); loadAlg->initialize(); - loadAlg->setPropertyValue( "Filename", runIt->toStdString() ); - loadAlg->setPropertyValue( "OutputWorkspace", "Loaded" ); + loadAlg->setPropertyValue( "Filename", fileIt->toStdString() ); + loadAlg->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used loadAlg->execute(); + + loadedWS = loadAlg->getProperty("OutputWorkspace"); + } + catch(std::exception& e) + { + QMessageBox::critical(this, "Loading failed", + "Unable to load one of the files.\n\nCheck log for details"); + g_log.error(e.what()); + break; } - catch(std::exception) { - // TODO: probably should show QMEssageBox - setState(Stopped); } } From 25c011f3855492ca25982b0d42805b2a353fc547 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:14:36 +0000 Subject: [PATCH 132/403] Refs #6473. Initial fitting implementation. --- .../src/MuonSequentialFitDialog.cpp | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 3ff70aa4b177..05abeeeffea3 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -204,10 +204,25 @@ namespace MantidWidgets if ( m_state == Running ) throw std::runtime_error("Couln't start: already running"); + const std::string label = m_ui.labelInput->text().toStdString(); + const std::string labelGroupName = "MuonSeqFit_" + label; + + AnalysisDataServiceImpl& ads = AnalysisDataService::Instance(); + + if ( ads.doesExist(labelGroupName) ) + { + // TODO: confirm that + ads.deepRemoveGroup(labelGroupName); + } + + // Create a group for label + ads.add(labelGroupName, boost::make_shared()); + QStringList runFilenames = m_ui.runs->getFilenames(); // Tell progress bar how many iterations we will need to make and reset it m_ui.progress->setRange( 0, runFilenames.size() ); + m_ui.progress->setFormat("%p%"); m_ui.progress->setValue(0); setState(Running); @@ -223,8 +238,6 @@ namespace MantidWidgets break; Workspace_sptr loadedWS; - // Update progress - m_ui.progress->setValue( m_ui.progress->value() + 1 ); try { @@ -245,8 +258,53 @@ namespace MantidWidgets g_log.error(e.what()); break; } + + MatrixWorkspace_sptr ws; + + if ( auto single = boost::dynamic_pointer_cast(loadedWS) ) + { + ws = single; + } + else if ( auto group = boost::dynamic_pointer_cast(loadedWS) ) { + auto first = boost::dynamic_pointer_cast( group->getItem(0) ); + ws = first; } + + const std::string runTitle = getRunTitle(ws); + const std::string wsBaseName = labelGroupName + "_" + runTitle; + + try + { + IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); + fit->initialize(); + fit->setProperty("Function", m_fitPropBrowser->getFittingFunction()); + fit->setProperty("InputWorkspace", ws); + fit->setProperty("WorkspaceIndex", 0); + fit->setProperty("StartX", m_fitPropBrowser->startX()); + fit->setProperty("EndX", m_fitPropBrowser->endX()); + fit->setProperty("Output", wsBaseName); + fit->setProperty("Minimizer", m_fitPropBrowser->minimizer()); + fit->setProperty("CostFunction", m_fitPropBrowser->costFunction()); + fit->execute(); + } + catch(std::exception& e) + { + QMessageBox::critical(this, "Fitting failed", + "Unable to fit one of the files.\n\nCheck log for details"); + g_log.error(e.what()); + break; + } + + // Make sure created fit workspaces end-up in the group + // TODO: this really should use loop + ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix"); + ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); + ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); + + // Update progress + m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) ); + m_ui.progress->setValue( m_ui.progress->value() + 1 ); } setState(Stopped); From b8a1ee38f0d1497d71d910aa01e172c0223e8e36 Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 17:15:18 +0000 Subject: [PATCH 133/403] Fix broken tests. Refs #8581. --- Code/Mantid/Framework/ICat/test/ICatTestHelper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Mantid/Framework/ICat/test/ICatTestHelper.cpp b/Code/Mantid/Framework/ICat/test/ICatTestHelper.cpp index bd0060d3952b..598b9b408dd5 100644 --- a/Code/Mantid/Framework/ICat/test/ICatTestHelper.cpp +++ b/Code/Mantid/Framework/ICat/test/ICatTestHelper.cpp @@ -10,6 +10,8 @@ namespace ICatTestHelper loginobj.initialize(); loginobj.setPropertyValue("Username", "mantid_test"); loginobj.setPropertyValue("Password", "mantidtestuser"); + loginobj.setPropertyValue("FacilityName", "ISIS"); + loginobj.execute(); if (!loginobj.isExecuted()) { From c1e1a2f9db02d2c984c6c6e8be102259b90ffb5a Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Tue, 10 Dec 2013 15:57:51 +0000 Subject: [PATCH 134/403] refs #8588. move algorithm_decorator into own module. --- .../ReflectometryReductionOneTest.py | 52 +--------------- .../test/testhelpers/CMakeLists.txt | 1 + .../test/testhelpers/algorithm_decorator.py | 61 +++++++++++++++++++ 3 files changed, 63 insertions(+), 51 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/testhelpers/algorithm_decorator.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index 5b72284d0046..e8da251aae62 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -1,59 +1,9 @@ import unittest from mantid.simpleapi import * +from testhelpers.algorithm_decorator import make_decorator import mantid.api - -import inspect -import re import math -def make_decorator(algorithm_to_decorate): - """ - Dynamically create a builder pattern style decorator around a Mantid algorithm. - This allows you to separate out setting algorithm parameters from the actual method execution. Parameters may be reset multiple times. - """ - - class Decorator(object): - - def __init__(self, alg_subject): - self.__alg_subject = alg_subject - self.__parameters__ = dict() - - def execute(self, additional=None, verbose=False): - if verbose: - print "Algorithm Parameters:" - print self.__parameters__ - print - out = self.__alg_subject(**self.__parameters__) - return out - - def set_additional(self, additional): - self.__parameters__.update(**additional) - - def add_getter_setter(type, name): - - def setter(self, x): - self.__parameters__[name] = x - - def getter(self): - return self.__parameters__[name] - - setattr(type, "set_" + name, setter) - setattr(type, "get_" + name, getter) - - - argspec = inspect.getargspec(algorithm_to_decorate) - for parameter in argspec.varargs.split(','): - m = re.search('(^\w+)', parameter) # Take the parameter key part from the defaults given as 'key=value' - if m: - parameter = m.group(0).strip() - m = re.search('\w+$', parameter) # strip off any leading numerical values produced by argspec - if m: - parameter = m.group(0).strip() - add_getter_setter(Decorator, m.group(0).strip()) - - return Decorator(algorithm_to_decorate) - - class ReflectometryReductionOneTest(unittest.TestCase): def construct_standard_algorithm(self): diff --git a/Code/Mantid/Framework/PythonInterface/test/testhelpers/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/testhelpers/CMakeLists.txt index 1da906f087d7..487f06eda1dc 100644 --- a/Code/Mantid/Framework/PythonInterface/test/testhelpers/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/testhelpers/CMakeLists.txt @@ -4,6 +4,7 @@ set ( PY_FILES __init__.py + algorithm_decorator.py ) # Copy python files to output directory diff --git a/Code/Mantid/Framework/PythonInterface/test/testhelpers/algorithm_decorator.py b/Code/Mantid/Framework/PythonInterface/test/testhelpers/algorithm_decorator.py new file mode 100644 index 000000000000..91c0fd54546d --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/testhelpers/algorithm_decorator.py @@ -0,0 +1,61 @@ +import inspect +import re + +def make_decorator(algorithm_to_decorate): + """ + Dynamically create a builder pattern style decorator around a Mantid algorithm. + This allows you to separate out setting algorithm parameters from the actual method execution. Parameters may be reset multiple times. + + Usage: + rebin = make_decorator(Rebin) + rebin.set_Params([0, 0.1, 1]) + .... + rebin.execute() + + Arguments: + algorithm_to_decorate: The mantid.simpleapi algorithm to decorate. + + + + """ + + class Decorator(object): + + def __init__(self, alg_subject): + self.__alg_subject = alg_subject + self.__parameters__ = dict() + + def execute(self, additional=None, verbose=False): + if verbose: + print "Algorithm Parameters:" + print self.__parameters__ + print + out = self.__alg_subject(**self.__parameters__) + return out + + def set_additional(self, additional): + self.__parameters__.update(**additional) + + def add_getter_setter(type, name): + + def setter(self, x): + self.__parameters__[name] = x + + def getter(self): + return self.__parameters__[name] + + setattr(type, "set_" + name, setter) + setattr(type, "get_" + name, getter) + + + argspec = inspect.getargspec(algorithm_to_decorate) + for parameter in argspec.varargs.split(','): + m = re.search('(^\w+)', parameter) # Take the parameter key part from the defaults given as 'key=value' + if m: + parameter = m.group(0).strip() + m = re.search('\w+$', parameter) # strip off any leading numerical values produced by argspec + if m: + parameter = m.group(0).strip() + add_getter_setter(Decorator, m.group(0).strip()) + + return Decorator(algorithm_to_decorate) From a8de94de11424ae4458d1c2526c40ed91e61757e Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 17:51:29 +0000 Subject: [PATCH 135/403] Refs #6473. Diagnosis table is being populated now. --- .../MuonSequentialFitDialog.h | 4 +++ .../src/MuonSequentialFitDialog.cpp | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 1dde6aec89aa..4d4f5477dacf 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -70,6 +70,10 @@ namespace MantidWidgets /// Initialize diagnosis table void initDiagnosisTable(); + /// Add a new entry to the diagnosis table + void addDiagnosisEntry(const std::string& runTitle, double fitQuality, + IFunction_sptr fittedFunction); + // -- VARIABLES ----------------------------------------------------------- /// UI form diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 05abeeeffea3..134b2748a230 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -118,6 +118,30 @@ namespace MantidWidgets m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); } + /** + * Add a new entry to the diagnosis table. + * @param runTitle :: Title of the run fitted + * @param fitQuality :: Number representing a goodness of the fit + * @param fittedFunction :: Function containing fitted parameters + */ + void MuonSequentialFitDialog::addDiagnosisEntry(const std::string& runTitle, double fitQuality, + IFunction_sptr fittedFunction) + { + int newRow = m_ui.diagnosisTable->rowCount(); + + m_ui.diagnosisTable->insertRow(newRow); + + m_ui.diagnosisTable->setItem(newRow, 0, new QTableWidgetItem( QString::fromStdString(runTitle) ) ); + m_ui.diagnosisTable->setItem(newRow, 1, new QTableWidgetItem( QString::number(fitQuality) ) ); + + for(int i = 2; i < m_ui.diagnosisTable->columnCount(); ++i) + { + std::string paramName = m_ui.diagnosisTable->horizontalHeaderItem(i)->text().toStdString(); + double value = fittedFunction->getParameter(paramName); + m_ui.diagnosisTable->setItem(newRow, i, new QTableWidgetItem( QString::number(value) ) ); + } + } + /** * Updates visibility/tooltip of label error asterisk. * @param label :: New label as specified by user @@ -225,6 +249,9 @@ namespace MantidWidgets m_ui.progress->setFormat("%p%"); m_ui.progress->setValue(0); + // Clear diagnosis table for new fit + m_ui.diagnosisTable->setRowCount(0); + setState(Running); m_stopRequested = false; @@ -274,6 +301,8 @@ namespace MantidWidgets const std::string runTitle = getRunTitle(ws); const std::string wsBaseName = labelGroupName + "_" + runTitle; + double fitQuality; + try { IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); @@ -287,6 +316,8 @@ namespace MantidWidgets fit->setProperty("Minimizer", m_fitPropBrowser->minimizer()); fit->setProperty("CostFunction", m_fitPropBrowser->costFunction()); fit->execute(); + + fitQuality = fit->getProperty("OutputChi2overDoF"); } catch(std::exception& e) { @@ -302,6 +333,9 @@ namespace MantidWidgets ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); + // Add information about the fit to the diagnosis table + addDiagnosisEntry(runTitle, fitQuality, m_fitPropBrowser->getFittingFunction()); + // Update progress m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) ); m_ui.progress->setValue( m_ui.progress->value() + 1 ); From e4bd61834e1501711b4098f3c36c7f51e1f6b0bf Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 10 Dec 2013 13:00:42 -0500 Subject: [PATCH 136/403] Re #8592. Copied over Art's changes. --- .../scripts/SCD_Reduction/ReduceSCD.config | 7 +++++++ .../scripts/SCD_Reduction/ReduceSCD_OneRun.py | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD.config b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD.config index 55653e97b564..7f3d6a0b3437 100644 --- a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD.config +++ b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD.config @@ -44,6 +44,13 @@ calibration_file_2 None data_directory None output_directory /SNS/TOPAZ/IPTS-9890/shared/SPAnH +# +# If use_monitor_counts is True, then the integrated beam monitor +# counts will be used for scaling. If use_monitor_counts is False, +# then the integrated proton charge will be used for scaling. These +# values will be listed under MONCNT in the integrate file. +use_monitor_counts False + # # Min & max tof determine the range of events loaded. # Max Q determines the range of Q values that will be mapped to diff --git a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py index 67b4d9917b77..6dc84e262920 100644 --- a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py +++ b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py @@ -23,14 +23,16 @@ # This version now includes the posibility to use the 1D cylindrical integration method # and the posibility to load a UB matrix which will be used for integration of the individual # runs and to index the combined file (Code from Xiapoing). -# - # # _v2: December 3rd 2013. Mads Joergensen # Adds the posibility to optimize the loaded UB for each run for a better peak prediction # It is also possible to find the common UB by using lattice parameters of the first # run or the loaded matirix instead of the default FFT method # +# _v3: December 5 2013. A. J. Schultz +# This version includes the Boolean parameter use_monitor_counts to allow +# the use of either monitor counts (True) or proton charge (False) for +# scaling. import os import sys @@ -161,13 +163,15 @@ Filename=calibration_file_1, Filename2=calibration_file_2 ) monitor_ws = LoadNexusMonitors( Filename=full_name ) +proton_charge = monitor_ws.getRun().getProtonCharge() * 1000.0 # get proton charge +print "\n", run, " has integrated proton charge x 1000 of", proton_charge, "\n" integrated_monitor_ws = Integration( InputWorkspace=monitor_ws, RangeLower=min_monitor_tof, RangeUpper=max_monitor_tof, StartWorkspaceIndex=monitor_index, EndWorkspaceIndex=monitor_index ) monitor_count = integrated_monitor_ws.dataY(0)[0] -print "\n", run, " has calculated monitor count", monitor_count, "\n" +print "\n", run, " has integrated monitor count", monitor_count, "\n" minVals= "-"+max_Q +",-"+max_Q +",-"+max_Q maxVals = max_Q +","+max_Q +","+ max_Q @@ -234,7 +238,14 @@ num_peaks = peaks_ws.getNumberPeaks() for i in range(num_peaks): peak = peaks_ws.getPeak(i) - peak.setMonitorCount( monitor_count ) + if use_monitor_counts: + peak.setMonitorCount( monitor_count ) + else: + peak.setMonitorCount( proton_charge ) +if use_monitor_counts: + print '\n*** Beam monitor counts used for scaling.' +else: + print '\n*** Proton charge x 1000 used for scaling.\n' if use_sphere_integration: # From a0041244db20af87a914cde89d0b19e4f3b4d6c7 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 18:06:34 +0000 Subject: [PATCH 137/403] Refs #6473. Various minor improvements. --- .../src/MuonSequentialFitDialog.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 134b2748a230..3f5950cad187 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -140,6 +140,8 @@ namespace MantidWidgets double value = fittedFunction->getParameter(paramName); m_ui.diagnosisTable->setItem(newRow, i, new QTableWidgetItem( QString::number(value) ) ); } + + m_ui.diagnosisTable->scrollToBottom(); } /** @@ -235,7 +237,13 @@ namespace MantidWidgets if ( ads.doesExist(labelGroupName) ) { - // TODO: confirm that + QMessageBox::StandardButton answer = QMessageBox::question(this, "Label already exists", + "Label you specified was used for one of the previous fits. Do you want to overwrite it?", + QMessageBox::Yes | QMessageBox::Cancel); + + if ( answer != QMessageBox::Yes ) + return; + ads.deepRemoveGroup(labelGroupName); } @@ -271,6 +279,7 @@ namespace MantidWidgets // TODO: should be MuonLoad here IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); loadAlg->setChild(true); + loadAlg->setRethrows(true); loadAlg->initialize(); loadAlg->setPropertyValue( "Filename", fileIt->toStdString() ); loadAlg->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used @@ -282,7 +291,6 @@ namespace MantidWidgets { QMessageBox::critical(this, "Loading failed", "Unable to load one of the files.\n\nCheck log for details"); - g_log.error(e.what()); break; } @@ -303,10 +311,13 @@ namespace MantidWidgets double fitQuality; + // TODO: fitting function logic + try { IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); fit->initialize(); + fit->setRethrows(true); fit->setProperty("Function", m_fitPropBrowser->getFittingFunction()); fit->setProperty("InputWorkspace", ws); fit->setProperty("WorkspaceIndex", 0); @@ -323,7 +334,6 @@ namespace MantidWidgets { QMessageBox::critical(this, "Fitting failed", "Unable to fit one of the files.\n\nCheck log for details"); - g_log.error(e.what()); break; } From 99132a78432112b18c5add0a30fbecfcfff708fc Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 18:11:47 +0000 Subject: [PATCH 138/403] Added debugging info. Refs #8581. --- Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp index 622ea983345f..965b5582d4c6 100644 --- a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp @@ -32,6 +32,8 @@ namespace Mantid ICat::Session::Instance().setSoapEndPoint(url); // Obtain the ICAT proxy that has been securely set, including soap-endpoint. ICat4::ICATPortBindingProxy icat = getICATProxy(); + // Output the soap end-point in use for debugging purposes. + g_log.debug() << "The ICAT soap end-point is: " << icat.soap_endpoint << "\n"; // Used to authenticate the user. ns1__login login; From ec911726ac7e1a0a32cf3bb9f20401a20de4addb Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Tue, 10 Dec 2013 18:12:51 +0000 Subject: [PATCH 139/403] Add support for ICAT3. Refs #8581. - Added two new helper methods to reduce duplication & bloat within ICat3Catalog. --- .../ICat/inc/MantidICat/ICat3/ICat3Helper.h | 6 + .../Framework/ICat/src/ICat3/ICat3Helper.cpp | 240 ++++-------------- 2 files changed, 56 insertions(+), 190 deletions(-) diff --git a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h index 9deed4109cb0..0adacff7f382 100644 --- a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h +++ b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h @@ -132,6 +132,12 @@ namespace Mantid /// Builds search query based on user input and stores query in related ICAT class. ICat3::ns1__advancedSearchDetails* buildSearchQuery(const CatalogSearchParam& inputs); + // Defines the SSL authentication scheme. + void setSSLContext(ICat3::ICATPortBindingProxy& icat); + + // Sets the soap-endpoint & SSL context for the proxy being returned. + ICat3::ICATPortBindingProxy getICATProxy(); + /** This is a template method to save data to table workspace * @param input :: pointer to input value * @param t :: table row reference diff --git a/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp b/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp index 5ea0b6ad0167..74a4c4a1eed3 100644 --- a/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp @@ -25,19 +25,7 @@ namespace Mantid */ int CICatHelper::doSearch(ICATPortBindingProxy& icat,boost::shared_ptr& request,ns1__searchByAdvancedResponse& response) { - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + icat = getICATProxy(); clock_t start=clock(); int ret_advsearch=icat.searchByAdvanced(request.get(),&response); if(ret_advsearch!=0) @@ -287,20 +275,7 @@ namespace Mantid API::ITableWorkspace_sptr& responsews_sptr) { //ICAt proxy object - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__getInvestigationIncludes request; //get the sessionid which is cached in session class during login @@ -436,20 +411,7 @@ namespace Mantid API::ITableWorkspace_sptr& responsews_sptr) { //ICAt proxy object - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); // request object ns1__getInvestigationIncludes request; @@ -545,21 +507,7 @@ namespace Mantid void CICatHelper::listInstruments(std::vector& instruments) { //ICAt proxy object - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } - + ICATPortBindingProxy icat = getICATProxy(); ns1__listInstruments request; //get the sessionid which is cached in session class during login @@ -610,21 +558,7 @@ namespace Mantid void CICatHelper::listInvestigationTypes(std::vector& investTypes) { //ICAt proxy object - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } - + ICATPortBindingProxy icat = getICATProxy(); ns1__listInvestigationTypes request; //get the sessionid which is cached in session class during login @@ -686,21 +620,7 @@ namespace Mantid */ int CICatHelper::doLogout() { - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__logout request; ns1__logoutResponse response; @@ -722,21 +642,7 @@ namespace Mantid */ void CICatHelper::doMyDataSearch(API::ITableWorkspace_sptr& ws_sptr) { - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__getMyInvestigationsIncludes request; ns1__getMyInvestigationsIncludesResponse response; @@ -818,20 +724,7 @@ namespace Mantid request.advancedSearchDetails = buildSearchQuery(inputs); //ICAt proxy object - ICATPortBindingProxy icat; - - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); int result = icat.searchByAdvancedPagination(&request, &response); @@ -950,20 +843,7 @@ namespace Mantid */ int64_t CICatHelper::getNumberOfSearchResults(const CatalogSearchParam& inputs) { - ICATPortBindingProxy icat; - - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__searchByAdvanced request; ns1__searchByAdvancedResponse response; @@ -996,21 +876,7 @@ namespace Mantid bool CICatHelper::isvalidSession() { - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__isSessionValid request; ns1__isSessionValidResponse response; @@ -1029,22 +895,12 @@ namespace Mantid */ void CICatHelper::doLogin(const std::string& name,const std::string& password,const std::string & url) { - UNUSED_ARG(url) - - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + // Store the soap end-point in the session for use later. + ICat::Session::Instance().setSoapEndPoint(url); + // Obtain the ICAT proxy that has been securely set, including soap-endpoint. + ICATPortBindingProxy icat = getICATProxy(); + // Output the soap end-point in use for debugging purposes. + g_log.debug() << "The ICAT soap end-point is: " << icat.soap_endpoint << "\n"; // CatalogLogin to icat ns1__login login; @@ -1076,20 +932,7 @@ namespace Mantid void CICatHelper::getdownloadURL(const long long& fileId,std::string& url) { - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__downloadDatafile request; @@ -1121,20 +964,7 @@ namespace Mantid void CICatHelper::getlocationString(const long long& fileid,std::string& filelocation) { - ICATPortBindingProxy icat; - // Define ssl authentication scheme - if (soap_ssl_client_context(&icat, - SOAP_SSL_NO_AUTHENTICATION, /* use SOAP_SSL_DEFAULT in production code */ - NULL, /* keyfile: required only when client must authenticate to - server (see SSL docs on how to obtain this file) */ - NULL, /* password to read the keyfile */ - NULL, /* optional cacert file to store trusted certificates */ - NULL, /* optional capath to directory with trusted certificates */ - NULL /* if randfile!=NULL: use a file with random data to seed randomness */ - )) - { - CErrorHandling::throwErrorMessages(icat); - } + ICATPortBindingProxy icat = getICATProxy(); ns1__getDatafile request; @@ -1157,7 +987,37 @@ namespace Mantid } } - - + /** + * Sets the soap-endpoint & SSL context for the proxy being returned. + * @return ICATPortBindingProxy :: The proxy with set endpoint & SSL context. + */ + ICat3::ICATPortBindingProxy CICatHelper::getICATProxy() + { + ICat3::ICATPortBindingProxy icat; + // Set the soap-endpoint of the catalog we want to use. + icat.soap_endpoint = ICat::Session::Instance().getSoapEndPoint().c_str(); + // Sets SSL authentication scheme + setSSLContext(icat); + return icat; + } + /** + * Defines the SSL authentication scheme. + * @param icat :: ICATPortBindingProxy object. + */ + void CICatHelper::setSSLContext(ICat3::ICATPortBindingProxy& icat) + { + if (soap_ssl_client_context(&icat, + SOAP_SSL_CLIENT, /* use SOAP_SSL_DEFAULT in production code */ + NULL, /* keyfile: required only when client must authenticate to + server (see SSL docs on how to obtain this file) */ + NULL, /* password to read the keyfile */ + NULL, /* optional cacert file to store trusted certificates */ + NULL, /* optional capath to directory with trusted certificates */ + NULL /* if randfile!=NULL: use a file with random data to seed randomness */ + )) + { + CErrorHandling::throwErrorMessages(icat); + } + } } } From 274b9568f8e1a2b432fefb7be029d0927ea7959e Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Tue, 10 Dec 2013 18:13:39 +0000 Subject: [PATCH 140/403] Refs #8550. Fixed failing system test. It is expected that multi-period data might contain all-zero groups. --- .../Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index 9908591e2dd4..e92dfff35a9b 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -584,10 +584,13 @@ namespace Mantid tableGroup->addWorkspace(table); } - if ( tableGroup->size() != static_cast(m_numberOfPeriods) ) - throw Exception::FileError("Zero grouping for some of the periods", m_filename); + if ( tableGroup->size() != 0 ) + { + if ( tableGroup->size() != static_cast(m_numberOfPeriods) ) + throw Exception::FileError("Zero grouping for some of the periods", m_filename); - setProperty("DetectorGroupingTable", tableGroup); + setProperty("DetectorGroupingTable", tableGroup); + } } } } From cbf094d9a530dcdd330ae4c7753f783c918c203e Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 10 Dec 2013 14:48:54 -0500 Subject: [PATCH 141/403] Re #8586. Adding support for TOPAS comments. --- .../inc/MantidDataHandling/SaveFocusedXYE.h | 4 +- .../DataHandling/src/SaveFocusedXYE.cpp | 38 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveFocusedXYE.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveFocusedXYE.h index 48e4c0983951..81094cd0eaf1 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveFocusedXYE.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveFocusedXYE.h @@ -56,7 +56,7 @@ namespace DataHandling class DLLExport SaveFocusedXYE : public API::Algorithm { public: - enum HeaderType {XYE, MAUD}; + enum HeaderType {XYE, MAUD, TOPAS}; /// (Empty) Constructor SaveFocusedXYE() : API::Algorithm(){} /// Virtual destructor @@ -99,6 +99,8 @@ class DLLExport SaveFocusedXYE : public API::Algorithm /// Header type HeaderType m_headerType; + /// Comment character + std::string m_comment; }; } diff --git a/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp b/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp index 15a0e4080ce4..5265015dc43d 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace Mantid::DataHandling; @@ -57,9 +58,10 @@ void SaveFocusedXYE::init() "The bank number in the file will be the workspace index + StartAtBankNumber."); declareProperty("Append", false, "If true and Filename already exists, append, else overwrite"); declareProperty("IncludeHeader", true, "Whether to include the header lines (default: true)"); - std::vector header(2); + std::vector header(3); header[0] = "XYE"; header[1] = "MAUD"; + header[2] = "TOPAS"; declareProperty("Format", "XYE", boost::make_shared(header), "A type of the header: XYE (default) or MAUD."); } @@ -98,15 +100,27 @@ void SaveFocusedXYE::exec() using std::ios_base; ios_base::openmode mode = (append ? (ios_base::out | ios_base::app) : ios_base::out); + m_comment = "#"; std::string headerType = getProperty("Format"); if ( headerType == "XYE" ) { m_headerType = XYE; } - else + else if (headerType == "MAUD") { m_headerType = MAUD; } + else if (headerType == "TOPAS") + { + m_headerType = TOPAS; + m_comment = "'"; + } + else + { + std::stringstream msg; + msg << "Unrecognized format \"" << m_headerType << "\""; + throw std::runtime_error(msg.str()); + } Progress progress(this, 0.0, 1.0, nHist); for (size_t i = 0; i < nHist; i++) @@ -232,11 +246,11 @@ void SaveFocusedXYE::setOtherProperties(IAlgorithm* alg, const std::string& prop */ void SaveFocusedXYE::writeHeaders(std::ostream& os, Mantid::API::MatrixWorkspace_const_sptr& workspace) const { - if ( m_headerType == XYE ) + if ( m_headerType == XYE || m_headerType == TOPAS ) { writeXYEHeaders( os, workspace ); } - else + else // MAUD { writeMAUDHeaders( os, workspace ); } @@ -249,10 +263,10 @@ void SaveFocusedXYE::writeHeaders(std::ostream& os, Mantid::API::MatrixWorkspace */ void SaveFocusedXYE::writeXYEHeaders(std::ostream& os,Mantid::API::MatrixWorkspace_const_sptr& workspace) const { - os << "# File generated by Mantid:" << std::endl; - os << "# Instrument: " << workspace->getInstrument()->getName() << std::endl; - os << "# The X-axis unit is: " << workspace->getAxis(0)->unit()->caption() << std::endl; - os << "# The Y-axis unit is: " << workspace->YUnitLabel() << std::endl; + os << m_comment << " File generated by Mantid:" << std::endl; + os << m_comment << " Instrument: " << workspace->getInstrument()->getName() << std::endl; + os << m_comment << " The X-axis unit is: " << workspace->getAxis(0)->unit()->caption() << std::endl; + os << m_comment << " The Y-axis unit is: " << workspace->YUnitLabel() << std::endl; } /** @@ -274,11 +288,11 @@ void SaveFocusedXYE::writeMAUDHeaders(std::ostream& os,Mantid::API::MatrixWorksp void SaveFocusedXYE::writeSpectraHeader(std::ostream& os, size_t index1, size_t index2, double flightPath, double tth, const std::string& caption) { - if ( m_headerType == XYE ) + if ( m_headerType == XYE || m_headerType == TOPAS ) { writeXYESpectraHeader( os, index1, index2, flightPath, tth, caption ); } - else + else // MAUD { writeMAUDSpectraHeader( os, index1, index2, flightPath, tth, caption ); } @@ -291,8 +305,8 @@ void SaveFocusedXYE::writeXYESpectraHeader(std::ostream& os, size_t index1, size UNUSED_ARG(index2); UNUSED_ARG(flightPath); UNUSED_ARG(tth); - os << "# Data for spectra :" << index1 << std::endl; - os << "# " << caption << " Y E" << std::endl; + os << m_comment << " Data for spectra :" << index1 << std::endl; + os << m_comment << " " << caption << " Y E" << std::endl; } /// Write spectra MAUD header From 1745c657d83ec637c970a11eb7b3df107e4455d8 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Tue, 10 Dec 2013 21:41:59 +0000 Subject: [PATCH 142/403] Add support for DetectorGroups to Compton functions The parameters are averaged across the DetectorGroup when one is found Refs #8593 --- .../CalculateGammaBackground.h | 2 - .../inc/MantidCurveFitting/ComptonProfile.h | 8 +- .../src/CalculateGammaBackground.cpp | 58 +++++--------- .../CurveFitting/src/ComptonProfile.cpp | 78 ++++++++++++------- 4 files changed, 75 insertions(+), 71 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CalculateGammaBackground.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CalculateGammaBackground.h index 2765d7ad0458..9bd2a19e11af 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CalculateGammaBackground.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CalculateGammaBackground.h @@ -81,8 +81,6 @@ namespace Mantid /// Compute the theta range for a given foil std::pair calculateThetaRange(const Geometry::IComponent_const_sptr & foilComp, const double radius, const unsigned int horizDir) const; - /// Retrieve parameter for given component - double getComponentParameter(const Geometry::IComponent & comp,const std::string &name) const; /// Input TOF data API::MatrixWorkspace_const_sptr m_inputWS; diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ComptonProfile.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ComptonProfile.h index f9fcebf7f5ec..fc076b667f8a 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ComptonProfile.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ComptonProfile.h @@ -58,6 +58,10 @@ namespace CurveFitting class MANTID_CURVEFITTING_DLL ComptonProfile : public virtual API::ParamFunction, public virtual API::IFunction1D { public: + /// Retrieve a component parameter + static double getComponentParameter(const Geometry::IComponent_const_sptr & comp, const Geometry::ParameterMap &pmap, + const std::string &name); + /// Default constructor required for factory ComptonProfile(); @@ -116,10 +120,6 @@ namespace CurveFitting /// Logger Kernel::Logger & m_log; - private: - /// Retrieve a component parameter - double getComponentParameter(const Geometry::IComponent & comp,const std::string &name) const; - /// Current workspace index, required to access instrument parameters size_t m_wsIndex; /// Store the mass values diff --git a/Code/Mantid/Framework/CurveFitting/src/CalculateGammaBackground.cpp b/Code/Mantid/Framework/CurveFitting/src/CalculateGammaBackground.cpp index 1f3c7f718168..abb94f850f09 100644 --- a/Code/Mantid/Framework/CurveFitting/src/CalculateGammaBackground.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/CalculateGammaBackground.cpp @@ -218,6 +218,7 @@ namespace Mantid void CalculateGammaBackground::calculateSpectrumFromDetector(const size_t inputIndex, const size_t outputIndex) { auto det = m_inputWS->getDetector(inputIndex); + const auto & pmap = m_inputWS->constInstrumentParameters(); auto detPos = det->getPos(); // -- Setup detector & resolution parameters -- @@ -225,15 +226,15 @@ namespace Mantid detPar.l1 = m_l1; detPar.l2 = m_samplePos.distance(detPos); detPar.theta = m_inputWS->detectorTwoTheta(det); //radians - detPar.t0 = getComponentParameter(*det, "t0")*1e-6; // seconds - detPar.efixed = getComponentParameter(*det,"efixed"); + detPar.t0 = ComptonProfile::getComponentParameter(det, pmap, "t0")*1e-6; // seconds + detPar.efixed = ComptonProfile::getComponentParameter(det, pmap,"efixed"); ResolutionParams detRes; - detRes.dl1 = getComponentParameter(*det, "sigma_l1"); // DL0 - detRes.dl2 = getComponentParameter(*det, "sigma_l2"); // DL1 - detRes.dthe = getComponentParameter(*det, "sigma_theta"); //DTH in radians - detRes.dEnGauss = getComponentParameter(*det, "sigma_gauss"); - detRes.dEnLorentz = getComponentParameter(*det, "hwhm_lorentz"); + detRes.dl1 = ComptonProfile::getComponentParameter(det, pmap, "sigma_l1"); // DL0 + detRes.dl2 = ComptonProfile::getComponentParameter(det, pmap, "sigma_l2"); // DL1 + detRes.dthe = ComptonProfile::getComponentParameter(det, pmap, "sigma_theta"); //DTH in radians + detRes.dEnGauss = ComptonProfile::getComponentParameter(det, pmap, "sigma_gauss"); + detRes.dEnLorentz = ComptonProfile::getComponentParameter(det, pmap, "hwhm_lorentz"); // Compute a time of flight spectrum convolved with a Voigt resolution function for each mass // at the detector point & sum to a single spectrum @@ -255,6 +256,7 @@ namespace Mantid void CalculateGammaBackground::calculateBackgroundFromFoils(const size_t inputIndex, const size_t outputIndex) { auto det = m_inputWS->getDetector(inputIndex); + const auto & pmap = m_inputWS->constInstrumentParameters(); auto detPos = det->getPos(); // -- Setup detector & resolution parameters -- @@ -262,15 +264,15 @@ namespace Mantid detPar.l1 = m_l1; detPar.l2 = m_samplePos.distance(detPos); detPar.theta = m_inputWS->detectorTwoTheta(det); //radians - detPar.t0 = getComponentParameter(*det, "t0")*1e-6; // seconds - detPar.efixed = getComponentParameter(*det,"efixed"); + detPar.t0 = ComptonProfile::getComponentParameter(det, pmap, "t0")*1e-6; // seconds + detPar.efixed = ComptonProfile::getComponentParameter(det, pmap,"efixed"); ResolutionParams detRes; - detRes.dl1 = getComponentParameter(*det, "sigma_l1"); // DL0 - detRes.dl2 = getComponentParameter(*det, "sigma_l2"); // DL1 - detRes.dthe = getComponentParameter(*det, "sigma_theta"); //DTH in radians - detRes.dEnGauss = getComponentParameter(*det, "sigma_gauss"); - detRes.dEnLorentz = getComponentParameter(*det, "hwhm_lorentz"); + detRes.dl1 = ComptonProfile::getComponentParameter(det, pmap, "sigma_l1"); // DL0 + detRes.dl2 = ComptonProfile::getComponentParameter(det, pmap, "sigma_l2"); // DL1 + detRes.dthe = ComptonProfile::getComponentParameter(det, pmap, "sigma_theta"); //DTH in radians + detRes.dEnGauss = ComptonProfile::getComponentParameter(det, pmap, "sigma_gauss"); + detRes.dEnLorentz = ComptonProfile::getComponentParameter(det, pmap, "hwhm_lorentz"); const size_t nxvalues = m_backgroundWS->blocksize(); std::vector foilSpectrum(nxvalues); @@ -510,6 +512,7 @@ namespace Mantid // foil geometry // there should be the same number in each position + const auto & pmap = m_inputWS->constInstrumentParameters(); auto foils0 = inst->getAllComponentsWithName("foil-pos0"); auto foils1 = inst->getAllComponentsWithName("foil-pos1"); const size_t nfoils = foils0.size(); @@ -534,16 +537,16 @@ namespace Mantid FoilInfo descr; descr.thetaMin = thetaRng0.first; descr.thetaMax = thetaRng0.second; - descr.lorentzWidth = getComponentParameter(*foil0, "hwhm_lorentz"); - descr.gaussWidth = getComponentParameter(*foil0, "sigma_gauss"); + descr.lorentzWidth = ComptonProfile::getComponentParameter(foil0, pmap, "hwhm_lorentz"); + descr.gaussWidth = ComptonProfile::getComponentParameter(foil0, pmap, "sigma_gauss"); m_foils0[i] = descr; //copy const auto & foil1 = foils1[i]; auto thetaRng1 = calculateThetaRange(foil1, m_foilRadius,refFrame->pointingHorizontal()); descr.thetaMin = thetaRng1.first; descr.thetaMax = thetaRng1.second; - descr.lorentzWidth = getComponentParameter(*foil1, "hwhm_lorentz"); - descr.gaussWidth = getComponentParameter(*foil1, "sigma_gauss"); + descr.lorentzWidth = ComptonProfile::getComponentParameter(foil1, pmap, "hwhm_lorentz"); + descr.gaussWidth = ComptonProfile::getComponentParameter(foil1, pmap, "sigma_gauss"); m_foils1[i] = descr; //copy } @@ -596,24 +599,5 @@ namespace Mantid return std::make_pair(theta - dtheta, theta + dtheta); } - /** - * @param comp A reference to the component that should contain the parameter - * @param name The name of the parameter - * @returns The value of the parameter if it exists - * @throws A std::invalid_argument error if the parameter does not exist - */ - double CalculateGammaBackground::getComponentParameter(const Geometry::IComponent & comp,const std::string &name) const - { - std::vector pars = comp.getNumberParameter(name); - if(!pars.empty()) - { - return pars[0]; - } - else - { - throw std::invalid_argument("CalculateGammaBackground - Cannot find component parameter \"" + name + "\"."); - } - } - } // namespace CurveFitting } // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/ComptonProfile.cpp b/Code/Mantid/Framework/CurveFitting/src/ComptonProfile.cpp index 0e9d10b26d93..698e7fefbd32 100644 --- a/Code/Mantid/Framework/CurveFitting/src/ComptonProfile.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/ComptonProfile.cpp @@ -3,7 +3,7 @@ //----------------------------------------------------------------------------- #include "MantidCurveFitting/ComptonProfile.h" #include "MantidAPI/FunctionFactory.h" - +#include "MantidGeometry/Instrument/DetectorGroup.h" #include namespace Mantid @@ -21,6 +21,47 @@ namespace CurveFitting ///@endcond } + /** + * If a DetectorGroup is encountered then the parameters are averaged over the group + * @param comp A pointer to the component that should contain the parameter + * @param pmap A reference to the ParameterMap that stores the parameters + * @param name The name of the parameter + * @returns The value of the parameter if it exists + * @throws A std::invalid_argument error if the parameter does not exist + */ + double ComptonProfile::getComponentParameter(const Geometry::IComponent_const_sptr & comp, const Geometry::ParameterMap &pmap, + const std::string &name) + { + if(!comp) throw std::invalid_argument("ComptonProfile - Cannot retrieve parameter from NULL component"); + + double result(0.0); + if(const auto group = boost::dynamic_pointer_cast(comp)) + { + const auto dets = group->getDetectors(); + double avg(0.0); + for(auto it = dets.begin(); it!= dets.end(); ++it) + { + auto param = pmap.getRecursive((*it)->getComponentID(), name); + if(param) avg += param->value(); + else throw std::invalid_argument("ComptonProfile - Unable to find DetectorGroup component parameter \"" + name + "\"."); + } + result = avg/static_cast(group->nDets()); + } + else + { + auto param = pmap.getRecursive(comp->getComponentID(), name); + if(param) + { + result = param->value(); + } + else + { + throw std::invalid_argument("ComptonProfile - Unable to find component parameter \"" + name + "\"."); + } + } + return result; + } + /** */ ComptonProfile::ComptonProfile() : API::ParamFunction(), API::IFunction1D(), @@ -89,18 +130,19 @@ namespace CurveFitting } DetectorParams detpar; + const auto & pmap = workspace->constInstrumentParameters(); detpar.l1 = sample->getDistance(*source); detpar.l2 = det->getDistance(*sample); detpar.theta = workspace->detectorTwoTheta(det); - detpar.t0 = getComponentParameter(*det,"t0")*1e-6; // Convert to seconds - detpar.efixed = getComponentParameter(*det,"efixed"); + detpar.t0 = getComponentParameter(det, pmap, "t0")*1e-6; // Convert to seconds + detpar.efixed = getComponentParameter(det, pmap, "efixed"); ResolutionParams respar; - respar.dl1 = getComponentParameter(*det, "sigma_l1"); - respar.dl2 = getComponentParameter(*det, "sigma_l2"); - respar.dthe = getComponentParameter(*det,"sigma_theta"); //radians - respar.dEnLorentz = getComponentParameter(*det, "hwhm_lorentz"); - respar.dEnGauss = getComponentParameter(*det, "sigma_gauss"); + respar.dl1 = getComponentParameter(det, pmap, "sigma_l1"); + respar.dl2 = getComponentParameter(det, pmap, "sigma_l2"); + respar.dthe = getComponentParameter(det, pmap, "sigma_theta"); //radians + respar.dEnLorentz = getComponentParameter(det, pmap, "hwhm_lorentz"); + respar.dEnGauss = getComponentParameter(det, pmap, "sigma_gauss"); this->cacheYSpaceValues(workspace->readX(m_wsIndex), workspace->isHistogramData(), detpar, respar); } @@ -304,25 +346,5 @@ namespace CurveFitting std::transform(voigt.begin(), voigt.end(), voigt.begin(), std::bind2nd(std::multiplies(), norm)); } - /** - * @param comp A reference to the component that should contain the parameter - * @param name The name of the parameter - * @returns The value of the parameter if it exists - * @throws A std::invalid_argument error if the parameter does not exist - */ - double ComptonProfile::getComponentParameter(const Geometry::IComponent & comp,const std::string &name) const - { - std::vector pars = comp.getNumberParameter(name); - if(!pars.empty()) - { - return pars[0]; - } - else - { - throw std::invalid_argument("ComptonProfile - Unable to find component parameter \"" + name + "\"."); - } - } - - } // namespace CurveFitting } // namespace Mantid From 77eb4787a35b31dd6d024f5dd1d6e5dcb9f3e1d6 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 10 Dec 2013 16:42:58 -0500 Subject: [PATCH 143/403] Re #8592. Forgot to define a variable. --- Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py index 6dc84e262920..98d0610fdea7 100644 --- a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py +++ b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py @@ -72,7 +72,8 @@ data_directory = params_dictionary[ "data_directory" ] output_directory = params_dictionary[ "output_directory" ] min_tof = params_dictionary[ "min_tof" ] -max_tof = params_dictionary[ "max_tof" ] +max_tof = params_dictionary[ "max_tof" ] +use_monitor_counts = params_dictionary[ "use_monitor_counts" ] min_monitor_tof = params_dictionary[ "min_monitor_tof" ] max_monitor_tof = params_dictionary[ "max_monitor_tof" ] monitor_index = params_dictionary[ "monitor_index" ] From 72cb56f69d983c3ec1134ce0fa86796c4ed15661 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 11 Dec 2013 08:36:26 +0000 Subject: [PATCH 144/403] refs #8591. Move helper and apply warning fix. --- .../ReflectometryReductionOne.h | 2 +- .../src/ReflectometryReductionOne.cpp | 29 +++++++++---------- .../test/ReflectometryReductionOneTest.h | 3 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index 3df25b1a9b96..22d53d41c4f9 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -65,7 +65,7 @@ namespace Mantid const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep); /// Convert to an IvsQ workspace. Performs detector positional corrections based on the component name and the theta value. - Mantid::API::MatrixWorkspace_sptr toIvsQ(API::MatrixWorkspace_sptr toConvert, const bool correctPosition, const bool isPointDetector, + Mantid::API::MatrixWorkspace_sptr toIvsQ(API::MatrixWorkspace_sptr toConvert, const bool correctPosition, OptionalDouble& thetaInDeg, Geometry::IComponent_const_sptr sample, Geometry::IComponent_const_sptr detector); private: diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index af7212bc3132..b6b0e1840d4f 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -81,8 +81,8 @@ namespace Mantid * @param originIndexes : Indexes in terms of the origin workspace * @return WorkspaceIndexes in terms of the host workspace */ - ReflectometryReductionOne::WorkspaceIndexList getIndexesInTermsOf(MatrixWorkspace_const_sptr hostWS, - MatrixWorkspace_sptr originWS, + ReflectometryReductionOne::WorkspaceIndexList getIndexesInTermsOf( + MatrixWorkspace_const_sptr hostWS, MatrixWorkspace_sptr originWS, const ReflectometryReductionOne::WorkspaceIndexList& originIndexes) { auto spectrumMap = hostWS->getSpectrumToWorkspaceIndexMap(); @@ -95,6 +95,16 @@ namespace Mantid return translatedIndexList; } + /** + * Helper method used with the stl to determine whether values are negative + * @param value : Value to check + * @return : True if negative. + */ + bool checkNotPositive(const int value) + { + return value < 0; + } + const std::string multiDetectorAnalysis = "MultiDetectorAnalysis"; const std::string pointDetectorAnalysis = "PointDetectorAnalysis"; } @@ -292,16 +302,6 @@ namespace Mantid return property->isDefault(); } - /** - * Helper method used with the stl to determine whether values are negative - * @param value : Value to check - * @return : True if negative. - */ - bool checkNotPositive(const int value) - { - return value < 0; - } - /** * Get the workspace index list * @return Workspace index list. @@ -765,14 +765,13 @@ namespace Mantid * * @param toConvert : Workspace to convert * @param bCorrectPosition : Flag to indicate that detector positions should be corrected based on the input theta values. - * @param isPointDetector : Flag to indicate that this is a point detector reduction run. * @param thetaInDeg : Theta in Degrees. Used for correction. * @param sample : Sample component * @param detector : Detector component * @return */ Mantid::API::MatrixWorkspace_sptr ReflectometryReductionOne::toIvsQ(API::MatrixWorkspace_sptr toConvert, const bool bCorrectPosition, - const bool isPointDetector, OptionalDouble& thetaInDeg, Geometry::IComponent_const_sptr sample, Geometry::IComponent_const_sptr detector) + OptionalDouble& thetaInDeg, Geometry::IComponent_const_sptr sample, Geometry::IComponent_const_sptr detector) { /* * Can either calculate a missing theta value for the purposes of reporting, or correct positions based on a theta value, @@ -973,7 +972,7 @@ namespace Mantid IvsLam = regionOfInterestWS / regionOfDirectBeamWS; // TODO. This needs checking. } - IvsQ = this->toIvsQ(IvsLam, correctDetctorPositions, isPointDetector, theta, sample, detector); + IvsQ = this->toIvsQ(IvsLam, correctDetctorPositions, theta, sample, detector); setProperty("ThetaOut", theta.get()); setProperty("OutputWorkspaceWavelength", IvsLam); diff --git a/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h b/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h index 6e52ae734da0..b1b7456b1c8b 100644 --- a/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h +++ b/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h @@ -108,8 +108,7 @@ class ReflectometryReductionOneTest: public CxxTest::TestSuite boost::optional theta = 0.7; - MatrixWorkspace_const_sptr inQ = alg.toIvsQ(toConvert, true /*correct position*/, - true /*is point detector*/, theta, sample, detector); + MatrixWorkspace_const_sptr inQ = alg.toIvsQ(toConvert, true /*correct position*/, theta, sample, detector); TS_ASSERT_EQUALS("MomentumTransfer", inQ->getAxis(0)->unit()->unitID()); From b5fe6c0571244f27c6fff8d9fc5f224ab6ebb775 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Wed, 11 Dec 2013 09:04:46 +0000 Subject: [PATCH 145/403] Refs #8176 Fix for broken system tests --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index ffdbbc9f26a9..c8238556cbb7 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -9,7 +9,6 @@ from mantid.api import PythonAlgorithm, AlgorithmFactory from mantid.kernel import StringListValidator, StringMandatoryValidator from mantid import config -from IndirectCommon import StartTime, EndTime import os.path, math class IndirectTransmission(PythonAlgorithm): @@ -26,7 +25,8 @@ def PyInit(self): self.declareProperty(name='Thickness', defaultValue=0.1, doc='Sample thickness. Default=0.1') def PyExec(self): - + from IndirectCommon import StartTime, EndTime + StartTime('IndirectTransmission') instrumentName = self.getPropertyValue('Instrument') From 8880fbd3074f165059243292fac72684945e020c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 10:04:14 +0000 Subject: [PATCH 146/403] Refs #6473. Minor improvements. --- .../inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h | 2 +- .../MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp | 3 +-- .../MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 4d4f5477dacf..4a8a96c20f2c 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -45,7 +45,7 @@ namespace MantidWidgets Q_OBJECT public: - MuonSequentialFitDialog(MuonFitPropertyBrowser* parent); + MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser); virtual ~MuonSequentialFitDialog(); enum DialogState diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp index f4bb5de81468..ecdd89bde2ba 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp @@ -317,8 +317,7 @@ void MuonFitPropertyBrowser::fit() void MuonFitPropertyBrowser::sequentialFit() { MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(this); - dialog->setModal(true); - dialog->show(); + dialog->exec(); } /** diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 3f5950cad187..de5a59c397ff 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -11,8 +11,8 @@ namespace MantidWidgets using namespace Mantid::API; Logger& MuonSequentialFitDialog::g_log(Logger::get("MuonSequentialFitDialog")); - /** + * Constructor */ MuonSequentialFitDialog::MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser) : @@ -360,7 +360,7 @@ namespace MantidWidgets void MuonSequentialFitDialog::stopFit() { if ( m_state != Running ) - throw std::runtime_error("Coulnd't stop: is not running"); + throw std::runtime_error("Couldn't stop: is not running"); m_stopRequested = true; } From 5262240245ec94ba31c1b44577715f1a496d9b3a Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 11 Dec 2013 10:14:19 +0000 Subject: [PATCH 147/403] Fix CachedExperimentInfoTest Refs #8416 --- .../MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp index 8404eff688f8..ebec09716e3c 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp @@ -191,6 +191,11 @@ namespace Mantid // Detector volume // Make sure it encompasses all possible detectors det->getBoundingBox(m_detBox); + if(m_detBox.isNull()) + { + throw std::invalid_argument("CachedExperimentInfo::initCaches - Detector has no bounding box, cannot sample from it. ID:" + + boost::lexical_cast(det->getID())); + } const double rad2deg = 180./M_PI; const double thetaInDegs = twoTheta()*rad2deg; From 73b82b91f73bdb696f9e8280167b80a25f0d2439 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Wed, 11 Dec 2013 10:16:15 +0000 Subject: [PATCH 148/403] Refs #8176 Swapped wavelength to have its own row. --- .../WorkflowAlgorithms/IndirectTransmission.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index c8238556cbb7..f3739aceb006 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -78,20 +78,17 @@ def PyExec(self): tableWs.addColumn("str", "Value") # Names for each of the output values - outputNames = ['Absorption Xsection at wavelength', 'Coherent Xsection', 'Incoherent Xsection', + outputNames = ['Wavelength', 'Absorption Xsection', 'Coherent Xsection', 'Incoherent Xsection', 'Total scattering Xsection', 'Number density', 'Thickness', 'Transmission (abs+scatt)', 'Total scattering'] # List of the calculated values - outputValues = [str(wave) + ' A = '+ str(absorptionXSection), coherentXSection, incoherentXSection, scatteringXSection, - density, thickness, transmission, scattering] - - # Convert all values to string - outputValues = map (str, outputValues) + outputValues = [wave, absorptionXSection, coherentXSection, incoherentXSection, + scatteringXSection, density, thickness, transmission, scattering] + + outputValues = map(str, outputValues) - output = zip (outputNames, outputValues) - #build table of values - for data in output: + for data in zip (outputNames, outputValues): tableWs.addRow(list(data)) logger.information(': '.join(list(data))) From e8d6a77377b3612769885660793cb8b7fb44abc8 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 11 Dec 2013 10:22:22 +0000 Subject: [PATCH 149/403] Add SumSpectra option to LoadVesuvio The final output is just a single spectrum when this option is used. Refs #8593 --- .../plugins/algorithms/LoadVesuvio.py | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadVesuvio.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadVesuvio.py index f347c7febcca..e23d59e8cb1d 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadVesuvio.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadVesuvio.py @@ -19,6 +19,7 @@ MODES=["SingleDifference", "DoubleDifference", "ThickDifference", "FoilOut", "FoilIn", "FoilInOut"] SPECTRA_PROP = "SpectrumList" INST_PAR_PROP = "InstrumentParFile" +SUM_PROP = "SumSpectra" # Raw workspace names which are necessary at the moment SUMMED_WS, SUMMED_MON = "__loadraw_evs", "__loadraw_evs_monitors" @@ -60,6 +61,10 @@ def PyInit(self): doc="An optional IP file. If provided the values are used to correct " "the default instrument values and attach the t0 values to each detector") + self.declareProperty(SUM_PROP, False, + doc="If true then the final output is a single spectrum containing the sum " + "of all of the requested spectra. All detector angles/parameters are " + "averaged over the individual inputs") #---------------------------------------------------------------------------------------- def PyExec(self): self._load_inst_parameters() @@ -90,8 +95,14 @@ def _exec_difference_mode(self): self._normalise_by_monitor() self._normalise_to_foil_out() self._calculate_diffs() - - self._load_ip_file() + # end of differencing loop + + ip_file = self.getPropertyValue(INST_PAR_PROP) + if len(ip_file) > 0: + self._load_ip_file(ip_file) + if self._sumspectra: + self._sum_all_spectra() + self._store_results() finally: # Ensures it happens whether there was an error or not self._cleanup_raw() @@ -216,6 +227,7 @@ def _retrieve_input(self): self._spectra = self.getProperty(SPECTRA_PROP).value.tolist() if self._mon_spectra in self._spectra: self._spectra.remove(self._spectra) + self._sumspectra = self.getProperty(SUM_PROP).value #---------------------------------------------------------------------------------------- @@ -608,14 +620,14 @@ def _calculate_thick_difference(self, ws_index): np.sqrt((eout**2 + ethick**2), eout) # The second argument makes it happen in place #---------------------------------------------------------------------------------------- - def _load_ip_file(self): + def _load_ip_file(self, ip_file): """ If provided, load the instrument parameter file into the result workspace + @param ip_file A string containing the full path to an IP file """ - ip_file = self.getProperty(INST_PAR_PROP).value if ip_file == "": - return + raise ValueError("Empty filename string for IP file") ip_header = self._get_header_format(ip_file) @@ -631,6 +643,22 @@ def _load_ip_file(self): self.foil_out = update_inst.getProperty("Workspace").value +#---------------------------------------------------------------------------------------- + + def _sum_all_spectra(self): + """ + Runs the SumSpectra algorithm to collapse all of the + spectra into 1 + """ + # More verbose until the child algorithm stuff is sorted + sum_spectra = self.createChildAlgorithm("SumSpectra") + sum_spectra.setLogging(_LOGGING_) + sum_spectra.setProperty("InputWorkspace", self.foil_out) + sum_spectra.setProperty("OutputWorkspace", self.foil_out) + sum_spectra.execute() + + self.foil_out = sum_spectra.getProperty("OutputWorkspace").value + #---------------------------------------------------------------------------------------- def _get_header_format(self, ip_filename): """ From a73f524bf138dfa52130417b20c7a99d83a8ab7d Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Wed, 11 Dec 2013 10:42:54 +0000 Subject: [PATCH 150/403] Select default facility. Refs #8581. --- Code/Mantid/Framework/ICat/src/CatalogLogin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp index 4600892e70ab..5e1fab8a4e87 100644 --- a/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp +++ b/Code/Mantid/Framework/ICat/src/CatalogLogin.cpp @@ -30,8 +30,9 @@ namespace Mantid declareProperty("Username","", requireValue,"The username to log into the catalog."); declareProperty(new Kernel::MaskedProperty("Password","", requireValue), "The password of the related username to use."); - declareProperty("FacilityName", "", boost::make_shared(Kernel::ConfigService::Instance().getFacilityNames()), - "Select a facility to log in to."); + declareProperty("FacilityName",Mantid::Kernel::ConfigService::Instance().getFacility().name(), + boost::make_shared(Kernel::ConfigService::Instance().getFacilityNames()), + "Select a facility to log in to."); } /// execute the algorithm From 4cf35e3306f3dbf20ed3b6dd6935922b6f3c672d Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 10:45:59 +0000 Subject: [PATCH 151/403] Refs #6473. Logic for init/sequential fitting options. --- .../src/MuonSequentialFitDialog.cpp | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index de5a59c397ff..07401f9481aa 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -260,6 +260,13 @@ namespace MantidWidgets // Clear diagnosis table for new fit m_ui.diagnosisTable->setRowCount(0); + // Get fit function as specified by user in the fit browser + IFunction_sptr fitFunction = FunctionFactory::Instance().createInitialized( + m_fitPropBrowser->getFittingFunction()->asString() ); + + // Whether we should use initial function for every fit + bool useInitFitFunction = (m_ui.paramTypeGroup->checkedButton() == m_ui.paramTypeInitial); + setState(Running); m_stopRequested = false; @@ -309,26 +316,39 @@ namespace MantidWidgets const std::string runTitle = getRunTitle(ws); const std::string wsBaseName = labelGroupName + "_" + runTitle; - double fitQuality; - // TODO: fitting function logic + IFunction_sptr functionToFit; + + if ( useInitFitFunction ) + // Create a copy so that the original function is not changed + functionToFit = FunctionFactory::Instance().createInitialized( fitFunction->asString() ); + else + // Use the same function over and over, so that previous fitted params are used for the next fit + functionToFit = fitFunction; + + IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); try { - IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); fit->initialize(); fit->setRethrows(true); - fit->setProperty("Function", m_fitPropBrowser->getFittingFunction()); + + // Set function. Gets updated when fit is done. + fit->setProperty("Function", functionToFit); + fit->setProperty("InputWorkspace", ws); + fit->setProperty("Output", wsBaseName); + + // We should have one spectra only in the workspace, so use the first one. fit->setProperty("WorkspaceIndex", 0); + + // Various properties from the fit prop. browser fit->setProperty("StartX", m_fitPropBrowser->startX()); fit->setProperty("EndX", m_fitPropBrowser->endX()); - fit->setProperty("Output", wsBaseName); fit->setProperty("Minimizer", m_fitPropBrowser->minimizer()); fit->setProperty("CostFunction", m_fitPropBrowser->costFunction()); - fit->execute(); - fitQuality = fit->getProperty("OutputChi2overDoF"); + fit->execute(); } catch(std::exception& e) { @@ -344,7 +364,7 @@ namespace MantidWidgets ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); // Add information about the fit to the diagnosis table - addDiagnosisEntry(runTitle, fitQuality, m_fitPropBrowser->getFittingFunction()); + addDiagnosisEntry(runTitle, fit->getProperty("OutputChi2OverDof"), functionToFit); // Update progress m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) ); From 9483f88cf8829cb10edaf7c4708a37ae12d2b5b0 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 11:24:49 +0000 Subject: [PATCH 152/403] Refs #6473. Showing errors in the diagnosis table. --- .../src/MuonSequentialFitDialog.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 07401f9481aa..aba3c9a7b674 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -109,13 +109,21 @@ namespace MantidWidgets IFunction_sptr fitFunc = m_fitPropBrowser->getFittingFunction(); for(size_t i = 0; i < fitFunc->nParams(); i++) - headerLabels << QString::fromStdString( fitFunc->parameterName(i) ); + { + QString paramName = QString::fromStdString( fitFunc->parameterName(i) ); + headerLabels << paramName; + headerLabels << paramName + "_Err"; + } m_ui.diagnosisTable->setColumnCount( headerLabels.size() ); m_ui.diagnosisTable->setHorizontalHeaderLabels(headerLabels); - // Make the table fill all the available space - m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + // Make the table fill all the available space and columns be resized to fit contents + m_ui.diagnosisTable->horizontalHeader()->setStretchLastSection(true); + m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + + // Make rows alternate bg colors for better user experience + m_ui.diagnosisTable->setAlternatingRowColors(true); } /** @@ -134,11 +142,16 @@ namespace MantidWidgets m_ui.diagnosisTable->setItem(newRow, 0, new QTableWidgetItem( QString::fromStdString(runTitle) ) ); m_ui.diagnosisTable->setItem(newRow, 1, new QTableWidgetItem( QString::number(fitQuality) ) ); - for(int i = 2; i < m_ui.diagnosisTable->columnCount(); ++i) + for(int i = 2; i < m_ui.diagnosisTable->columnCount(); i += 2) { std::string paramName = m_ui.diagnosisTable->horizontalHeaderItem(i)->text().toStdString(); - double value = fittedFunction->getParameter(paramName); - m_ui.diagnosisTable->setItem(newRow, i, new QTableWidgetItem( QString::number(value) ) ); + size_t paramIndex = fittedFunction->parameterIndex(paramName); + + QString value = QString::number( fittedFunction->getParameter(paramIndex) ); + QString error = QString::number( fittedFunction->getError(paramIndex) ); + + m_ui.diagnosisTable->setItem(newRow, i, new QTableWidgetItem(value) ); + m_ui.diagnosisTable->setItem(newRow, i + 1, new QTableWidgetItem(error) ); } m_ui.diagnosisTable->scrollToBottom(); From c21d90af98edf77c86f502212e13563edee3ee0b Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Wed, 11 Dec 2013 11:25:51 +0000 Subject: [PATCH 153/403] Add reference to ticket #8521 in comment re #8546 Signed-off-by: Karl Palmen --- Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index 439e02a61f94..128ff57d5ba7 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -115,7 +115,7 @@ void LoadParameterFile::exec() void LoadParameterFile::execManually(bool useString, std::string filename, std::string parameterXML, Mantid::API::ExperimentInfo_sptr localWorkspace) { - // TODO: Refactor to remove the need for the const cast + // TODO: Refactor to remove the need for the const cast (ticket #8521) Instrument_sptr instrument = boost::const_pointer_cast(localWorkspace->getInstrument()->baseInstrument()); // Set up the DOM parser and parse xml file From 829b0993680f7c2fab12af8e56261738223d2baa Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 12:47:00 +0000 Subject: [PATCH 154/403] Refs #8494. Initial class files. --- .../WorkflowAlgorithms/CMakeLists.txt | 3 + .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 56 +++++++++++++++ .../WorkflowAlgorithms/src/MuonLoad.cpp | 70 +++++++++++++++++++ .../WorkflowAlgorithms/test/MuonLoadTest.h | 60 ++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h create mode 100644 Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp create mode 100644 Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/CMakeLists.txt b/Code/Mantid/Framework/WorkflowAlgorithms/CMakeLists.txt index a77011d32e40..650b41cd4654 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/WorkflowAlgorithms/CMakeLists.txt @@ -19,6 +19,7 @@ set ( SRC_FILES src/HFIRLoad.cpp src/HFIRSANSNormalise.cpp src/MuonCalculateAsymmetry.cpp + src/MuonLoad.cpp src/RefReduction.cpp src/RefRoi.cpp src/SANSBeamFinder.cpp @@ -56,6 +57,7 @@ set ( INC_FILES inc/MantidWorkflowAlgorithms/HFIRLoad.h inc/MantidWorkflowAlgorithms/HFIRSANSNormalise.h inc/MantidWorkflowAlgorithms/MuonCalculateAsymmetry.h + inc/MantidWorkflowAlgorithms/MuonLoad.h inc/MantidWorkflowAlgorithms/RefReduction.h inc/MantidWorkflowAlgorithms/RefRoi.h inc/MantidWorkflowAlgorithms/SANSBeamFinder.h @@ -70,6 +72,7 @@ set ( INC_FILES set ( TEST_FILES MuonCalculateAsymmetryTest.h + MuonLoadTest.h SANSSolidAngleCorrectionTest.h StepScanTest.h ) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h new file mode 100644 index 000000000000..d4b33800259f --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -0,0 +1,56 @@ +#ifndef MANTID_WORKFLOWALGORITHMS_MUONLOAD_H_ +#define MANTID_WORKFLOWALGORITHMS_MUONLOAD_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ +namespace WorkflowAlgorithms +{ + + /** MuonLoad : TODO: DESCRIPTION + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport MuonLoad : public API::Algorithm + { + public: + MuonLoad(); + virtual ~MuonLoad(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + + private: + virtual void initDocs(); + void init(); + void exec(); + + + }; + + +} // namespace WorkflowAlgorithms +} // namespace Mantid + +#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOAD_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp new file mode 100644 index 000000000000..c3442a361af7 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -0,0 +1,70 @@ +/*WIKI* +TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page. +*WIKI*/ + +#include "MantidWorkflowAlgorithms/MuonLoad.h" + +namespace Mantid +{ +namespace WorkflowAlgorithms +{ + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(MuonLoad) + + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + MuonLoad::MuonLoad() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + MuonLoad::~MuonLoad() + { + } + + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string MuonLoad::name() const { return "MuonLoad";}; + + /// Algorithm's version for identification. @see Algorithm::version + int MuonLoad::version() const { return 1;}; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string MuonLoad::category() const { return TODO: FILL IN A CATEGORY;} + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void MuonLoad::initDocs() + { + this->setWikiSummary("TODO: Enter a quick description of your algorithm."); + this->setOptionalMessage("TODO: Enter a quick description of your algorithm."); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void MuonLoad::init() + { + declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input), "An input workspace."); + declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace."); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void MuonLoad::exec() + { + // TODO Auto-generated execute stub + } + + + +} // namespace WorkflowAlgorithms +} // namespace Mantid \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h new file mode 100644 index 000000000000..026eb6d985f8 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -0,0 +1,60 @@ +#ifndef MANTID_WORKFLOWALGORITHMS_MUONLOADTEST_H_ +#define MANTID_WORKFLOWALGORITHMS_MUONLOADTEST_H_ + +#include + +#include "MantidWorkflowAlgorithms/MuonLoad.h" + +using Mantid::WorkflowAlgorithms::MuonLoad; + +class MuonLoadTest : public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static MuonLoadTest *createSuite() { return new MuonLoadTest(); } + static void destroySuite( MuonLoadTest *suite ) { delete suite; } + + + void test_Init() + { + MuonLoad alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_exec() + { + // Name of the output workspace. + std::string outWSName("MuonLoadTest_OutputWS"); + + MuonLoad alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("REPLACE_PROPERTY_NAME_HERE!!!!", "value") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. TODO: Change to your desired type + Workspace_sptr ws; + TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWSName) ); + TS_ASSERT(ws); + if (!ws) return; + + // TODO: Check the results + + // Remove workspace from the data service. + AnalysisDataService::Instance().remove(outWSName); + } + + void test_Something() + { + TSM_ASSERT( "You forgot to write a test!", 0); + } + + +}; + + +#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOADTEST_H_ */ \ No newline at end of file From 170480a136e85430222c72961279d8556e5f2508 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 10 Dec 2013 16:34:02 -0500 Subject: [PATCH 155/403] Re #8497. Added in a missing factor of 2pi. --- Code/Mantid/Framework/Crystal/src/PredictPeaks.cpp | 4 ++-- .../Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/src/PredictPeaks.cpp b/Code/Mantid/Framework/Crystal/src/PredictPeaks.cpp index 1e195549ef21..0a03cfdb7a5b 100644 --- a/Code/Mantid/Framework/Crystal/src/PredictPeaks.cpp +++ b/Code/Mantid/Framework/Crystal/src/PredictPeaks.cpp @@ -318,7 +318,7 @@ namespace Crystal { // ---------------- Determine which HKL to look for ------------------------------------- // Inverse d-spacing that is the limit to look for. - double dstar = 1.0/minD; + double Qmax = 2.*M_PI/minD; V3D hklMin(0,0,0); V3D hklMax(0,0,0); for (double qx=-1; qx < 2; qx += 2) @@ -327,7 +327,7 @@ namespace Crystal { // Build a q-vector for this corner of a cube V3D Q(qx,qy,qz); - Q *= dstar; + Q *= Qmax; V3D hkl = crystal.hklFromQ(Q); // Find the limits of each hkl for (size_t i=0; i<3; i++) diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp index e1b5647249f0..cecae9362640 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp @@ -163,7 +163,7 @@ namespace Geometry { DblMatrix UBinv = this->getUB(); UBinv.Invert(); - V3D out = UBinv*Q; //transform back to HKL + V3D out = UBinv*Q/TWO_PI; //transform back to HKL return out; } From 0e69da2351eaed80efa00afd8523517d9a15d298 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Wed, 11 Dec 2013 10:18:20 -0500 Subject: [PATCH 156/403] Re #8497. Missed a unit test that needed to be changed. --- Code/Mantid/Framework/Geometry/test/OrientedLatticeTest.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/Geometry/test/OrientedLatticeTest.h b/Code/Mantid/Framework/Geometry/test/OrientedLatticeTest.h index 2ea23bcbbb69..a2006de288f4 100644 --- a/Code/Mantid/Framework/Geometry/test/OrientedLatticeTest.h +++ b/Code/Mantid/Framework/Geometry/test/OrientedLatticeTest.h @@ -41,7 +41,7 @@ class OrientedLatticeTest : public CxxTest::TestSuite // Convert to and from HKL V3D hkl = u.hklFromQ(V3D(1.0, 2.0, 3.0)); double dstar = u.dstar(hkl[0], hkl[1], hkl[2]); - TS_ASSERT_DELTA( dstar, sqrt(1+4.0+9.0), 1e-4); // The d-spacing after a round trip matches the Q we put in + TS_ASSERT_DELTA( dstar, .5*sqrt(1+4.0+9.0)/M_PI, 1e-4); // The d-spacing after a round trip matches the Q we put in } From 153238e10deded09cdecd101fbfa59079359e71b Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 16:12:54 +0000 Subject: [PATCH 157/403] Refs #8494. Initial documentation and properties. --- .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 4 +- .../WorkflowAlgorithms/src/MuonLoad.cpp | 73 ++++++++++++++++--- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h index d4b33800259f..4a33a215abe1 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -9,7 +9,7 @@ namespace Mantid namespace WorkflowAlgorithms { - /** MuonLoad : TODO: DESCRIPTION + /** MuonLoad : loads Muon workspace ready for analysis. Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory @@ -53,4 +53,4 @@ namespace WorkflowAlgorithms } // namespace WorkflowAlgorithms } // namespace Mantid -#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOAD_H_ */ \ No newline at end of file +#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOAD_H_ */ diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index c3442a361af7..b845cfedf0ff 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -4,25 +4,33 @@ TODO: Enter a full wiki-markup description of your algorithm here. You can then #include "MantidWorkflowAlgorithms/MuonLoad.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/ListValidator.h" +#include "MantidAPI/FileProperty.h" +#include "MantidDataObjects/TableWorkspace.h" + namespace Mantid { namespace WorkflowAlgorithms { + using namespace Kernel; + using namespace API; + using namespace DataObjects; // Register the algorithm into the AlgorithmFactory DECLARE_ALGORITHM(MuonLoad) - - //---------------------------------------------------------------------------------------------- - /** Constructor + /** + * Constructor */ MuonLoad::MuonLoad() { } //---------------------------------------------------------------------------------------------- - /** Destructor + /** + * Destructor */ MuonLoad::~MuonLoad() { @@ -37,27 +45,68 @@ namespace WorkflowAlgorithms int MuonLoad::version() const { return 1;}; /// Algorithm's category for identification. @see Algorithm::category - const std::string MuonLoad::category() const { return TODO: FILL IN A CATEGORY;} + const std::string MuonLoad::category() const { return "Workflow\\Muon";} //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm void MuonLoad::initDocs() { - this->setWikiSummary("TODO: Enter a quick description of your algorithm."); - this->setOptionalMessage("TODO: Enter a quick description of your algorithm."); + this->setWikiSummary("Loads Muon workspace ready for analysis."); + this->setOptionalMessage("Loads Muon workspace ready for analysis."); } //---------------------------------------------------------------------------------------------- - /** Initialize the algorithm's properties. + /* + * Initialize the algorithm's properties. */ void MuonLoad::init() { - declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input), "An input workspace."); - declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace."); + declareProperty(new FileProperty("Filename", "", FileProperty::Load, ".nxs"), + "The name of the Nexus file to load" ); + + declareProperty("FirstPeriod", EMPTY_INT(), "Group index of the first period workspace to use"); + declareProperty("SecondPeriod", EMPTY_INT(), "Group index of the first period workspace to use"); + + std::vector allowedOperations; + allowedOperations.push_back("+"); allowedOperations.push_back("-"); + declareProperty("PeriodOperation","+", boost::make_shared(allowedOperations), + "If two periods specified, what operation to apply to workspaces to get a final one."); + + declareProperty("ApplyDeadTimeCorrection", false, + "Whether dead time correction should be applied to loaded workspace"); + declareProperty(new FileProperty("CustomDeadTimeFile", "", FileProperty::OptionalLoad, ".nxs"), + "Nexus file with custom dead time table. See LoadMuonNexus for format expected."); + + declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input), + "Table with detector grouping information. See LoadMuonNexus for format expected."); + + declareProperty("TimeZero", EMPTY_DBL(), "Value used for Time Zero correction."); + declareProperty(new ArrayProperty("RebinParams"), + "Params used for rebinning. If empty - rebinning is not done."); + declareProperty("Xmin", EMPTY_DBL(), "Minimal X value to include"); + declareProperty("Xmax", EMPTY_DBL(), "Maximal X value to include"); + + std::vector allowedTypes; + allowedTypes.push_back("PairAsymmetry"); + allowedTypes.push_back("GroupAsymmetry"); + allowedTypes.push_back("GroupCounts"); + declareProperty("OutputType", "PairAsymmetry", boost::make_shared(allowedTypes), + "What kind of workspace required for analysis."); + + declareProperty("PairFirstIndex", EMPTY_INT(), "Workspace index of the first pair group"); + declareProperty("PairSecondIndex", EMPTY_INT(), "Workspace index of the second pair group"); + declareProperty("PairAlpha", 1.0, "Alpha value of the pair"); + + declareProperty("GroupIndex", EMPTY_INT(), "Workspace index of the group"); + + declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), + "An output workspace."); } //---------------------------------------------------------------------------------------------- - /** Execute the algorithm. + /** + * Execute the algorithm. */ void MuonLoad::exec() { @@ -67,4 +116,4 @@ namespace WorkflowAlgorithms } // namespace WorkflowAlgorithms -} // namespace Mantid \ No newline at end of file +} // namespace Mantid From f8b41819012053d2ea02171f340dbbaf01462e41 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Wed, 11 Dec 2013 17:24:30 +0000 Subject: [PATCH 158/403] Refs #8494. Test for basic functionality. --- .../WorkflowAlgorithms/test/MuonLoadTest.h | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index 026eb6d985f8..3d8b5d7f6f6d 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -4,9 +4,16 @@ #include #include "MantidWorkflowAlgorithms/MuonLoad.h" +#include "MantidAPI/ScopedWorkspace.h" +#include "MantidAPI/TableRow.h" +#include "MantidDataObjects/TableWorkspace.h" using Mantid::WorkflowAlgorithms::MuonLoad; +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace Mantid::DataObjects; + class MuonLoadTest : public CxxTest::TestSuite { public: @@ -23,38 +30,60 @@ class MuonLoadTest : public CxxTest::TestSuite TS_ASSERT( alg.isInitialized() ) } - void test_exec() + void test_simpleLoad() { - // Name of the output workspace. - std::string outWSName("MuonLoadTest_OutputWS"); + ScopedWorkspace output; + + TableWorkspace_sptr grouping = createGroupingTable(); MuonLoad alg; TS_ASSERT_THROWS_NOTHING( alg.initialize() ) TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("REPLACE_PROPERTY_NAME_HERE!!!!", "value") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "emu00006473.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", grouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("OutputType", "GroupCounts") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("GroupIndex", 0) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", output.name()) ); TS_ASSERT_THROWS_NOTHING( alg.execute(); ); TS_ASSERT( alg.isExecuted() ); - // Retrieve the workspace from data service. TODO: Change to your desired type - Workspace_sptr ws; - TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS(outWSName) ); + // Retrieve the workspace from data service. + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast( output.retrieve() ); + TS_ASSERT(ws); - if (!ws) return; - - // TODO: Check the results - - // Remove workspace from the data service. - AnalysisDataService::Instance().remove(outWSName); + if (ws) + { + TSM_ASSERT( "You forgot to check the results!", 0); + } } - - void test_Something() + + TableWorkspace_sptr createGroupingTable() { - TSM_ASSERT( "You forgot to write a test!", 0); + auto t = boost::make_shared(); + + t->addColumn("vector_int", "Detectors"); + + std::vector group1; + for ( int i = 33; i <= 64; ++i ) + { + group1.push_back(i); + } + TableRow row1 = t->appendRow(); + row1 << group1; + + std::vector group2; + for ( int i = 1; i <= 32; ++i ) + { + group2.push_back(i); + } + TableRow row2 = t->appendRow(); + row2 << group2; + + return t; } }; -#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOADTEST_H_ */ \ No newline at end of file +#endif /* MANTID_WORKFLOWALGORITHMS_MUONLOADTEST_H_ */ From b972f73cdb529728c29f82e2322c58a668cfbd8d Mon Sep 17 00:00:00 2001 From: Roman Tolchenov Date: Thu, 12 Dec 2013 08:56:03 +0000 Subject: [PATCH 159/403] Re #8569. Manually setting a shift in u coordinate --- .../InstrumentWidget/InstrumentWindow.cpp | 20 +++++ .../InstrumentWidget/InstrumentWindow.h | 6 +- .../InstrumentWindowRenderTab.cpp | 80 ++++++++++++++++++- .../InstrumentWindowRenderTab.h | 4 + .../InstrumentWidget/RotationSurface.cpp | 43 +++++++--- .../Mantid/InstrumentWidget/RotationSurface.h | 6 +- 6 files changed, 146 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp index 18280a90c58d..24ef57e91856 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp @@ -55,6 +55,9 @@ using namespace Mantid::API; using namespace Mantid::Geometry; using namespace MantidQt::API; +// Name of the QSettings group to store the InstrumentWindw settings +const char* InstrumentWindowSettingsGroup = "Mantid/InstrumentWindow"; + /** * Constructor. */ @@ -1344,3 +1347,20 @@ void InstrumentWindow::createTabs(QSettings& settings) m_tabs << m_renderTab << pickTab << maskTab << treeTab; } + +/** + * Return a name for a group in QSettings to store InstrumentWindow configuration. + */ +QString InstrumentWindow::getSettingsGroupName() const +{ + return QString::fromAscii( InstrumentWindowSettingsGroup ); +} + +/** + * Construct a name for a group in QSettings to store instrument-specific configuration. + */ +QString InstrumentWindow::getInstrumentSettingsGroupName() const +{ + return QString::fromAscii( InstrumentWindowSettingsGroup ) + "/" + + QString::fromStdString( getInstrumentActor()->getInstrument()->getName() ); +} diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.h index 87f8a823af98..a88d305b0031 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.h @@ -91,7 +91,7 @@ class InstrumentWindow : public MdiSubWindow, public MantidQt::API::WorkspaceObs void setViewType(const QString& type); /// for saving the instrument window to mantid project QString saveToString(const QString& geometry, bool saveAsTemplate= false); - InstrumentActor* getInstrumentActor(){return m_instrumentActor;} + InstrumentActor* getInstrumentActor() const {return m_instrumentActor;} bool blocked()const{return m_blocked;} void selectTab(int tab); void selectTab(Tab tab){selectTab(int(tab));} @@ -99,6 +99,10 @@ class InstrumentWindow : public MdiSubWindow, public MantidQt::API::WorkspaceObs InstrumentWindowTab *getTab(const Tab tab) const; /// Get a filename for saving QString getSaveFileName(const QString& title, const QString& filters, QString* selectedFilter = NULL); + /// Get a name for settings group + QString getSettingsGroupName() const; + /// Get a name for a instrument-specific settings group + QString getInstrumentSettingsGroupName() const; signals: void enableLighting(bool); diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp index 2b6fbb146fa5..a170fd875bcd 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp @@ -2,6 +2,7 @@ #include "ProjectionSurface.h" #include "UnwrappedSurface.h" #include "Projection3D.h" +#include "RotationSurface.h" #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,6 +29,8 @@ #include "BinDialog.h" #include "ColorMapWidget.h" +#include + InstrumentWindowRenderTab::InstrumentWindowRenderTab(InstrumentWindow* instrWindow): InstrumentWindowTab(instrWindow) @@ -128,6 +132,8 @@ InstrumentWindowTab(instrWindow) m_wireframe->setCheckable(true); m_wireframe->setChecked(false); connect(m_wireframe, SIGNAL(toggled(bool)), m_instrWindow, SLOT(setWireframe(bool))); + m_UCorrection = new QAction("U Correction",this); + connect(m_UCorrection, SIGNAL(triggered()),this,SLOT(setUCorrection())); // Create "Use OpenGL" action m_GLView = new QAction("Use OpenGL",this); @@ -147,6 +153,8 @@ InstrumentWindowTab(instrWindow) displaySettingsMenu->addAction(m_wireframe); displaySettingsMenu->addAction(m_lighting); displaySettingsMenu->addAction(m_GLView); + displaySettingsMenu->addAction(m_UCorrection); + displaySettings->setMenu(displaySettingsMenu); connect(displaySettingsMenu,SIGNAL(hovered(QAction*)),this,SLOT(showMenuToolTip(QAction*))); @@ -251,20 +259,47 @@ void InstrumentWindowRenderTab::enable3DSurface(bool on) } } +/** + * Surface-specific adjustments. + */ void InstrumentWindowRenderTab::initSurface() { setAxis(QString::fromStdString(m_instrWindow->getInstrumentActor()->getInstrument()->getDefaultAxis())); auto surface = getSurface(); + + // 3D axes switch needs to be shown for the 3D surface auto p3d = boost::dynamic_pointer_cast(surface); if ( p3d ) { p3d->set3DAxesState(areAxesOn()); } + bool detectorsOnly = !m_instrWindow->getInstrumentActor()->areGuidesShown(); m_displayDetectorsOnly->blockSignals(true); m_displayDetectorsOnly->setChecked(detectorsOnly); m_displayDetectorsOnly->blockSignals(false); setPrecisionMenuItemChecked(surface->getPeakLabelPrecision()); + + // enable u-correction for surfaces of rotation. correction applied in the last + // session is loaded and re-applied in the new session + auto rotSurface = boost::dynamic_pointer_cast(surface); + if ( rotSurface ) + { + m_UCorrection->setEnabled(true); + QString groupName = m_instrWindow->getInstrumentSettingsGroupName(); + QSettings settings; + settings.beginGroup( groupName ); + bool isManualUCorrection = settings.value("ManualUCorrection",false).asBool(); + if ( isManualUCorrection ) + { + double ucorr = settings.value("UCorrection",0.0).asDouble(); + rotSurface->setUCorrection( ucorr ); + } + } + else + { + m_UCorrection->setEnabled(false); + } } /** @@ -491,7 +526,7 @@ void InstrumentWindowRenderTab::setColorMapAutoscaling(bool on) QMenu* InstrumentWindowRenderTab::createPeaksMenu() { QSettings settings; - settings.beginGroup("Mantid/InstrumentWindow"); + settings.beginGroup( m_instrWindow->getSettingsGroupName() ); QMenu* menu = new QMenu(this); // show/hide peak hkl labels @@ -631,3 +666,46 @@ void InstrumentWindowRenderTab::showMenuToolTip(QAction *action) QToolTip::showText(QCursor::pos(),action->toolTip(),this); } +/** + * Set the offset in u-coordinate of a 2d (unwrapped) surface + * @param ucorr :: New value for the correction. + */ +void InstrumentWindowRenderTab::setUCorrection() +{ + auto surface = getSurface(); + auto rotSurface = boost::dynamic_pointer_cast(surface); + if ( rotSurface ) + { + bool ok; + double oldUCorr = rotSurface->getUCorrection(); + // ask the user to enter a number for the u-correction + double ucorr = QInputDialog::getDouble(this, "MantiPplot - Input", + "U Correction", oldUCorr, -std::numeric_limits::max(),std::numeric_limits::max(), 4, &ok); + // update the surface only if the correction changes + if (ok && ucorr != oldUCorr) + { + rotSurface->setUCorrection( ucorr ); // manually set the correction + rotSurface->requestRedraw(); // redraw the view + QSettings settings; + settings.beginGroup( m_instrWindow->getInstrumentSettingsGroupName() ); + settings.setValue("ManualUCorrection",true); + settings.setValue("UCorrection",ucorr); + } + } +} + +/** + * Get current value for the u-correction for a RotationSurface. + * Return 0 if it's not a RotationSurface. + */ +double InstrumentWindowRenderTab::getUCorrection() const +{ + auto surface = getSurface(); + auto rotSurface = boost::dynamic_pointer_cast(surface); + if ( rotSurface ) + { + return rotSurface->getUCorrection(); + } + return 0.0; +} + diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h index 86a915619f10..ca8abe4a3b07 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h @@ -16,6 +16,7 @@ class QCheckBox; class QAction; class QActionGroup; class QMenu; +class QLineEdit; /** * Implements the Render tab in InstrumentWindow. @@ -66,6 +67,7 @@ private slots: void scaleTypeChanged(int); void glOptionChanged(bool); void showMenuToolTip(QAction*); + void setUCorrection(); private: void showEvent (QShowEvent *); @@ -73,6 +75,7 @@ private slots: QFrame * setupAxisFrame(); void setPrecisionMenuItemChecked(int n); void enable3DSurface( bool on ); + double getUCorrection() const; QPushButton *m_surfaceTypeButton; QPushButton *mSaveImage; @@ -100,6 +103,7 @@ private slots: QAction *m_wireframe; QAction *m_lighting; QAction *m_GLView; ///< toggle between OpenGL and simple view + QAction *m_UCorrection; QActionGroup *m_precisionActionGroup; QList m_precisionActions; diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.cpp index de03e72b60e9..a4e5d0b918b0 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.cpp @@ -10,7 +10,8 @@ RotationSurface::RotationSurface(const InstrumentActor* rootActor,const Mantid:: UnwrappedSurface(rootActor), m_pos(origin), m_zaxis(axis), - m_u_correction(0) + m_u_correction(0), + m_manual_u_correction(false) { } @@ -22,7 +23,10 @@ void RotationSurface::init() // the actor calls this->callback for each detector m_unwrappedDetectors.clear(); m_assemblies.clear(); - m_u_correction = 0.0; + if ( !m_manual_u_correction ) + { + m_u_correction = 0.0; + } size_t ndet = m_instrActor->ndetectors(); m_unwrappedDetectors.resize(ndet); @@ -67,10 +71,13 @@ void RotationSurface::init() m_yaxis = m_zaxis.cross_prod(m_xaxis); } - // give some valid values to u bounds in case some code checks - // on u to be within them - m_u_min = -DBL_MAX; - m_u_max = DBL_MAX; + if ( !m_manual_u_correction ) + { + // give some valid values to u bounds in case some code checks + // on u to be within them + m_u_min = -DBL_MAX; + m_u_max = DBL_MAX; + } // For each detector in the order of actors // cppcheck-suppress syntaxError @@ -130,7 +137,10 @@ void RotationSurface::init() if (udet.v > m_v_max) m_v_max = udet.v; } - findAndCorrectUGap(); + if ( !m_manual_u_correction ) + { + findAndCorrectUGap(); + } double dU = fabs(m_u_max - m_u_min); double dV = fabs(m_v_max - m_v_min); @@ -156,7 +166,8 @@ void RotationSurface::init() m_u_max += du; m_v_min -= dv; m_v_max += dv; - m_viewRect = RectF( QPointF(m_u_min,m_v_min), QPointF(m_u_max,m_v_max) ); + + m_viewRect = RectF( QPointF(m_u_min,m_v_min), QPointF(m_u_max,m_v_max) ); } @@ -249,12 +260,24 @@ double RotationSurface::applyUCorrection(double u)const u += m_u_correction; if (u < m_u_min) { - u += period; + double periods = floor( (m_u_max - u) / period ) * period; + u += periods; } if (u > m_u_max) { - u -= period; + double periods = floor( (u - m_u_min) / period ) * period; + u -= periods; } return u; } +/** + * Set new value for the u-correction. + * Correct all uv corrdinates of detectors. + */ +void RotationSurface::setUCorrection(double ucorr) +{ + m_u_correction = ucorr; + m_manual_u_correction = true; + this->updateDetectors(); +} diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.h index b77748be4b32..2ab6ef2b31e6 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/RotationSurface.h @@ -12,6 +12,10 @@ class RotationSurface: public UnwrappedSurface public: RotationSurface(const InstrumentActor* rootActor,const Mantid::Kernel::V3D& origin,const Mantid::Kernel::V3D& axis); void init(); + // Get the value of the u-correction - a shift in the u-coord added to automatically determined uv coordinates + double getUCorrection() const {return m_u_correction;} + // Set new value for the u-correction + void setUCorrection(double ucorr); protected: @@ -32,7 +36,7 @@ class RotationSurface: public UnwrappedSurface Mantid::Kernel::V3D m_xaxis; ///< The x axis Mantid::Kernel::V3D m_yaxis; ///< The y axis double m_u_correction; ///< Correction to u calculated by project() after findAndCorrectUGap() - + bool m_manual_u_correction; ///< Flag set to prevent automatic FindAndCorrectUGap() }; #endif // ROTATIONSURFACE_H From 3c9d43fedbc1e440757489609d470ce3ed5c0147 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 09:24:33 +0000 Subject: [PATCH 160/403] Refs #8494. Initial logic. No grouping, DTC or any other corrections applied yet. --- .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 6 + .../WorkflowAlgorithms/src/MuonLoad.cpp | 113 +++++++++++++++++- 2 files changed, 114 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h index 4a33a215abe1..4daa9498cb64 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -8,6 +8,8 @@ namespace Mantid { namespace WorkflowAlgorithms { + using namespace Kernel; + using namespace API; /** MuonLoad : loads Muon workspace ready for analysis. @@ -46,7 +48,11 @@ namespace WorkflowAlgorithms void init(); void exec(); + /// Returns a workspace for the first period as specified using FirstPeriod property. + MatrixWorkspace_sptr getFirstPeriodWS(WorkspaceGroup_sptr ws); + /// Returns a workspace for the second period as specified using SecondPeriod property. + MatrixWorkspace_sptr getSecondPeriodWS(WorkspaceGroup_sptr ws); }; diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index b845cfedf0ff..d7a61c3273e1 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -65,7 +65,7 @@ namespace WorkflowAlgorithms declareProperty(new FileProperty("Filename", "", FileProperty::Load, ".nxs"), "The name of the Nexus file to load" ); - declareProperty("FirstPeriod", EMPTY_INT(), "Group index of the first period workspace to use"); + declareProperty("FirstPeriod", 0, "Group index of the first period workspace to use"); declareProperty("SecondPeriod", EMPTY_INT(), "Group index of the first period workspace to use"); std::vector allowedOperations; @@ -78,8 +78,9 @@ namespace WorkflowAlgorithms declareProperty(new FileProperty("CustomDeadTimeFile", "", FileProperty::OptionalLoad, ".nxs"), "Nexus file with custom dead time table. See LoadMuonNexus for format expected."); - declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input), - "Table with detector grouping information. See LoadMuonNexus for format expected."); + declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input, + PropertyMode::Optional), "Table with detector grouping information." + " See LoadMuonNexus for format expected."); declareProperty("TimeZero", EMPTY_DBL(), "Value used for Time Zero correction."); declareProperty(new ArrayProperty("RebinParams"), @@ -96,7 +97,7 @@ namespace WorkflowAlgorithms declareProperty("PairFirstIndex", EMPTY_INT(), "Workspace index of the first pair group"); declareProperty("PairSecondIndex", EMPTY_INT(), "Workspace index of the second pair group"); - declareProperty("PairAlpha", 1.0, "Alpha value of the pair"); + declareProperty("Alpha", 1.0, "Alpha value of the pair"); declareProperty("GroupIndex", EMPTY_INT(), "Workspace index of the group"); @@ -110,10 +111,112 @@ namespace WorkflowAlgorithms */ void MuonLoad::exec() { - // TODO Auto-generated execute stub + const std::string filename = getProperty("Filename"); + + // Load the file + IAlgorithm_sptr load = createChildAlgorithm("LoadMuonNexus"); + load->setProperty("Filename", filename); + load->execute(); + + Workspace_sptr loadedWS = load->getProperty("OutputWorkspace"); + + MatrixWorkspace_sptr firstPeriodWS, secondPeriodWS; + + // Deal with single-period workspace + if ( auto ws = boost::dynamic_pointer_cast(loadedWS) ) + { + if ( static_cast( getProperty("FirstPeriod") ) != 0 ) + throw std::invalid_argument("Single period data but first period is not 0."); + + if ( static_cast( getProperty("SecondPeriod") ) != EMPTY_INT() ) + throw std::invalid_argument("Single period data but second period specified"); + + firstPeriodWS = ws; + } + // Deal with multi-period workspace + else if ( auto group = boost::dynamic_pointer_cast(loadedWS) ) + { + firstPeriodWS = getFirstPeriodWS(group); + secondPeriodWS = getSecondPeriodWS(group); + } + // Unexpected workspace type + else + { + throw std::runtime_error("Loaded workspace is of invalid type"); + } + + IAlgorithm_sptr calcAssym = createChildAlgorithm("MuonCalculateAsymmetry"); + + // Set period workspaces + calcAssym->setProperty("FirstPeriodWorkspace", firstPeriodWS); + calcAssym->setProperty("SecondPeriodWorkspace", secondPeriodWS); + + // Copy similar properties over + calcAssym->setProperty("PeriodOperation", + static_cast( getProperty("PeriodOperation") ) ); + calcAssym->setProperty("OutputType", + static_cast( getProperty("OutputType") ) ); + calcAssym->setProperty("PairFirstIndex", + static_cast( getProperty("PairFirstIndex") ) ); + calcAssym->setProperty("PairSecondIndex", + static_cast( getProperty("PairSecondIndex") ) ); + calcAssym->setProperty("Alpha", + static_cast( getProperty("Alpha") ) ); + calcAssym->setProperty("GroupIndex", + static_cast( getProperty("GroupIndex") ) ); + + calcAssym->execute(); + + MatrixWorkspace_sptr outWS = calcAssym->getProperty("OutputWorkspace"); + setProperty("OutputWorkspace", outWS); } + /** + * Returns a workspace for the first period as specified using FirstPeriod property. + * @param group :: Loaded group of workspaces to use + * @return Workspace for the period + */ + MatrixWorkspace_sptr MuonLoad::getFirstPeriodWS(WorkspaceGroup_sptr group) + { + int firstPeriod = getProperty("FirstPeriod"); + + MatrixWorkspace_sptr resultWS; + + if ( firstPeriod < 0 || firstPeriod >= static_cast( group->size() ) ) + throw std::invalid_argument("Workspace doesn't contain specified first period"); + + resultWS = boost::dynamic_pointer_cast( group->getItem(firstPeriod) ); + + if ( ! resultWS ) + throw std::invalid_argument("First period workspace is not a MatrixWorkspace"); + + return resultWS; + } + /** + * Returns a workspace for the second period as specified using SecondPeriod property. + * @param group :: Loaded group of workspaces to use + * @return Workspace for the period + */ + MatrixWorkspace_sptr MuonLoad::getSecondPeriodWS(WorkspaceGroup_sptr group) + { + int secondPeriod = getProperty("SecondPeriod"); + + MatrixWorkspace_sptr resultWS; + + if ( secondPeriod != EMPTY_INT() ) + { + if ( secondPeriod < 0 || secondPeriod >= static_cast( group->size() ) ) + throw std::invalid_argument("Workspace doesn't contain specified second period"); + + resultWS = boost::dynamic_pointer_cast( group->getItem(secondPeriod) ); + + if ( ! resultWS ) + throw std::invalid_argument("Second period workspace is not a MatrixWorkspace"); + } + + return resultWS; + } } // namespace WorkflowAlgorithms } // namespace Mantid From bde2a4b2103509f508a5eb1d51f1d3ece7bd8f7c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 10:05:57 +0000 Subject: [PATCH 161/403] Refs #8494. Grouping functionality. --- .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 3 ++ .../WorkflowAlgorithms/src/MuonLoad.cpp | 44 ++++++++++++++++--- .../WorkflowAlgorithms/test/MuonLoadTest.h | 19 ++++++-- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h index 4daa9498cb64..61b0ab6a0fe3 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -53,6 +53,9 @@ namespace WorkflowAlgorithms /// Returns a workspace for the second period as specified using SecondPeriod property. MatrixWorkspace_sptr getSecondPeriodWS(WorkspaceGroup_sptr ws); + + /// Groups specified workspace according to specified DetectorGroupingTable. + MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_sptr ws); }; diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index d7a61c3273e1..171f42b6d808 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -69,7 +69,8 @@ namespace WorkflowAlgorithms declareProperty("SecondPeriod", EMPTY_INT(), "Group index of the first period workspace to use"); std::vector allowedOperations; - allowedOperations.push_back("+"); allowedOperations.push_back("-"); + allowedOperations.push_back("+"); + allowedOperations.push_back("-"); declareProperty("PeriodOperation","+", boost::make_shared(allowedOperations), "If two periods specified, what operation to apply to workspaces to get a final one."); @@ -78,9 +79,8 @@ namespace WorkflowAlgorithms declareProperty(new FileProperty("CustomDeadTimeFile", "", FileProperty::OptionalLoad, ".nxs"), "Nexus file with custom dead time table. See LoadMuonNexus for format expected."); - declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input, - PropertyMode::Optional), "Table with detector grouping information." - " See LoadMuonNexus for format expected."); + declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input), + "Table with detector grouping information. See LoadMuonNexus for format expected."); declareProperty("TimeZero", EMPTY_DBL(), "Value used for Time Zero correction."); declareProperty(new ArrayProperty("RebinParams"), @@ -144,12 +144,25 @@ namespace WorkflowAlgorithms { throw std::runtime_error("Loaded workspace is of invalid type"); } - + + // TODO: deal with dead time correction + + // Deal with grouping + firstPeriodWS = groupWorkspace(firstPeriodWS); + + if ( secondPeriodWS ) + secondPeriodWS = groupWorkspace(secondPeriodWS); + + // TODO: offsetting, cropping, rebinning + IAlgorithm_sptr calcAssym = createChildAlgorithm("MuonCalculateAsymmetry"); - // Set period workspaces + // Set first period workspace calcAssym->setProperty("FirstPeriodWorkspace", firstPeriodWS); - calcAssym->setProperty("SecondPeriodWorkspace", secondPeriodWS); + + // Set second period workspace, if have one + if ( secondPeriodWS ) + calcAssym->setProperty("SecondPeriodWorkspace", secondPeriodWS); // Copy similar properties over calcAssym->setProperty("PeriodOperation", @@ -218,5 +231,22 @@ namespace WorkflowAlgorithms return resultWS; } + /** + * Groups specified workspace according to specified DetectorGroupingTable. + * @param ws :: Workspace to group + * @return Grouped workspace + */ + MatrixWorkspace_sptr MuonLoad::groupWorkspace(MatrixWorkspace_sptr ws) + { + TableWorkspace_sptr grouping = getProperty("DetectorGroupingTable"); + + IAlgorithm_sptr group = createChildAlgorithm("MuonGroupDetectors"); + group->setProperty("InputWorkspace", ws); + group->setProperty("DetectorGroupingTable", grouping); + group->execute(); + + return group->getProperty("OutputWorkspace"); + } + } // namespace WorkflowAlgorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index 3d8b5d7f6f6d..73107746fbdc 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -53,7 +53,20 @@ class MuonLoadTest : public CxxTest::TestSuite TS_ASSERT(ws); if (ws) { - TSM_ASSERT( "You forgot to check the results!", 0); + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 1 ); + TS_ASSERT_EQUALS( ws->blocksize(), 2000 ); + + TS_ASSERT_EQUALS( ws->readY(0)[0], 461 ); + TS_ASSERT_EQUALS( ws->readY(0)[1000], 192 ); + TS_ASSERT_EQUALS( ws->readY(0)[1752], 5 ); + + TS_ASSERT_DELTA( ws->readE(0)[0], 21.471, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1000], 13.856, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1752], 2.236, 0.001 ); + + TS_ASSERT_DELTA( ws->readX(0)[0], -0.254, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1000], 15.746, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1752], 27.778, 0.001 ); } } @@ -64,7 +77,7 @@ class MuonLoadTest : public CxxTest::TestSuite t->addColumn("vector_int", "Detectors"); std::vector group1; - for ( int i = 33; i <= 64; ++i ) + for ( int i = 1; i <= 16; ++i ) { group1.push_back(i); } @@ -72,7 +85,7 @@ class MuonLoadTest : public CxxTest::TestSuite row1 << group1; std::vector group2; - for ( int i = 1; i <= 32; ++i ) + for ( int i = 17; i <= 32; ++i ) { group2.push_back(i); } From 4f290916d0f39c0df54dcd0823733dc6cd01bf11 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 10:23:18 +0000 Subject: [PATCH 162/403] Refs #8494. Test for multi-period data. --- .../WorkflowAlgorithms/test/MuonLoadTest.h | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index 73107746fbdc..de08d8e95fc1 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -34,7 +34,15 @@ class MuonLoadTest : public CxxTest::TestSuite { ScopedWorkspace output; - TableWorkspace_sptr grouping = createGroupingTable(); + std::vector group1, group2; + + for ( int i = 1; i <= 16; ++i ) + group1.push_back(i); + + for ( int i = 17; i <= 32; ++i ) + group2.push_back(i); + + TableWorkspace_sptr grouping = createGroupingTable(group1, group2); MuonLoad alg; TS_ASSERT_THROWS_NOTHING( alg.initialize() ) @@ -70,32 +78,71 @@ class MuonLoadTest : public CxxTest::TestSuite } } - TableWorkspace_sptr createGroupingTable() + void test_multiPeriod() { - auto t = boost::make_shared(); + ScopedWorkspace output; - t->addColumn("vector_int", "Detectors"); + std::vector group1, group2; - std::vector group1; - for ( int i = 1; i <= 16; ++i ) - { + for ( int i = 33; i <= 64; ++i ) group1.push_back(i); + for ( int i = 1; i <= 32; ++i ) + group2.push_back(i); + + TableWorkspace_sptr grouping = createGroupingTable(group1, group2); + + MuonLoad alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "MUSR00015189.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("FirstPeriod", 0) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("SecondPeriod", 1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("PeriodOperation", "+") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", grouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("OutputType", "GroupCounts") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("GroupIndex", 1) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", output.name()) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast( output.retrieve() ); + + TS_ASSERT(ws); + if (ws) + { + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 1 ); + TS_ASSERT_EQUALS( ws->blocksize(), 2000 ); + + TS_ASSERT_EQUALS( ws->readY(0)[0], 23); + TS_ASSERT_EQUALS( ws->readY(0)[1000], 3); + TS_ASSERT_EQUALS( ws->readY(0)[1701], 1); + + TS_ASSERT_DELTA( ws->readE(0)[0], 4.796, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1000], 1.732, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1701], 1.000, 0.001 ); + + TS_ASSERT_DELTA( ws->readX(0)[0], -0.550, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1000], 15.450, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1701], 26.666, 0.001 ); } + } + + TableWorkspace_sptr createGroupingTable(const std::vector& group1, const std::vector& group2) + { + auto t = boost::make_shared(); + + t->addColumn("vector_int", "Detectors"); + TableRow row1 = t->appendRow(); row1 << group1; - std::vector group2; - for ( int i = 17; i <= 32; ++i ) - { - group2.push_back(i); - } TableRow row2 = t->appendRow(); row2 << group2; return t; } - }; From 9cc05743f49bf6d82855e9e85d9c9a4c1e17f3f9 Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Thu, 12 Dec 2013 12:22:27 +0000 Subject: [PATCH 163/403] Set properties for a given ICATProxy. Refs #8607. --- .../ICat/inc/MantidICat/ICat4/ICat4Catalog.h | 4 +- .../Framework/ICat/src/ICat4/ICat4Catalog.cpp | 40 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h index 2523525a4360..b6d15a6c6c18 100644 --- a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h +++ b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat4/ICat4Catalog.h @@ -86,8 +86,8 @@ namespace Mantid std::string bytesToString(int64_t &fileSize); // Helper method that formats a given timestamp. std::string formatDateTime(const time_t ×tamp, const std::string &format); - // Sets the soap-endpoint & SSL context for the proxy being returned. - ICat4::ICATPortBindingProxy getICATProxy(); + // Sets the soap-endpoint & SSL context for the given ICAT proxy. + void setICATProxySettings(ICat4::ICATPortBindingProxy& icat); // Reference to the logger class. Kernel::Logger& g_log; diff --git a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp index 965b5582d4c6..b2448ffc10da 100644 --- a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp @@ -30,8 +30,10 @@ namespace Mantid { // Store the soap end-point in the session for use later. ICat::Session::Instance().setSoapEndPoint(url); - // Obtain the ICAT proxy that has been securely set, including soap-endpoint. - ICat4::ICATPortBindingProxy icat = getICATProxy(); + // Securely set, including soap-endpoint. + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); + // Output the soap end-point in use for debugging purposes. g_log.debug() << "The ICAT soap end-point is: " << icat.soap_endpoint << "\n"; @@ -87,7 +89,8 @@ namespace Mantid */ void ICat4Catalog::logout() { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__logout request; ns1__logoutResponse response; @@ -257,7 +260,8 @@ namespace Mantid g_log.debug() << "ICat4Catalog::search -> Query is: { " << query << " }" << std::endl; - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -284,7 +288,8 @@ namespace Mantid */ int64_t ICat4Catalog::getNumberOfSearchResults(const CatalogSearchParam& inputs) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -326,7 +331,8 @@ namespace Mantid */ void ICat4Catalog::myData(Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -431,7 +437,8 @@ namespace Mantid */ void ICat4Catalog::getDataSets(const long long& investigationId, Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -499,7 +506,8 @@ namespace Mantid */ void ICat4Catalog::getDataFiles(const long long& investigationId, Mantid::API::ITableWorkspace_sptr& outputws) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -576,7 +584,8 @@ namespace Mantid */ void ICat4Catalog::listInstruments(std::vector& instruments) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -616,7 +625,8 @@ namespace Mantid */ void ICat4Catalog::listInvestigationTypes(std::vector& invstTypes) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__search request; ns1__searchResponse response; @@ -657,7 +667,8 @@ namespace Mantid */ void ICat4Catalog::getFileLocation(const long long & fileID, std::string & fileLocation) { - ICat4::ICATPortBindingProxy icat = getICATProxy(); + ICat4::ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__get request; ns1__getResponse response; @@ -810,17 +821,14 @@ namespace Mantid } /** - * Sets the soap-endpoint & SSL context for the proxy being returned. - * @return ICATPortBindingProxy :: The proxy with set endpoint & SSL context. + * Sets the soap-endpoint & SSL context for the given ICAT proxy. */ - ICat4::ICATPortBindingProxy ICat4Catalog::getICATProxy() + void ICat4Catalog::setICATProxySettings(ICat4::ICATPortBindingProxy& icat) { - ICat4::ICATPortBindingProxy icat; // Set the soap-endpoint of the catalog we want to use. icat.soap_endpoint = ICat::Session::Instance().getSoapEndPoint().c_str(); // Sets SSL authentication scheme setSSLContext(icat); - return icat; } } } From 1db0923974c886f86b0260c5efea3ab7f1a58e8b Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Thu, 12 Dec 2013 12:30:53 +0000 Subject: [PATCH 164/403] Set properties for a given ICAT3Proxy. Refs #8607. --- .../ICat/inc/MantidICat/ICat3/ICat3Helper.h | 4 +- .../Framework/ICat/src/ICat3/ICat3Helper.cpp | 55 +++++++++++-------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h index 0adacff7f382..6cb98192381d 100644 --- a/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h +++ b/Code/Mantid/Framework/ICat/inc/MantidICat/ICat3/ICat3Helper.h @@ -135,8 +135,8 @@ namespace Mantid // Defines the SSL authentication scheme. void setSSLContext(ICat3::ICATPortBindingProxy& icat); - // Sets the soap-endpoint & SSL context for the proxy being returned. - ICat3::ICATPortBindingProxy getICATProxy(); + // Sets the soap-endpoint & SSL context for the given ICAT proxy. + void setICATProxySettings(ICat3::ICATPortBindingProxy& icat); /** This is a template method to save data to table workspace * @param input :: pointer to input value diff --git a/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp b/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp index 74a4c4a1eed3..dab2fab53679 100644 --- a/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat3/ICat3Helper.cpp @@ -25,7 +25,8 @@ namespace Mantid */ int CICatHelper::doSearch(ICATPortBindingProxy& icat,boost::shared_ptr& request,ns1__searchByAdvancedResponse& response) { - icat = getICATProxy(); + setICATProxySettings(icat); + clock_t start=clock(); int ret_advsearch=icat.searchByAdvanced(request.get(),&response); if(ret_advsearch!=0) @@ -275,7 +276,8 @@ namespace Mantid API::ITableWorkspace_sptr& responsews_sptr) { //ICAt proxy object - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__getInvestigationIncludes request; //get the sessionid which is cached in session class during login @@ -411,7 +413,8 @@ namespace Mantid API::ITableWorkspace_sptr& responsews_sptr) { //ICAt proxy object - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); // request object ns1__getInvestigationIncludes request; @@ -507,7 +510,8 @@ namespace Mantid void CICatHelper::listInstruments(std::vector& instruments) { //ICAt proxy object - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__listInstruments request; //get the sessionid which is cached in session class during login @@ -558,7 +562,8 @@ namespace Mantid void CICatHelper::listInvestigationTypes(std::vector& investTypes) { //ICAt proxy object - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__listInvestigationTypes request; //get the sessionid which is cached in session class during login @@ -620,7 +625,8 @@ namespace Mantid */ int CICatHelper::doLogout() { - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__logout request; ns1__logoutResponse response; @@ -642,7 +648,8 @@ namespace Mantid */ void CICatHelper::doMyDataSearch(API::ITableWorkspace_sptr& ws_sptr) { - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__getMyInvestigationsIncludes request; ns1__getMyInvestigationsIncludesResponse response; @@ -723,8 +730,8 @@ namespace Mantid request.startIndex = offset; request.advancedSearchDetails = buildSearchQuery(inputs); - //ICAt proxy object - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); int result = icat.searchByAdvancedPagination(&request, &response); @@ -843,7 +850,8 @@ namespace Mantid */ int64_t CICatHelper::getNumberOfSearchResults(const CatalogSearchParam& inputs) { - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__searchByAdvanced request; ns1__searchByAdvancedResponse response; @@ -875,8 +883,8 @@ namespace Mantid */ bool CICatHelper::isvalidSession() { - - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__isSessionValid request; ns1__isSessionValidResponse response; @@ -897,8 +905,11 @@ namespace Mantid { // Store the soap end-point in the session for use later. ICat::Session::Instance().setSoapEndPoint(url); + // Obtain the ICAT proxy that has been securely set, including soap-endpoint. - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); + // Output the soap end-point in use for debugging purposes. g_log.debug() << "The ICAT soap end-point is: " << icat.soap_endpoint << "\n"; @@ -931,8 +942,8 @@ namespace Mantid void CICatHelper::getdownloadURL(const long long& fileId,std::string& url) { - - ICATPortBindingProxy icat = getICATProxy(); + ICATPortBindingProxy icat; + setICATProxySettings(icat); ns1__downloadDatafile request; @@ -963,9 +974,9 @@ namespace Mantid void CICatHelper::getlocationString(const long long& fileid,std::string& filelocation) { - - ICATPortBindingProxy icat = getICATProxy(); - + ICATPortBindingProxy icat; + setICATProxySettings(icat); + ns1__getDatafile request; boost::shared_ptrsessionId_sptr(new std::string); @@ -988,18 +999,16 @@ namespace Mantid } /** - * Sets the soap-endpoint & SSL context for the proxy being returned. - * @return ICATPortBindingProxy :: The proxy with set endpoint & SSL context. + * Sets the soap-endpoint & SSL context for the given ICAT proxy. */ - ICat3::ICATPortBindingProxy CICatHelper::getICATProxy() + void CICatHelper::setICATProxySettings(ICat3::ICATPortBindingProxy& icat) { - ICat3::ICATPortBindingProxy icat; // Set the soap-endpoint of the catalog we want to use. icat.soap_endpoint = ICat::Session::Instance().getSoapEndPoint().c_str(); // Sets SSL authentication scheme setSSLContext(icat); - return icat; } + /** * Defines the SSL authentication scheme. * @param icat :: ICATPortBindingProxy object. From 7810548d3ddfd8bcc7cfd8a1ffb09202193e59fb Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 13:27:40 +0000 Subject: [PATCH 165/403] Refs #8494. Bin value correction. --- .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 3 + .../WorkflowAlgorithms/src/MuonLoad.cpp | 81 ++++++++++++++++++- .../WorkflowAlgorithms/test/MuonLoadTest.h | 51 ++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h index 61b0ab6a0fe3..69f11abcdca3 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -56,6 +56,9 @@ namespace WorkflowAlgorithms /// Groups specified workspace according to specified DetectorGroupingTable. MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_sptr ws); + + /// Applies offset, crops and rebin the workspace according to specified params + MatrixWorkspace_sptr correctWorkspace(MatrixWorkspace_sptr ws, double loadedTimeZero); }; diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index 171f42b6d808..4d3d02aa41bb 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -153,7 +153,13 @@ namespace WorkflowAlgorithms if ( secondPeriodWS ) secondPeriodWS = groupWorkspace(secondPeriodWS); - // TODO: offsetting, cropping, rebinning + // Correct bin values + double loadedTimeZero = load->getProperty("TimeZero"); + + firstPeriodWS = correctWorkspace(firstPeriodWS, loadedTimeZero); + + if ( secondPeriodWS ) + secondPeriodWS = correctWorkspace(secondPeriodWS, loadedTimeZero); IAlgorithm_sptr calcAssym = createChildAlgorithm("MuonCalculateAsymmetry"); @@ -248,5 +254,78 @@ namespace WorkflowAlgorithms return group->getProperty("OutputWorkspace"); } + /** + * Applies offset, crops and rebin the workspace according to specified params. + * @param ws :: Workspace to correct + * @param loadedTimeZero :: Time zero of the data, so we can calculate the offset + * @return Corrected workspace + */ + MatrixWorkspace_sptr MuonLoad::correctWorkspace(MatrixWorkspace_sptr ws, double loadedTimeZero) + { + // Offset workspace, if need to + double timeZero = getProperty("TimeZero"); + if ( timeZero != EMPTY_DBL() ) + { + double offset = loadedTimeZero - timeZero; + + IAlgorithm_sptr changeOffset = createChildAlgorithm("ChangeBinOffset"); + changeOffset->setProperty("InputWorkspace", ws); + changeOffset->setProperty("Offset", offset); + changeOffset->execute(); + + ws = changeOffset->getProperty("OutputWorkspace"); + } + + // Crop workspace, if need to + double Xmin = getProperty("Xmin"); + double Xmax = getProperty("Xmax"); + if ( Xmin != EMPTY_DBL() || Xmax != EMPTY_DBL() ) + { + IAlgorithm_sptr crop = createChildAlgorithm("CropWorkspace"); + crop->setProperty("InputWorkspace", ws); + + if ( Xmin != EMPTY_DBL() ) + crop->setProperty("Xmin", Xmin); + + if ( Xmax != EMPTY_DBL() ) + crop->setProperty("Xmax", Xmax); + + crop->execute(); + + ws = crop->getProperty("OutputWorkspace"); + } + + // Rebin workspace if need to + std::vector rebinParams = getProperty("RebinParams"); + if ( ! rebinParams.empty() ) + { + IAlgorithm_sptr rebin = createChildAlgorithm("Rebin"); + rebin->setProperty("InputWorkspace", ws); + rebin->setProperty("Params", rebinParams); + rebin->execute(); + + ws = rebin->getProperty("OutputWorkspace"); + + // TODO: following should be removed when FullBinsOnly function is added to Rebin algorithm + + // Muon group don't want last bin if shorter than previous bins + double binSize = ws->dataX(0)[1] - ws->dataX(0)[0]; + size_t numBins = ws->dataX(0).size(); + + if ( (ws->dataX(0)[numBins-1] - ws->dataX(0)[numBins-2]) != binSize ) + { + IAlgorithm_sptr crop2 = createChildAlgorithm("CropWorkspace"); + crop2->setProperty("InputWorkspace", ws); + crop2->setProperty("Xmax", ws->dataX(0)[numBins-2]); + crop2->execute(); + + ws = crop2->getProperty("OutputWorkspace"); + } + } + + + return ws; + } + } // namespace WorkflowAlgorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index de08d8e95fc1..7ebf3ff0055c 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -128,6 +128,57 @@ class MuonLoadTest : public CxxTest::TestSuite } } + void test_binCorrectionParams() + { + ScopedWorkspace output; + + std::vector group1, group2; + + for ( int i = 1; i <= 16; ++i ) + group1.push_back(i); + for ( int i = 17; i <= 32; ++i ) + group2.push_back(i); + + TableWorkspace_sptr grouping = createGroupingTable(group1, group2); + + MuonLoad alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "emu00006473.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", grouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("OutputType", "GroupCounts") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("GroupIndex", 0) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("TimeZero", 0.5) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Xmin", 0.1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Xmax", 16.0) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("RebinParams", "0.08") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", output.name()) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast( output.retrieve() ); + + TS_ASSERT(ws); + if (ws) + { + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 1 ); + TS_ASSERT_EQUALS( ws->blocksize(), 198 ); + + TS_ASSERT_DELTA( ws->readX(0)[0], 0.102, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[100], 8.102, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[198], 15.942, 0.001 ); + + TS_ASSERT_DELTA( ws->readY(0)[0], 1024372.2, 0.1); + TS_ASSERT_DELTA( ws->readY(0)[100], 24589.0, 0.1); + TS_ASSERT_DELTA( ws->readY(0)[197], 730.0, 0.1); + + TS_ASSERT_DELTA( ws->readE(0)[0], 1012.113, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[100], 156.809, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[197], 27.019, 0.001 ); + } + } + TableWorkspace_sptr createGroupingTable(const std::vector& group1, const std::vector& group2) { auto t = boost::make_shared(); From b70a3b288faee9c596c0618620352f559549270f Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 14:15:57 +0000 Subject: [PATCH 166/403] Refs #8494. Dead time correction functionality. --- .../inc/MantidWorkflowAlgorithms/MuonLoad.h | 5 ++ .../WorkflowAlgorithms/src/MuonLoad.cpp | 42 ++++++++++++- .../WorkflowAlgorithms/test/MuonLoadTest.h | 59 +++++++++++++++++++ 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h index 69f11abcdca3..1a2e4b471f6c 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonLoad.h @@ -3,6 +3,7 @@ #include "MantidKernel/System.h" #include "MantidAPI/Algorithm.h" +#include "MantidDataObjects/TableWorkspace.h" namespace Mantid { @@ -10,6 +11,7 @@ namespace WorkflowAlgorithms { using namespace Kernel; using namespace API; + using namespace DataObjects; /** MuonLoad : loads Muon workspace ready for analysis. @@ -57,6 +59,9 @@ namespace WorkflowAlgorithms /// Groups specified workspace according to specified DetectorGroupingTable. MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_sptr ws); + /// Applies dead time correction to the workspace. + MatrixWorkspace_sptr applyDTC(MatrixWorkspace_sptr ws, TableWorkspace_sptr dt); + /// Applies offset, crops and rebin the workspace according to specified params MatrixWorkspace_sptr correctWorkspace(MatrixWorkspace_sptr ws, double loadedTimeZero); }; diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index 4d3d02aa41bb..884768e8b600 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -76,8 +76,8 @@ namespace WorkflowAlgorithms declareProperty("ApplyDeadTimeCorrection", false, "Whether dead time correction should be applied to loaded workspace"); - declareProperty(new FileProperty("CustomDeadTimeFile", "", FileProperty::OptionalLoad, ".nxs"), - "Nexus file with custom dead time table. See LoadMuonNexus for format expected."); + declareProperty(new WorkspaceProperty("CustomDeadTimeTable", "",Direction::Input, + PropertyMode::Optional), "Table with dead time information. See LoadMuonNexus for format expected."); declareProperty(new WorkspaceProperty("DetectorGroupingTable","",Direction::Input), "Table with detector grouping information. See LoadMuonNexus for format expected."); @@ -116,6 +116,7 @@ namespace WorkflowAlgorithms // Load the file IAlgorithm_sptr load = createChildAlgorithm("LoadMuonNexus"); load->setProperty("Filename", filename); + load->setProperty("DeadTimeTable", "__YouDontSeeMeIAmNinja"); // Name is not used (child alg.) load->execute(); Workspace_sptr loadedWS = load->getProperty("OutputWorkspace"); @@ -145,7 +146,26 @@ namespace WorkflowAlgorithms throw std::runtime_error("Loaded workspace is of invalid type"); } - // TODO: deal with dead time correction + // Deal with dead time correction (if required + bool applyDtc = getProperty("ApplyDeadTimeCorrection"); + if ( applyDtc ) + { + TableWorkspace_sptr deadTimes = getProperty("CustomDeadTimeTable"); + + if ( ! deadTimes ) + { + // If no dead times specified - try to use ones from the file + deadTimes = load->getProperty("DeadTimeTable"); + + if ( ! deadTimes ) + throw std::runtime_error("File doesn't contain any dead times"); + } + + firstPeriodWS = applyDTC(firstPeriodWS, deadTimes); + + if ( secondPeriodWS ) + secondPeriodWS = applyDTC(secondPeriodWS, deadTimes); + } // Deal with grouping firstPeriodWS = groupWorkspace(firstPeriodWS); @@ -254,6 +274,22 @@ namespace WorkflowAlgorithms return group->getProperty("OutputWorkspace"); } + /** + * Applies dead time correction to the workspace. + * @param ws :: Workspace to apply correction + * @param dt :: Dead time table to use + * @return Corrected workspace + */ + MatrixWorkspace_sptr MuonLoad::applyDTC(MatrixWorkspace_sptr ws, TableWorkspace_sptr dt) + { + IAlgorithm_sptr dtc = createChildAlgorithm("ApplyDeadTimeCorr"); + dtc->setProperty("InputWorkspace", ws); + dtc->setProperty("DeadTimeTable", dt); + dtc->execute(); + + return dtc->getProperty("OutputWorkspace"); + } + /** * Applies offset, crops and rebin the workspace according to specified params. * @param ws :: Workspace to correct diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index 7ebf3ff0055c..94c99d69f2db 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -179,6 +179,65 @@ class MuonLoadTest : public CxxTest::TestSuite } } + void test_deadTimeCorrection() + { + ScopedWorkspace output; + + std::vector group1, group2; + + for ( int i = 1; i <= 16; ++i ) + group1.push_back(i); + for ( int i = 17; i <= 32; ++i ) + group2.push_back(i); + + TableWorkspace_sptr grouping = createGroupingTable(group1, group2); + + auto deadTimes = boost::make_shared(); + deadTimes->addColumn("int", "spectrum"); + deadTimes->addColumn("double", "dead-time"); + + for ( int i = 0; i < 32; ++i ) + { + TableRow newRow = deadTimes->appendRow(); + newRow << (i+1) << 1.0; + } + + MuonLoad alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "emu00006473.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", grouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("ApplyDeadTimeCorrection", true) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("CustomDeadTimeTable", deadTimes) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("OutputType", "GroupCounts") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("GroupIndex", 0) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", output.name()) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast( output.retrieve() ); + + TS_ASSERT(ws); + if (ws) + { + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 1 ); + TS_ASSERT_EQUALS( ws->blocksize(), 2000 ); + + TS_ASSERT_DELTA( ws->readY(0)[0], 463.383, 0.001 ); + TS_ASSERT_DELTA( ws->readY(0)[1000], 192.468, 0.001 ); + TS_ASSERT_DELTA( ws->readY(0)[1752], 5.00075, 0.00001 ) ; + + TS_ASSERT_DELTA( ws->readE(0)[0], 21.471, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1000], 13.856, 0.001 ); + TS_ASSERT_DELTA( ws->readE(0)[1752], 2.236, 0.001 ); + + TS_ASSERT_DELTA( ws->readX(0)[0], -0.254, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1000], 15.746, 0.001 ); + TS_ASSERT_DELTA( ws->readX(0)[1752], 27.778, 0.001 ); + } + } + TableWorkspace_sptr createGroupingTable(const std::vector& group1, const std::vector& group2) { auto t = boost::make_shared(); From 7d4eac1c5dfcb81b00929f538ef927e7157b2896 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 14:28:26 +0000 Subject: [PATCH 167/403] Refs #8494. Simple test for error reporting. --- .../WorkflowAlgorithms/test/MuonLoadTest.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h index 94c99d69f2db..8ebb33e6044c 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/test/MuonLoadTest.h @@ -238,6 +238,30 @@ class MuonLoadTest : public CxxTest::TestSuite } } + void test_errorReporting() + { + ScopedWorkspace output; + + auto emptyGrouping = createGroupingTable(std::vector(), std::vector()); + + MuonLoad alg; + alg.setRethrows(true); + + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + + TS_ASSERT_THROWS( alg.setPropertyValue("Filename", "non-existent-file.nxs"), std::invalid_argument ); + + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "emu00006473.nxs") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("DetectorGroupingTable", emptyGrouping) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("OutputType", "GroupCounts") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("GroupIndex", 0) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", output.name()) ); + + TS_ASSERT_THROWS( alg.execute(), std::invalid_argument ); + TS_ASSERT( ! alg.isExecuted() ); + } + TableWorkspace_sptr createGroupingTable(const std::vector& group1, const std::vector& group2) { auto t = boost::make_shared(); From 3bd97075e7d21d65e210f00640127e88cf37e9c2 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Thu, 12 Dec 2013 09:37:52 -0500 Subject: [PATCH 168/403] Refs #8208 option to use lattice constants --- .../Crystal/src/SCDCalibratePanels.cpp | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp index fe0f9fb1c42a..6f06dddb9415 100644 --- a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp +++ b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp @@ -99,6 +99,7 @@ To do so select the workspace, which you have calibrated as the InputWorkspace a #include "MantidAPI/IFunction.h" #include "MantidGeometry/Instrument/RectangularDetector.h" #include "MantidGeometry/Crystal/IndexingUtils.h" +#include "MantidGeometry/Crystal/OrientedLattice.h" using namespace Mantid::DataObjects; using namespace Mantid::API; @@ -669,7 +670,17 @@ namespace Mantid double alpha = getProperty("alpha"); double beta = getProperty("beta"); double gamma = getProperty("gamma"); - + if ((a == EMPTY_DBL() || b == EMPTY_DBL() || c == EMPTY_DBL() || alpha == EMPTY_DBL() || + beta == EMPTY_DBL() || gamma == EMPTY_DBL()) && peaksWs->sample().hasOrientedLattice()) + { + OrientedLattice latt = peaksWs->mutableSample().getOrientedLattice(); + a = latt.a(); + b = latt.b(); + c = latt.c(); + alpha = latt.alpha(); + beta = latt.beta(); + gamma = latt.gamma(); + } double tolerance = getProperty("tolerance"); if( !GoodStart( peaksWs, a,b,c,alpha,beta,gamma,tolerance)) @@ -1371,12 +1382,12 @@ namespace Mantid auto mustBePositive = boost::make_shared >(); mustBePositive->setLower(0.0); - declareProperty("a", 0.0, mustBePositive, "Lattice Parameter a"); - declareProperty("b", 0.0, mustBePositive, "Lattice Parameter b"); - declareProperty("c", 0.0, mustBePositive, "Lattice Parameter c"); - declareProperty("alpha", 0.0, mustBePositive, "Lattice Parameter alpha in degrees"); - declareProperty("beta", 0.0, mustBePositive, "Lattice Parameter beta in degrees"); - declareProperty("gamma", 0.0, mustBePositive, "Lattice Parameter gamma in degrees"); + declareProperty("a", EMPTY_DBL(), mustBePositive, "Lattice Parameter a (Leave empty to use lattice constants in peaks workspace)"); + declareProperty("b", EMPTY_DBL(), mustBePositive, "Lattice Parameter b (Leave empty to use lattice constants in peaks workspace)"); + declareProperty("c", EMPTY_DBL(), mustBePositive, "Lattice Parameter c (Leave empty to use lattice constants in peaks workspace)"); + declareProperty("alpha", EMPTY_DBL(), mustBePositive, "Lattice Parameter alpha in degrees (Leave empty to use lattice constants in peaks workspace)"); + declareProperty("beta", EMPTY_DBL(), mustBePositive, "Lattice Parameter beta in degrees (Leave empty to use lattice constants in peaks workspace)"); + declareProperty("gamma", EMPTY_DBL(), mustBePositive, "Lattice Parameter gamma in degrees (Leave empty to use lattice constants in peaks workspace)"); declareProperty("useL0", true, "Fit the L0(source to sample) distance"); declareProperty("usetimeOffset", true, "Fit the time offset value"); From 222b9e17950ff16dd0b7db2791bd7e9e11db4ce9 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Thu, 12 Dec 2013 10:19:51 -0500 Subject: [PATCH 169/403] Re #8410. Made modifications as suggested by Russell. --- .../DataHandling/src/LoadEventNexus.cpp | 2 +- .../Framework/Kernel/inc/MantidKernel/Task.h | 2 +- .../Framework/Kernel/test/ThreadPoolTest.h | 3 +- .../Kernel/test/ThreadSchedulerMutexesTest.h | 35 +++++-------------- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp index 4de40493faca..1d78ba0b4b6d 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp @@ -1606,7 +1606,7 @@ void LoadEventNexus::loadEvents(API::Progress * const prog, const bool monitors) // Make the thread pool ThreadScheduler * scheduler = new ThreadSchedulerMutexes(); ThreadPool pool(scheduler); - boost::shared_ptr diskIOMutex(new Mutex()); + auto diskIOMutex = boost::make_shared(); size_t bank0 = 0; size_t bankn = bankNames.size(); diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h index 2446ff10feb4..005019d23a97 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Task.h @@ -74,7 +74,7 @@ namespace Kernel /** Get the mutex object for this Task * @return Mutex pointer, or NULL */ - boost::shared_ptr getMutex() + boost::shared_ptr getMutex() { return m_mutex; } diff --git a/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h b/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h index 8406c3edc696..cac3e1e365f9 100644 --- a/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h +++ b/Code/Mantid/Framework/Kernel/test/ThreadPoolTest.h @@ -12,6 +12,7 @@ #include "MantidKernel/ThreadSchedulerMutexes.h" #include +#include #include #include #include @@ -388,7 +389,7 @@ class ThreadPoolTest : public CxxTest::TestSuite Task * task = new FunctionTask( boost::bind(&TimeWaster::add_to_number, &mywaster, i), static_cast(i) ); // Create a new mutex every 1000 tasks. This is more relevant to the ThreadSchedulerMutexes; others ignore it. if (i % 1000 == 0) - lastMutex = boost::shared_ptr(new Mutex()); + lastMutex = boost::make_shared(); task->setMutex(lastMutex); p.schedule( task ); } diff --git a/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h b/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h index 785aec542a0f..ade9d21c9f25 100644 --- a/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h +++ b/Code/Mantid/Framework/Kernel/test/ThreadSchedulerMutexesTest.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -44,8 +45,8 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite void test_push() { ThreadSchedulerMutexes sc; - boost::shared_ptr mut1(new Mutex()); - boost::shared_ptr mut2(new Mutex()); + auto mut1 = boost::make_shared(); + auto mut2 = boost::make_shared(); TaskWithMutex * task1 = new TaskWithMutex(mut1, 10.0); TaskWithMutex * task2 = new TaskWithMutex(mut2, 9.0); @@ -53,19 +54,14 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( sc.size(), 1); sc.push( task2 ); TS_ASSERT_EQUALS( sc.size(), 2); - -// delete task1; -// delete task2; -// delete mut1; -// delete mut2; } void test_queue() { ThreadSchedulerMutexes sc; - boost::shared_ptr mut1(new Mutex()); - boost::shared_ptr mut2(new Mutex()); - boost::shared_ptr mut3(new Mutex()); + auto mut1 = boost::make_shared(); + auto mut2 = boost::make_shared(); + auto mut3 = boost::make_shared(); TaskWithMutex * task1 = new TaskWithMutex(mut1, 10.0); TaskWithMutex * task2 = new TaskWithMutex(mut1, 9.0); TaskWithMutex * task3 = new TaskWithMutex(mut1, 8.0); @@ -122,17 +118,6 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( task, task5 ); TS_ASSERT_EQUALS( sc.size(), 0 ); // (for this task, the thread pool would have to wait till the mutex is released) - -// delete task1; -// delete task2; -// delete task3; -// delete task4; -// delete task5; -// delete task6; -// delete task7; -// delete mut1; -// delete mut2; -// delete mut3; } void test_clear() @@ -140,7 +125,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite ThreadSchedulerMutexes sc; for (size_t i=0; i<10; i++) { - TaskWithMutex * task = new TaskWithMutex(boost::shared_ptr(new Mutex()), 10.0); + TaskWithMutex * task = new TaskWithMutex(boost::make_shared(), 10.0); sc.push(task); } TS_ASSERT_EQUALS(sc.size(), 10); @@ -155,7 +140,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite { ThreadSchedulerMutexes sc; Timer tim0; - boost::shared_ptr mut1(new Mutex()); + auto mut1 = boost::make_shared(); size_t num = 500; for (size_t i=0; i < num; i++) { @@ -171,8 +156,6 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite } //std::cout << tim1.elapsed() << " secs to pop." << std::endl; TS_ASSERT_EQUALS( sc.size(), 0); - -// delete mut1; } void test_performance_lotsOfMutexes() @@ -182,7 +165,7 @@ class ThreadSchedulerMutexesTest : public CxxTest::TestSuite size_t num = 500; for (size_t i=0; i < num; i++) { - sc.push(new TaskWithMutex(boost::shared_ptr(new Mutex()), 10.0)); + sc.push(new TaskWithMutex(boost::make_shared(), 10.0)); } //std::cout << tim0.elapsed() << " secs to push." << std::endl; TS_ASSERT_EQUALS( sc.size(), num); From 9974373e79bf32743e9417dda33639d14868a65c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Thu, 12 Dec 2013 15:48:42 +0000 Subject: [PATCH 170/403] Refs #8597. Fix problem with multi-period dead times. --- .../Framework/WorkflowAlgorithms/src/MuonLoad.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp index 884768e8b600..4205786760c6 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/MuonLoad.cpp @@ -146,6 +146,7 @@ namespace WorkflowAlgorithms throw std::runtime_error("Loaded workspace is of invalid type"); } + // Deal with dead time correction (if required bool applyDtc = getProperty("ApplyDeadTimeCorrection"); if ( applyDtc ) @@ -155,7 +156,16 @@ namespace WorkflowAlgorithms if ( ! deadTimes ) { // If no dead times specified - try to use ones from the file - deadTimes = load->getProperty("DeadTimeTable"); + Workspace_sptr loadedDeadTimes = load->getProperty("DeadTimeTable"); + + if ( auto table = boost::dynamic_pointer_cast(loadedDeadTimes) ) + { + deadTimes = table; + } + else if ( auto group = boost::dynamic_pointer_cast(loadedDeadTimes) ) + { + deadTimes = boost::dynamic_pointer_cast( group->getItem(0) ); + } if ( ! deadTimes ) throw std::runtime_error("File doesn't contain any dead times"); From bfe30694d645b6545f08874aae27d924290587c8 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Thu, 12 Dec 2013 15:59:03 +0000 Subject: [PATCH 171/403] Add code from ConvertFullprofToXML re #8398 Untested do not git checkbuild Signed-off-by: Karl Palmen --- .../LoadFullprofResolution.h | 21 +++ .../src/LoadFullprofResolution.cpp | 173 +++++++++++++++++- 2 files changed, 188 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h index c384df58f284..2163d7c474e7 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h @@ -88,6 +88,27 @@ namespace DataHandling /// Put parameters into a metrix workspace void putParametersIntoWorkspace( const API::ITableWorkspace_sptr &tws, API::MatrixWorkspace_sptr ws); + /// Add an ALFBE parameter + void addALFBEParameter(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent, const std::string& paramName); + + /// Add set of Sigma parameters + void addSigmaParameters(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent ); + + /// Add set of Gamma parameters + void addGammaParameters(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent ); + + /// Get value for XML eq attribute for parameter + std::string getXMLEqValue( const API::Column_const_sptr, const std::string& name ); + + // Translate a parameter name from as it appears in the table workspace to its name in the XML file + std::string getXMLParameterName( const std::string& name ); + + /// Get row numbers of the parameters in the table workspace + void getTableRowNumbers(const API::ITableWorkspace_sptr & tablews, std::map& parammap); + + /// Place to store the row numbers + std::map m_rowNumbers; + }; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index 8d44b341a562..e1a30df8b927 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -12,6 +12,10 @@ Load Fullprof resolution (.irf) file to TableWorkspace(s) and optionally into th #include "MantidAPI/InstrumentDataService.h" #include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" +#include +#include +#include + #include #include #include @@ -25,6 +29,7 @@ using namespace Mantid::API; using namespace Mantid::DataObjects; using namespace Mantid::Kernel; using namespace std; +using namespace Poco::XML; using Geometry::Instrument; using Geometry::Instrument_sptr; @@ -751,19 +756,175 @@ namespace DataHandling } void LoadFullprofResolution::putParametersIntoWorkspace( const API::ITableWorkspace_sptr &tws, API::MatrixWorkspace_sptr ws) + { + + // Get instrument name from matrix workspace + std::string instrumentName = ws->getInstrument()->getName(); + + // Convert table workspace into DOM XML document + // Set up writer to Paremeter file + DOMWriter writer; + writer.setNewLine("\n"); + writer.setOptions(XMLWriter::PRETTY_PRINT); + + // Get current time + Kernel::DateAndTime date = Kernel::DateAndTime::getCurrentTime(); + std::string ISOdate = date.toISO8601String(); + std::string ISOdateShort = ISOdate.substr(0,19); // Remove fraction of seconds + + // Create document + AutoPtr mDoc = new Document(); + AutoPtr rootElem = mDoc->createElement("parameter-file"); + rootElem->setAttribute("date", ISOdateShort); + mDoc->appendChild(rootElem); + + // Add instrument + AutoPtr instrumentElem = mDoc->createElement("component-link"); + instrumentElem->setAttribute("name",instrumentName); + rootElem->appendChild(instrumentElem); + API::Column_const_sptr column1 = tws->getColumn( 1 ); + addALFBEParameter( column1, mDoc, instrumentElem, "Alph0"); + addALFBEParameter( column1, mDoc, instrumentElem, "Beta0"); + addALFBEParameter( column1, mDoc, instrumentElem, "Alph1"); + addALFBEParameter( column1, mDoc, instrumentElem, "Beta1"); + + // Add banks + if(tws->columnCount() < 2){ + throw std::runtime_error("No banks found"); + } + size_t num_banks = tws->columnCount()-1; + + for( size_t i=0; igetColumn( i+1 ); + const double bankNumber = column->cell(0); + std::ostringstream bankName; + bankName << "bank" << bankNumber; + AutoPtr bankElem = mDoc->createElement("component-link"); + bankElem->setAttribute("name",bankName.str()); + addSigmaParameters( column, mDoc, bankElem ); + addGammaParameters( column, mDoc, bankElem ); + rootElem->appendChild(bankElem); + } + + // Convert DOM XML document into string + // ? std::ofstream outFile(); + // ? writer.writeNode(outFile, mDoc); // How do I do this? + + + // Load the string into the workspace + + } + + /* Add an ALFBE parameter to the XML document according to the table workspace + * + * paramName is the name of the parameter as it appears in the table workspace + */ + void LoadFullprofResolution::addALFBEParameter(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Element* parent, const std::string& paramName) { - Instrument_const_sptr instrument = ws->getInstrument(); - //Instrument_const_sptr baseInstrument = ws->getInstrument()->baseInstrument(); + AutoPtr parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", getXMLParameterName(paramName)); + parameterElem->setAttribute("type","fitting"); - //InstrumentDefinitionParser loadInstr; - //loadInstr.setComponentLinks(instrument, pRootElem); + AutoPtr formulaElem = mDoc->createElement("formula"); + formulaElem->setAttribute("eq",getXMLEqValue(column, paramName)); + if(paramName != "Beta1") formulaElem->setAttribute("result-unit","TOF"); + parameterElem->appendChild(formulaElem); - auto & pmap = ws->instrumentParameters(); + AutoPtr fixedElem = mDoc->createElement("fixed"); + parameterElem->appendChild(fixedElem); - //pmap.addString(instrument->getComponentID(), blah); // What do I do here? + parent->appendChild(parameterElem); + } + /* Add a set of SIGMA paraters to the XML document according to the table workspace + * for the bank at the given column of the table workspace + */ + void LoadFullprofResolution::addSigmaParameters(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Poco::XML::Element* parent ) + { + AutoPtr parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", "IkedaCarpenterPV:SigmaSquared"); + parameterElem->setAttribute("type","fitting"); + + AutoPtr formulaElem = mDoc->createElement("formula"); + std::string eqValue = getXMLEqValue(column, "Sig1")+"*centre^2+"+getXMLEqValue(column, "Sig0"); + formulaElem->setAttribute("eq", eqValue); + formulaElem->setAttribute("unit","dSpacing"); + formulaElem->setAttribute("result-unit","TOF^2"); + parameterElem->appendChild(formulaElem); + + parent->appendChild(parameterElem); + } + + /* Add a set of GAMMA paraters to the XML document according to the table workspace + * for the bank at the given column of the table workspace + */ + void LoadFullprofResolution::addGammaParameters(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Poco::XML::Element* parent ) + { + AutoPtr parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", "IkedaCarpenterPV:Gamma"); + parameterElem->setAttribute("type","fitting"); + + AutoPtr formulaElem = mDoc->createElement("formula"); + std::string eqValue = getXMLEqValue(column, "Gam1" )+"*centre"; + formulaElem->setAttribute("eq", eqValue); + formulaElem->setAttribute("unit","dSpacing"); + formulaElem->setAttribute("result-unit","TOF"); + parameterElem->appendChild(formulaElem); + + parent->appendChild(parameterElem); } + + + /* + * Get the XML name of a parameter given its Table Workspace name + */ + std::string LoadFullprofResolution::getXMLParameterName( const std::string& name ) + { + // Only used for ALFBE parameters + std::string prefix = "IkedaCarpenterPV:"; + if(name == "Alph0") return prefix+"Alpha0"; + if(name == "Beta0") return prefix+"Beta0"; + if(name == "Alph1") return prefix+"Alpha1"; + if(name == "Beta1") return prefix+"Kappa"; + return "?"+name; + } + + /* + * Get the value string to put in the XML eq attribute of the formula element of the paramenter element + * given the name of the parameter in the table workspace. + */ + std::string LoadFullprofResolution::getXMLEqValue( const API::Column_const_sptr column, const std::string& name ) + { + size_t paramNumber = m_rowNumbers[name]; + //API::Column_const_sptr column = tablews->getColumn( columnIndex ); + double eqValue = column->cell(paramNumber); + if(name.substr(0,3) == "Sig") eqValue = eqValue*eqValue; // Square the sigma values + return boost::lexical_cast(eqValue); + } + + /* This function fills in a list of the row numbers starting 0 of the parameters + in the table workspace, so one can find the position in a column of + the value of the given parameter. + */ + void LoadFullprofResolution::getTableRowNumbers(const API::ITableWorkspace_sptr & tablews, std::map& parammap) + { + parammap.clear(); + + size_t numrows = tablews->rowCount(); + for (size_t i = 0; i < numrows; ++i) + { + TableRow row = tablews->getRow(i); + std::string name; + row >> name; + parammap.insert(std::make_pair(name, i)); + } + + return; + } + + } // namespace DataHandling } // namespace Mantid From f7e78b053244635c930d04b00411f4395ca97595 Mon Sep 17 00:00:00 2001 From: Alex Buts Date: Thu, 12 Dec 2013 17:04:59 +0000 Subject: [PATCH 172/403] refs #8609 modified Mari to avoid diagnostics completely. --- Code/Mantid/instrument/MARI_Parameters.xml | 4 ++++ Code/Mantid/scripts/Inelastic/dgreduce.py | 14 ++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/instrument/MARI_Parameters.xml b/Code/Mantid/instrument/MARI_Parameters.xml index b75425f2d0c2..203ffd48d212 100644 --- a/Code/Mantid/instrument/MARI_Parameters.xml +++ b/Code/Mantid/instrument/MARI_Parameters.xml @@ -29,6 +29,10 @@ + + + + diff --git a/Code/Mantid/scripts/Inelastic/dgreduce.py b/Code/Mantid/scripts/Inelastic/dgreduce.py index 05b8302fb01c..752b6cd4bee0 100644 --- a/Code/Mantid/scripts/Inelastic/dgreduce.py +++ b/Code/Mantid/scripts/Inelastic/dgreduce.py @@ -257,8 +257,11 @@ def arb_units(wb_run,sample_run,ei_guess,rebin,map_file='default',monovan_run=No if Reducer.mask_run == None : mask_run=sample_run - + masking = None; masks_done=False + if not Reducer.run_diagnostics: + header="Diagnostics skipped " + masks_done = True; if Reducer.save_and_reuse_masks : raise NotImplementedError("Save and reuse masks option is not yet implemented") mask_file_name = common.create_resultname(str(mask_run),Reducer.instr_name,'_masks.xml') @@ -268,7 +271,7 @@ def arb_units(wb_run,sample_run,ei_guess,rebin,map_file='default',monovan_run=No #Reducer.hard_mask_file = mask_full_file; #Reducer.use_hard_mask_only = True masks_done=True - header="Masking loaded " + header="Masking fully skipped and processed {0} spectra and {1} bad spectra " else: pass #------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -278,7 +281,7 @@ def arb_units(wb_run,sample_run,ei_guess,rebin,map_file='default',monovan_run=No if not masks_done: masking = Reducer.diagnose(wb_run,sample = mask_run, second_white = None,print_results=True) - header = "Diag Processed " + header = "Diag Processed workspace with {0:d} spectra and masked {1:d} bad spectra" # Calculate absolute units: @@ -308,7 +311,7 @@ def arb_units(wb_run,sample_run,ei_guess,rebin,map_file='default',monovan_run=No failed_sp_list,nSpectra = get_failed_spectra_list_from_masks(masking) nMaskedSpectra = len(failed_sp_list) # this tells turkey in case of hard mask only but everythin else semems work fine - print '{0} workspace with {1:d} spectra and masked {2:d} bad spectra'.format(header,nSpectra,nMaskedSpectra) + print header.format(nSpectra,nMaskedSpectra) #Run the conversion first on the sample deltaE_wkspace_sample = Reducer.convert_to_energy(sample_run, ei_guess, wb_run) @@ -701,6 +704,9 @@ def get_failed_spectra_list_from_masks(masking_wksp): masking_wksp = mtd[masking_wksp] failed_spectra = [] + if masking_wksp is None: + return (failed_spectra,0); + n_spectra = masking_wksp.getNumberHistograms() for i in xrange(n_spectra): if masking_wksp.readY(i)[0] >0.99 : # spectrum is masked From 3a0cfe2322ab692532d6822e03c36e2d2fd31adb Mon Sep 17 00:00:00 2001 From: Alex Buts Date: Thu, 12 Dec 2013 17:24:20 +0000 Subject: [PATCH 173/403] refs #8609 Allow to drop diagnostics for all ISIS inelastic instrum. --- Code/Mantid/instrument/LET_Parameters.xml | 5 +++++ Code/Mantid/instrument/MAPS_Parameters.xml | 5 +++++ Code/Mantid/instrument/MARI_Parameters.xml | 2 +- Code/Mantid/instrument/MERLIN_Parameters.xml | 5 +++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/instrument/LET_Parameters.xml b/Code/Mantid/instrument/LET_Parameters.xml index 805c0dfdc219..02f28044bd03 100644 --- a/Code/Mantid/instrument/LET_Parameters.xml +++ b/Code/Mantid/instrument/LET_Parameters.xml @@ -28,6 +28,11 @@ + + + + + diff --git a/Code/Mantid/instrument/MAPS_Parameters.xml b/Code/Mantid/instrument/MAPS_Parameters.xml index e651324cc82a..332e71d7c7b3 100644 --- a/Code/Mantid/instrument/MAPS_Parameters.xml +++ b/Code/Mantid/instrument/MAPS_Parameters.xml @@ -28,6 +28,11 @@ + + + + + diff --git a/Code/Mantid/instrument/MARI_Parameters.xml b/Code/Mantid/instrument/MARI_Parameters.xml index 203ffd48d212..042911c94b22 100644 --- a/Code/Mantid/instrument/MARI_Parameters.xml +++ b/Code/Mantid/instrument/MARI_Parameters.xml @@ -29,7 +29,7 @@ - + diff --git a/Code/Mantid/instrument/MERLIN_Parameters.xml b/Code/Mantid/instrument/MERLIN_Parameters.xml index ddced9473df2..c98eca1fd56e 100644 --- a/Code/Mantid/instrument/MERLIN_Parameters.xml +++ b/Code/Mantid/instrument/MERLIN_Parameters.xml @@ -28,6 +28,11 @@ + + + + + From 215d896e081fa7af54db38584ddaeaacc82f892d Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Thu, 12 Dec 2013 13:07:25 -0500 Subject: [PATCH 174/403] Refs #8600 two new input parameters for SaveHKL --- .../Crystal/inc/MantidCrystal/SaveHKL.h | 4 +- Code/Mantid/Framework/Crystal/src/SaveHKL.cpp | 38 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveHKL.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveHKL.h index 1e53922dd093..bf68c723f5a7 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveHKL.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SaveHKL.h @@ -3,6 +3,7 @@ #include "MantidKernel/System.h" #include "MantidAPI/Algorithm.h" +#include "MantidDataObjects/PeaksWorkspace.h" namespace Mantid { @@ -59,7 +60,8 @@ namespace Crystal double radius; // in cm double power_th; double spectrumCalc(double TOF, int iSpec,std::vector > time, std::vector > spectra, size_t id); - + DataObjects::PeaksWorkspace_sptr ws; + void sizeBanks(std::string bankName, int& nCols, int& nRows); }; diff --git a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp index 1c0eadb3391e..6b3369cd07ce 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp @@ -127,6 +127,9 @@ namespace Crystal histoTypes.push_back(""); declareProperty("SortBy", histoTypes[2],boost::make_shared(histoTypes), "Sort the histograms by bank, run number or both (default)."); + declareProperty("MinIsigI", EMPTY_DBL(), mustBePositive, + "The minimum I/sig(I) ratio"); + declareProperty("WidthBorder", EMPTY_INT(), "Width of border of detectors"); } //---------------------------------------------------------------------------------------------- @@ -136,13 +139,14 @@ namespace Crystal { std::string filename = getPropertyValue("Filename"); - PeaksWorkspace_sptr ws = getProperty("InputWorkspace"); - + ws = getProperty("InputWorkspace"); double scaleFactor = getProperty("ScalePeaks"); double dMin = getProperty("MinDSpacing"); double wlMin = getProperty("MinWavelength"); double wlMax = getProperty("MaxWavelength"); std::string type = getProperty("SortBy"); + double minIsigI = getProperty("MinIsigI"); + int widthBorder = getProperty("WidthBorder"); // Sequence and run number int seqNum = 1; @@ -294,9 +298,14 @@ namespace Crystal Peak & p = peaks[wi]; if (p.getIntensity() == 0.0 || boost::math::isnan(p.getIntensity()) || boost::math::isnan(p.getSigmaIntensity())) continue; + if (minIsigI != EMPTY_DBL() && p.getIntensity() < std::abs(minIsigI * p.getSigmaIntensity())) continue; int run = p.getRunNumber(); int bank = 0; std::string bankName = p.getBankName(); + int nCols, nRows; + sizeBanks(bankName, nCols, nRows); + if (widthBorder != EMPTY_INT() && (p.getCol() < widthBorder || p.getRow() < widthBorder || p.getCol() > (nCols - widthBorder) || + p.getRow() > (nRows -widthBorder))) continue; // Take out the "bank" part of the bank name and convert to an int bankName.erase(remove_if(bankName.begin(), bankName.end(), not1(std::ptr_fun (::isdigit))), bankName.end()); Strings::convert(bankName, bank); @@ -516,7 +525,30 @@ namespace Crystal return spect; } - + void SaveHKL::sizeBanks(std::string bankName, int& nCols, int& nRows) + { + if (bankName.compare("None") == 0) return; + boost::shared_ptr parent = ws->getInstrument()->getComponentByName(bankName); + if (parent->type().compare("RectangularDetector") == 0) + { + boost::shared_ptr RDet = boost::dynamic_pointer_cast< + const RectangularDetector>(parent); + + nCols = RDet->xpixels(); + nRows = RDet->ypixels(); + } + else + { + std::vector children; + boost::shared_ptr asmb = boost::dynamic_pointer_cast(parent); + asmb->getChildren(children, false); + boost::shared_ptr asmb2 = boost::dynamic_pointer_cast(children[0]); + std::vector grandchildren; + asmb2->getChildren(grandchildren,false); + nRows = static_cast(grandchildren.size()); + nCols = static_cast(children.size()); + } + } } // namespace Mantid } // namespace Crystal From 94f8ba826ddfddd2f817dac0e48cf43c1aaa4586 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Thu, 12 Dec 2013 14:56:16 -0500 Subject: [PATCH 175/403] Refs #8502 first four refactor tasks --- .../MantidGeometry/Crystal/IndexingUtils.h | 16 --- .../MantidGeometry/Crystal/OrientedLattice.h | 11 ++ .../Geometry/src/Crystal/ConventionalCell.cpp | 23 +-- .../Geometry/src/Crystal/IndexingUtils.cpp | 135 +++--------------- .../Geometry/src/Crystal/OrientedLattice.cpp | 80 +++++++++++ .../Geometry/src/Crystal/ScalarUtils.cpp | 7 +- .../Geometry/test/IndexingUtilsTest.h | 10 +- .../Framework/Kernel/inc/MantidKernel/V3D.h | 4 + Code/Mantid/Framework/Kernel/src/V3D.cpp | 13 ++ 9 files changed, 149 insertions(+), 150 deletions(-) diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h index 36f8b20cec97..80a9add7d9ee 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h @@ -51,10 +51,6 @@ namespace Geometry class MANTID_GEOMETRY_DLL IndexingUtils { public: - - /// Convenience method for sorting list of V3D objects based on magnitude - static bool CompareMagnitude( const Kernel::V3D & v1, - const Kernel::V3D & v2 ); /// Find the UB matrix that most nearly indexes the specified qxyz values /// given the lattice parameters @@ -270,18 +266,6 @@ class MANTID_GEOMETRY_DLL IndexingUtils double plane_spacing, double required_tolerance ); - /// Get the UB matix corresponding to the real space edge vectors a, b, c - static bool GetUB( Kernel::DblMatrix & UB, - const Kernel::V3D & a_dir, - const Kernel::V3D & b_dir, - const Kernel::V3D & c_dir ); - - /// Get the real space edge vectors a, b, c corresponding to the UB matrix - static bool GetABC( const Kernel::DblMatrix & UB, - Kernel::V3D & a_dir, - Kernel::V3D & b_dir, - Kernel::V3D & c_dir ); - /// Get the lattice parameters for the specified orientation matrix static bool GetLatticeParameters( const Kernel::DblMatrix & UB, std::vector & lattice_par ); diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h index 01de89ea4e44..837a9fa453d4 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h @@ -73,6 +73,17 @@ namespace Geometry void saveNexus(::NeXus::File * file, const std::string & group) const; /// Load the lattice to from an open NeXus file void loadNexus(::NeXus::File * file, const std::string & group); + /// Get the UB matix corresponding to the real space edge vectors a, b, c + static bool GetUB( Kernel::DblMatrix & UB, + const Kernel::V3D & a_dir, + const Kernel::V3D & b_dir, + const Kernel::V3D & c_dir ); + + /// Get the real space edge vectors a, b, c corresponding to the UB matrix + static bool GetABC( const Kernel::DblMatrix & UB, + Kernel::V3D & a_dir, + Kernel::V3D & b_dir, + Kernel::V3D & c_dir ); private: Kernel::DblMatrix U; diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/ConventionalCell.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/ConventionalCell.cpp index 12c51dd374fa..ebea990bf8a1 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/ConventionalCell.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/ConventionalCell.cpp @@ -7,6 +7,7 @@ #include "MantidKernel/V3D.h" #include "MantidGeometry/Crystal/ConventionalCell.h" #include "MantidGeometry/Crystal/IndexingUtils.h" +#include "MantidGeometry/Crystal/OrientedLattice.h" namespace Mantid @@ -217,13 +218,13 @@ namespace Geometry V3D a_dir; V3D b_dir; V3D c_dir; - IndexingUtils::GetABC( UB, a_dir, b_dir, c_dir ); + OrientedLattice::GetABC( UB, a_dir, b_dir, c_dir ); std::vector edges; edges.push_back( a_dir ); edges.push_back( b_dir ); edges.push_back( c_dir ); - std::sort( edges.begin(), edges.end(), IndexingUtils::CompareMagnitude ); + std::sort( edges.begin(), edges.end(), V3D::CompareMagnitude ); V3D a = edges[0]; V3D b = edges[1]; @@ -234,7 +235,7 @@ namespace Geometry { c = c * (-1); } - IndexingUtils::GetUB( UB, a, b, c ); + OrientedLattice::GetUB( UB, a, b, c ); } @@ -253,7 +254,7 @@ namespace Geometry V3D a; V3D b; V3D c; - IndexingUtils::GetABC( UB, a, b, c ); + OrientedLattice::GetABC( UB, a, b, c ); double a_b_diff = fabs( a.norm() - b.norm() ) / std::min( a.norm(), b.norm() ); @@ -268,11 +269,11 @@ namespace Geometry // equal sides first. if ( a_c_diff <= a_b_diff && a_c_diff <= b_c_diff ) { - IndexingUtils::GetUB( UB, c, a, b ); + OrientedLattice::GetUB( UB, c, a, b ); } else if ( b_c_diff <= a_b_diff && b_c_diff <= a_c_diff ) { - IndexingUtils::GetUB( UB, b, c, a ); + OrientedLattice::GetUB( UB, b, c, a ); } } @@ -292,7 +293,7 @@ namespace Geometry V3D a; V3D b; V3D c; - IndexingUtils::GetABC( UB, a, b, c ); + OrientedLattice::GetABC( UB, a, b, c ); double alpha = b.angle( c ) * 180.0/M_PI; double beta = c.angle( a ) * 180.0/M_PI; @@ -300,22 +301,22 @@ namespace Geometry // degree angle last if ( fabs(alpha-90) > 20 ) { - IndexingUtils::GetUB( UB, b, c, a ); + OrientedLattice::GetUB( UB, b, c, a ); } else if ( fabs(beta-90) > 20 ) { - IndexingUtils::GetUB( UB, c, a, b ); + OrientedLattice::GetUB( UB, c, a, b ); } // if the non 90 degree angle // is about 60 degrees, make // it about 120 degrees. - IndexingUtils::GetABC( UB, a, b, c ); + OrientedLattice::GetABC( UB, a, b, c ); double gamma = a.angle( b ) * 180.0/M_PI; if ( fabs( gamma - 60 ) < 10 ) { a = a * ( -1 ); // reflect a and c to change c = c * ( -1 ); // alpha and gamma to their - IndexingUtils::GetUB( UB, a, b, c ); // supplementary angle + OrientedLattice::GetUB( UB, a, b, c ); // supplementary angle } } diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp index 16f6fcb52184..e912cff68942 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp @@ -42,8 +42,8 @@ static bool CompareABCsum( const DblMatrix & UB_1, const DblMatrix & UB_2 ) V3D a2; V3D b2; V3D c2; - IndexingUtils::GetABC( UB_1, a1, b1, c1 ); - IndexingUtils::GetABC( UB_2, a2, b2, c2 ); + OrientedLattice::GetABC( UB_1, a1, b1, c1 ); + OrientedLattice::GetABC( UB_2, a2, b2, c2 ); double sum_1 = a1.norm() + b1.norm() + c1.norm(); double sum_2 = a2.norm() + b2.norm() + c2.norm(); @@ -65,7 +65,7 @@ static double GetDiffFrom90Sum( const DblMatrix & UB ) V3D b; V3D c; - if ( !IndexingUtils::GetABC( UB, a, b, c ) ) + if ( !OrientedLattice::GetABC( UB, a, b, c ) ) return -1; double alpha = b.angle( c ) * RAD_TO_DEG; @@ -93,19 +93,6 @@ static bool CompareDiffFrom90( const DblMatrix & UB_1, const DblMatrix & UB_2 ) } -/** - Comparator function for sorting list of 3D vectors based on their magnitude. - @param v1 first vector - @param v2 seconde vector - @return true if v1.norm() < v2.norm(). - */ -bool IndexingUtils::CompareMagnitude( const V3D & v1, const V3D & v2 ) -{ - double mag_sq_1 = v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]; - double mag_sq_2 = v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]; - return (mag_sq_1 < mag_sq_2); -} - /** STATIC method Find_UB: Calculates the matrix that most nearly indexes @@ -213,7 +200,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, // specified by the base_peak parameter if ( base_index < 0 || base_index >= (int)q_vectors.size() ) { - std::sort( shifted_qs.begin(), shifted_qs.end(), CompareMagnitude ); + std::sort( shifted_qs.begin(), shifted_qs.end(), V3D::CompareMagnitude ); } else { @@ -237,7 +224,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, sorted_qs.push_back( q_vectors[i] ); } - std::sort( sorted_qs.begin(), sorted_qs.end(), CompareMagnitude ); + std::sort( sorted_qs.begin(), sorted_qs.end(), V3D::CompareMagnitude ); if ( num_initial > sorted_qs.size() ) num_initial = sorted_qs.size(); @@ -428,7 +415,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, // specified by the base_peak parameter if ( base_index < 0 || base_index >= (int)q_vectors.size() ) { - std::sort( shifted_qs.begin(), shifted_qs.end(), CompareMagnitude ); + std::sort( shifted_qs.begin(), shifted_qs.end(), V3D::CompareMagnitude ); } else { @@ -452,7 +439,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, sorted_qs.push_back( q_vectors[i] ); } - std::sort( sorted_qs.begin(), sorted_qs.end(), CompareMagnitude ); + std::sort( sorted_qs.begin(), sorted_qs.end(), V3D::CompareMagnitude ); if ( num_initial > sorted_qs.size() ) num_initial = sorted_qs.size(); @@ -475,7 +462,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, "Find_UB(): Could not find at least three possible lattice directions"); } - std::sort( directions.begin(), directions.end(), CompareMagnitude ); + std::sort( directions.begin(), directions.end(), V3D::CompareMagnitude ); if ( ! FormUB_From_abc_Vectors(UB, directions, 0, min_d, max_d ) ) { @@ -639,7 +626,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, throw std::invalid_argument("Find_UB(): Could not find enough a,b,c vectors"); } - std::sort( directions.begin(), directions.end(), CompareMagnitude ); + std::sort( directions.begin(), directions.end(), V3D::CompareMagnitude ); double min_vol = min_d * min_d * min_d / 4.0; @@ -1216,7 +1203,7 @@ double IndexingUtils::ScanFor_UB( DblMatrix & UB, } } - if ( !GetUB( UB, a_dir, b_dir, c_dir ) ) + if ( !OrientedLattice::GetUB( UB, a_dir, b_dir, c_dir ) ) { throw std::runtime_error( "UB could not be formed, invert matrix failed"); } @@ -1585,7 +1572,7 @@ size_t IndexingUtils::FFTScanFor_Directions( std::vector & directions, temp_dirs.push_back( current_dir ); } - std::sort( temp_dirs.begin(), temp_dirs.end(), CompareMagnitude ); + std::sort( temp_dirs.begin(), temp_dirs.end(), V3D::CompareMagnitude ); // discard duplicates: double len_tol = 0.1; // 10% tolerance for lengths @@ -1837,7 +1824,7 @@ bool IndexingUtils::FormUB_From_abc_Vectors( DblMatrix & UB, return false; } // now build the UB matrix from a,b,c - if ( !GetUB( UB, a_dir, b_dir, c_dir ) ) + if ( !OrientedLattice::GetUB( UB, a_dir, b_dir, c_dir ) ) { throw std::runtime_error( "UB could not be formed, invert matrix failed"); } @@ -1934,7 +1921,7 @@ bool IndexingUtils::FormUB_From_abc_Vectors( DblMatrix & UB, c_dir = c_dir * (-1.0); } // now build the UB matrix from a,b,c - if ( !GetUB( UB, a_dir, b_dir, c_dir ) ) + if ( !OrientedLattice::GetUB( UB, a_dir, b_dir, c_dir ) ) { throw std::runtime_error( "UB could not be formed, invert matrix failed"); } @@ -2278,9 +2265,7 @@ bool IndexingUtils::CheckUB( const DblMatrix & UB ) } } - double det = UB[0][0] * ( UB[1][1] * UB[2][2] - UB[1][2] * UB[2][1] ) - - UB[0][1] * ( UB[1][0] * UB[2][2] - UB[1][2] * UB[2][0] ) - + UB[0][2] * ( UB[1][0] * UB[2][1] - UB[1][1] * UB[2][0] ); + double det = UB.determinant(); double abs_det = fabs(det); if ( abs_det > 10 || abs_det < 1e-12 ) // UB not found correctly @@ -2962,86 +2947,6 @@ int IndexingUtils::SelectDirection( V3D & best_direction, } -/** - Get the UB matrix corresponding to the real space edge vectors a,b,c. - The inverse of the matrix with vectors a,b,c as rows will be stored in UB. - - @param UB A 3x3 matrix that will be set to the UB matrix. - @param a_dir The real space edge vector for side a of the unit cell - @param b_dir The real space edge vector for side b of the unit cell - @param c_dir The real space edge vector for side c of the unit cell - - @return true if UB was set to the new matrix and false if UB could not be - set since the matrix with a,b,c as rows could not be inverted. - */ -bool IndexingUtils::GetUB( DblMatrix & UB, - const V3D & a_dir, - const V3D & b_dir, - const V3D & c_dir ) -{ - if ( UB.numRows() != 3 || UB.numCols() != 3 ) - { - throw std::invalid_argument("Find_UB(): UB matrix NULL or not 3X3"); - } - - UB.setRow( 0, a_dir ); - UB.setRow( 1, b_dir ); - UB.setRow( 2, c_dir ); - try - { - UB.Invert(); - } - catch (...) - { - return false; - } - return true; -} - - -/** - Get the real space edge vectors a,b,c corresponding to the UB matrix. - The rows of the inverse of the matrix with will be stored in a_dir, - b_dir, c_dir. - - @param UB A 3x3 matrix containing a UB matrix. - @param a_dir Will be set to the real space edge vector for side a - of the unit cell - @param b_dir Will be set to the real space edge vector for side b - of the unit cell - @param c_dir Will be set to the real space edge vector for side c - of the unit cell - - @return true if the inverse of the matrix UB could be found and the - a_dir, b_dir and c_dir vectors have been set to the rows of - UB inverse. - */ -bool IndexingUtils::GetABC( const DblMatrix & UB, - V3D & a_dir, - V3D & b_dir, - V3D & c_dir ) -{ - if ( UB.numRows() != 3 || UB.numCols() != 3 ) - { - throw std::invalid_argument("GetABC(): UB matrix NULL or not 3X3"); - } - - DblMatrix UB_inverse( UB ); - try - { - UB_inverse.Invert(); - } - catch (...) - { - return false; - } - a_dir( UB_inverse[0][0], UB_inverse[0][1], UB_inverse[0][2] ); - b_dir( UB_inverse[1][0], UB_inverse[1][1], UB_inverse[1][2] ); - c_dir( UB_inverse[2][0], UB_inverse[2][1], UB_inverse[2][2] ); - - return true; -} - /** * Get the lattice parameters, a, b, c, alpha, beta, gamma and cell volume @@ -3061,7 +2966,7 @@ bool IndexingUtils::GetLatticeParameters( const DblMatrix & UB, V3D b_dir; V3D c_dir; - if ( ! GetABC( UB, a_dir, b_dir, c_dir ) ) + if ( ! OrientedLattice::GetABC( UB, a_dir, b_dir, c_dir ) ) { return false; } @@ -3171,7 +3076,7 @@ bool IndexingUtils::MakeNiggliUB( const DblMatrix & UB, V3D b; V3D c; - if ( !GetABC( UB, a, b, c ) ) + if ( !OrientedLattice::GetABC( UB, a, b, c ) ) { return false; } @@ -3204,7 +3109,7 @@ bool IndexingUtils::MakeNiggliUB( const DblMatrix & UB, } // next sort the list of linear combinations // in order of increasing length - std::sort( directions.begin(), directions.end(), CompareMagnitude ); + std::sort( directions.begin(), directions.end(), V3D::CompareMagnitude ); // next form a list of possible UB matrices // using sides from the list of linear @@ -3238,7 +3143,7 @@ bool IndexingUtils::MakeNiggliUB( const DblMatrix & UB, if ( vol > min_vol && HasNiggliAngles( a, b, c, 0.01 ) ) { Matrix new_tran(3,3,false); - GetUB( new_tran, a, b, c ); + OrientedLattice::GetUB( new_tran, a, b, c ); UB_list.push_back( new_tran ); } } @@ -3265,14 +3170,14 @@ bool IndexingUtils::MakeNiggliUB( const DblMatrix & UB, std::vector short_list; short_list.push_back( UB_list[0] ); - GetABC( short_list[0], a, b, c ); + OrientedLattice::GetABC( short_list[0], a, b, c ); total_length = a.norm() + b.norm() + c.norm(); bool got_short_list = false; size_t i = 1; while ( i < UB_list.size() && !got_short_list ) { - GetABC( UB_list[i], v1, v2, v3 ); + OrientedLattice::GetABC( UB_list[i], v1, v2, v3 ); double next_length = v1.norm() + v2.norm() + v3.norm(); if ( fabs(next_length - total_length)/total_length < length_tol ) short_list.push_back( UB_list[i] ); diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp index e1b5647249f0..40ead5d50fec 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp @@ -282,5 +282,85 @@ namespace Geometry file->closeGroup(); } + + /** + Get the UB matrix corresponding to the real space edge vectors a,b,c. + The inverse of the matrix with vectors a,b,c as rows will be stored in UB. + + @param UB A 3x3 matrix that will be set to the UB matrix. + @param a_dir The real space edge vector for side a of the unit cell + @param b_dir The real space edge vector for side b of the unit cell + @param c_dir The real space edge vector for side c of the unit cell + + @return true if UB was set to the new matrix and false if UB could not be + set since the matrix with a,b,c as rows could not be inverted. + */ + bool OrientedLattice::GetUB( DblMatrix & UB, + const V3D & a_dir, + const V3D & b_dir, + const V3D & c_dir ) + { + if ( UB.numRows() != 3 || UB.numCols() != 3 ) + { + throw std::invalid_argument("Find_UB(): UB matrix NULL or not 3X3"); + } + + UB.setRow( 0, a_dir ); + UB.setRow( 1, b_dir ); + UB.setRow( 2, c_dir ); + try + { + UB.Invert(); + } + catch (...) + { + return false; + } + return true; + } + + + /** + Get the real space edge vectors a,b,c corresponding to the UB matrix. + The rows of the inverse of the matrix with will be stored in a_dir, + b_dir, c_dir. + + @param UB A 3x3 matrix containing a UB matrix. + @param a_dir Will be set to the real space edge vector for side a + of the unit cell + @param b_dir Will be set to the real space edge vector for side b + of the unit cell + @param c_dir Will be set to the real space edge vector for side c + of the unit cell + + @return true if the inverse of the matrix UB could be found and the + a_dir, b_dir and c_dir vectors have been set to the rows of + UB inverse. + */ + bool OrientedLattice::GetABC( const DblMatrix & UB, + V3D & a_dir, + V3D & b_dir, + V3D & c_dir ) + { + if ( UB.numRows() != 3 || UB.numCols() != 3 ) + { + throw std::invalid_argument("GetABC(): UB matrix NULL or not 3X3"); + } + + DblMatrix UB_inverse( UB ); + try + { + UB_inverse.Invert(); + } + catch (...) + { + return false; + } + a_dir( UB_inverse[0][0], UB_inverse[0][1], UB_inverse[0][2] ); + b_dir( UB_inverse[1][0], UB_inverse[1][1], UB_inverse[1][2] ); + c_dir( UB_inverse[2][0], UB_inverse[2][1], UB_inverse[2][2] ); + + return true; + } }//Namespace Geometry }//Namespace Mantid diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/ScalarUtils.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/ScalarUtils.cpp index 0f414733c5ed..f52dcf92ccc1 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/ScalarUtils.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/ScalarUtils.cpp @@ -5,6 +5,7 @@ #include "MantidGeometry/Crystal/ScalarUtils.h" #include "MantidGeometry/Crystal/ReducedCell.h" #include "MantidGeometry/Crystal/IndexingUtils.h" +#include "MantidGeometry/Crystal/OrientedLattice.h" using namespace Mantid::Geometry; using Mantid::Kernel::V3D; @@ -211,7 +212,7 @@ std::vector ScalarUtils::GetCellsUBOnly( * reflections of a,b,c and forming the ConventionalCellInfo object * corresponding to the smallest form error. * - * @param UB Orientation transformation corresponding to a Niggli + * @param UB Crystal::Orientation transformation corresponding to a Niggli * reduced cell. * @param form_num The form number to use. * @@ -379,7 +380,7 @@ std::vector ScalarUtils::GetRelatedUBs( V3D a_temp, b_temp, c_temp, // vectors for generating handedness m_a_temp,m_b_temp,m_c_temp; // preserving permutations of sides - IndexingUtils::GetABC( UB, a_vec, b_vec, c_vec ); + OrientedLattice::GetABC( UB, a_vec, b_vec, c_vec ); m_a_vec = a_vec * (-1.0); m_b_vec = b_vec * (-1.0); @@ -435,7 +436,7 @@ std::vector ScalarUtils::GetRelatedUBs( b.norm() <= factor * c.norm() ) // could be Niggli within { // experimental error Matrix temp_UB(3,3,false); - IndexingUtils::GetUB( temp_UB, a, b, c ); + OrientedLattice::GetUB( temp_UB, a, b, c ); result.push_back( temp_UB ); } } diff --git a/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h b/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h index d89e20bd4188..7bdbe7484b9a 100644 --- a/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h +++ b/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h @@ -8,7 +8,7 @@ #include #include #include - +#include "MantidGeometry/Crystal/OrientedLattice.h" #include using namespace Mantid::Geometry; @@ -959,7 +959,7 @@ class IndexingUtilsTest : public CxxTest::TestSuite Matrix UB(3,3,false); - IndexingUtils::GetUB( UB, a_dir, b_dir, c_dir ); + OrientedLattice::GetUB( UB, a_dir, b_dir, c_dir ); for ( size_t row = 0; row < 3; row++ ) { @@ -980,7 +980,7 @@ class IndexingUtilsTest : public CxxTest::TestSuite V3D b; V3D c; - IndexingUtils::GetABC( UB, a, b, c ); + OrientedLattice::GetABC( UB, a, b, c ); a = a - a_dir; b = b - b_dir; @@ -1063,7 +1063,7 @@ class IndexingUtilsTest : public CxxTest::TestSuite V3D a(10,0,0); V3D b(-5,5,0); V3D c(0,5,5); - IndexingUtils::GetUB(UB, a,b,c); + OrientedLattice::GetUB(UB, a,b,c); Matrix newUB(3,3,false); @@ -1073,7 +1073,7 @@ class IndexingUtilsTest : public CxxTest::TestSuite V3D a_dir; V3D b_dir; V3D c_dir; - IndexingUtils::GetABC(newUB, a_dir,b_dir,c_dir); + OrientedLattice::GetABC(newUB, a_dir,b_dir,c_dir); double alpha = b_dir.angle( c_dir ) * 180.0/PI; double beta = c_dir.angle( a_dir ) * 180.0/PI; double gamma = a_dir.angle( b_dir ) * 180.0/PI; diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/V3D.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/V3D.h index 7b80c2419f26..75c2f53a9c76 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/V3D.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/V3D.h @@ -54,6 +54,10 @@ namespace Mantid V3D operator+(const V3D& v) const; V3D& operator+=(const V3D& v); + /// Convenience method for sorting list of V3D objects based on magnitude + static bool CompareMagnitude( const Kernel::V3D & v1, + const Kernel::V3D & v2 ); + // explicit conversion into vector operator std::vector()const{std::vector tmp(3); tmp[0]=x;tmp[1]=y; tmp[2]=z;return tmp;} diff --git a/Code/Mantid/Framework/Kernel/src/V3D.cpp b/Code/Mantid/Framework/Kernel/src/V3D.cpp index 3d042bcbc522..d86f9d42c2c6 100644 --- a/Code/Mantid/Framework/Kernel/src/V3D.cpp +++ b/Code/Mantid/Framework/Kernel/src/V3D.cpp @@ -864,6 +864,19 @@ double V3D::toMillerIndexes(double eps) } +/** + Comparator function for sorting list of 3D vectors based on their magnitude. + @param v1 first vector + @param v2 seconde vector + @return true if v1.norm() < v2.norm(). + */ +bool V3D::CompareMagnitude( const V3D & v1, const V3D & v2 ) +{ + double mag_sq_1 = v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]; + double mag_sq_2 = v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]; + return (mag_sq_1 < mag_sq_2); +} + } // Namespace Kernel } // Namespace Mantid From f0c73dc430c628c664c80fe80ae558ac3e15db3c Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 12 Dec 2013 15:54:04 -0500 Subject: [PATCH 176/403] Re #8613. Add a test that exposes the bug. --- .../DataHandling/test/LoadEventNexusTest.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h b/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h index adaa3a006e3d..b9aaf2aecbe7 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h @@ -332,6 +332,24 @@ class LoadEventNexusTest : public CxxTest::TestSuite doTestSingleBank(false, false, "bankDoesNotExist", true); } + void test_SingleBank_with_no_events() + { + LoadEventNexus load; + TS_ASSERT_THROWS_NOTHING( load.initialize() ); + TS_ASSERT_THROWS_NOTHING( load.setPropertyValue("Filename", "HYSA_12509.nxs.h5") ); + TS_ASSERT_THROWS_NOTHING( load.setPropertyValue("BankName", "bank10") ); + const std::string outws("AnEmptyWS"); + TS_ASSERT_THROWS_NOTHING( load.setPropertyValue("OutputWorkspace", outws) ); + if ( !load.execute() ) + { + TS_FAIL("LoadEventNexus shouldn't fail to load an empty bank"); + return; + } + + auto ws = AnalysisDataService::Instance().retrieveWS(outws); + TS_ASSERT_EQUALS( ws->getNumberEvents(), 0 ); + } + void test_instrument_inside_nexus_file() { LoadEventNexus load; From 2acaadd64218f9d0b76d1a2efab3df09680ab78d Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 12 Dec 2013 16:39:00 -0500 Subject: [PATCH 177/403] Added splitByPulseTime(). Refs #8427. --- .../inc/MantidDataObjects/EventList.h | 7 + .../Framework/DataObjects/src/EventList.cpp | 127 ++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/EventList.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/EventList.h index ecb52326a9ca..673a8d3d2435 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/EventList.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/EventList.h @@ -281,6 +281,9 @@ class DLLExport EventList : public Mantid::API::IEventList void splitByFullTime(Kernel::TimeSplitterType & splitter, std::map outputs, double tofcorrection, bool docorrection) const; + /// Split events by pulse time + void splitByPulseTime(Kernel::TimeSplitterType & splitter, std::map outputs) const; + void multiply(const double value, const double error = 0.0); EventList& operator*=(const double value); @@ -375,6 +378,10 @@ class DLLExport EventList : public Mantid::API::IEventList template< class T > void splitByFullTimeHelper(Kernel::TimeSplitterType & splitter, std::map outputs, typename std::vector & events, double tofcorrection, bool docorrection) const; + /// Split events by pulse time + template< class T > + void splitByPulseTimeHelper(Kernel::TimeSplitterType & splitter, std::map outputs, + typename std::vector & events) const; template< class T> static void multiplyHelper(std::vector & events, const double value, const double error = 0.0); template diff --git a/Code/Mantid/Framework/DataObjects/src/EventList.cpp b/Code/Mantid/Framework/DataObjects/src/EventList.cpp index 4ee29fa8a00c..89c1803daf98 100644 --- a/Code/Mantid/Framework/DataObjects/src/EventList.cpp +++ b/Code/Mantid/Framework/DataObjects/src/EventList.cpp @@ -3895,6 +3895,133 @@ namespace DataObjects return; } + + //------------------------------------------- -------------------------------------------------- + /** Split the event list into n outputs by each event's pulse time only + */ + template< class T > + void EventList::splitByPulseTimeHelper(Kernel::TimeSplitterType & splitter, std::map outputs, + typename std::vector & events) const + { + // Prepare to TimeSplitter Iterate through the splitter at the same time + Kernel::TimeSplitterType::iterator itspl = splitter.begin(); + Kernel::TimeSplitterType::iterator itspl_end = splitter.end(); + Kernel::DateAndTime start, stop; + + // Prepare to Events Iterate through all events (sorted by tof) + typename std::vector::iterator itev = events.begin(); + typename std::vector::iterator itev_end = events.end(); + + // Iterate (loop) on all splitters + while (itspl != itspl_end) + { + // Get the splitting interval times and destination group + start = itspl->start().totalNanoseconds(); + stop = itspl->stop().totalNanoseconds(); + const int index = itspl->index(); + + // Skip the events before the start of the time and put to 'unfiltered' EventList + EventList* myOutput = outputs[-1]; + while (itev != itev_end) + { + if (itev->m_pulsetime < start) + { + // Record to index = -1 space + const T eventCopy(*itev); + myOutput->addEventQuickly(eventCopy); + ++ itev; + } + else + { + // Event within a splitter interval + break; + } + } + + // Go through all the events that are in the interval (if any) + while (itev != itev_end) + { + + if (itev->m_pulsetime < stop) + { + // Duplicate event + const T eventCopy(*itev); + EventList * myOutput = outputs[index]; + //Add the copy to the output + myOutput->addEventQuickly(eventCopy); + ++itev; + } + else + { + // Out of interval + break; + } + } + + //Go to the next interval + ++itspl; + //But if we reached the end, then we are done. + if (itspl==itspl_end) + break; + + //No need to keep looping through the filter if we are out of events + if (itev == itev_end) + break; + } // END-WHILE Splitter + + return; + } + + //---------------------------------------------------------------------------------------------- + /** Split the event list by pulse time + */ + void EventList::splitByPulseTime(Kernel::TimeSplitterType & splitter, std::map outputs) const + { + // Check for supported event type + if (eventType == WEIGHTED_NOTIME) + throw std::runtime_error("EventList::splitByTime() called on an EventList that no longer has time information."); + + // Start by sorting the event list by pulse time. + this->sortPulseTimeTOF(); + + // Initialize all the output event lists + std::map::iterator outiter; + for (outiter = outputs.begin(); outiter != outputs.end(); ++outiter) + { + EventList* opeventlist = outiter->second; + opeventlist->clear(); + opeventlist->detectorIDs = this->detectorIDs; + opeventlist->refX = this->refX; + // Match the output event type. + opeventlist->switchTo(eventType); + } + + // Split + if (splitter.size() <= 0) + { + // No splitter: copy all events to group workspace = -1 + (*outputs[-1]) = (*this); + } + else + { + // Split + switch (eventType) + { + case TOF: + splitByPulseTimeHelper(splitter, outputs, this->events); + break; + case WEIGHTED: + splitByPulseTimeHelper(splitter, outputs, this->weightedEvents); + break; + case WEIGHTED_NOTIME: + break; + } + } + + return; + } + + //-------------------------------------------------------------------------- /** Get the vector of events contained in an EventList; * this is overloaded by event type. From dc505c6324b8ac11fdd803830f3e52e4a6723be9 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Thu, 12 Dec 2013 16:40:33 -0500 Subject: [PATCH 178/403] Implemented option filter by pulse time. Refs #8427. --- .../Framework/Algorithms/src/FilterEvents.cpp | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp b/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp index ace2cdf10644..c78a2a789737 100644 --- a/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp +++ b/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp @@ -18,6 +18,17 @@ Some events are not inside any splitters. They are put to a workspace name ende If input property 'OutputWorkspaceIndexedFrom1' is set to True, then this workspace shall not be outputed. +==== Difference from FilterByLogValue ==== +In FilterByLogValue(), EventList.splitByTime() is used. + +In FilterEvents(), if FilterByPulse is selected true, EventList.SplitByTime is called; +otherwise, EventList.SplitByFullTime() is called instead. + +The difference between splitByTime and splitByFullTime is that splitByTime filters events by pulse time, +and splitByFullTime considers both pulse time and TOF. + +Therefore, FilterByLogValue is not suitable for fast log filtering. + *WIKI*/ #include "MantidAlgorithms/FilterEvents.h" @@ -379,10 +390,11 @@ namespace Algorithms //---------------------------------------------------------------------------------------------- /** Parse TOF-correction table workspace to vectors + * Default correction value is equal to 1. */ void FilterEvents::importDetectorTOFCalibration() { - // 1. Prepare output + // Prepare output (class variables) m_detectorIDs.clear(); m_detTofOffsets.clear(); @@ -390,7 +402,7 @@ namespace Algorithms m_detectorIDs.resize(numhist, 0); m_detTofOffsets.resize(numhist, 1.0); - // 2. Set the detector IDs + // Set up the detector IDs to m_detectorIDs[] for (size_t i = 0; i < numhist; ++i) { // FIXME - current implementation assumes one detector per spectra @@ -411,19 +423,19 @@ namespace Algorithms m_detectorIDs[i] = detid; } - // 3. Apply the correction table if it applies + // Calculate TOF correction value for all detectors if (m_detCorrectWorkspace) { - // If a detector calibration workspace is present + // Obtain correction from detector calibration workspace - // a) Check input workspace + // Check input workspace vector colnames = m_detCorrectWorkspace->getColumnNames(); if (colnames.size() < 2) throw runtime_error("Input table workspace is not valide."); else if (colnames[0].compare("DetectorID") || colnames[1].compare("Correction")) throw runtime_error("Input table workspace has wrong column definition."); - // b) Parse detector to a map + // Parse detector and its TOF offset (i.e., correction) to a map map correctmap; size_t numrows = m_detCorrectWorkspace->rowCount(); for (size_t i = 0; i < numrows; ++i) @@ -437,7 +449,7 @@ namespace Algorithms correctmap.insert(make_pair(detid, offset)); } - // c) Map correction map to list + // Check size of TOF correction map if (correctmap.size() > numhist) { g_log.warning() << "Input correction table workspace has more detectors (" << correctmap.size() @@ -454,6 +466,7 @@ namespace Algorithms throw runtime_error(errss.str()); } + // Map correction map to list map::iterator fiter; for (size_t i = 0; i < numhist; ++i) { @@ -509,12 +522,17 @@ namespace Algorithms const DataObjects::EventList& input_el = m_eventWS->getEventList(iws); // Perform the filtering (using the splitting function and just one output) - if (m_doTOFCorrection) + if (mFilterByPulseTime) + { + input_el.splitByPulseTime(m_splitters, outputs); + } + else if (m_doTOFCorrection) { input_el.splitByFullTime(m_splitters, outputs, m_detTofOffsets[iws], m_doTOFCorrection); } else { + // FIXME - is there a way to avoid multiplying 1.0 to all TOF? Which can save CPU time input_el.splitByFullTime(m_splitters, outputs, 1.0, m_doTOFCorrection); } @@ -573,8 +591,8 @@ namespace Algorithms } - /* - * Generate splitters for specified workspace index + //---------------------------------------------------------------------------------------------- + /** Generate splitters for specified workspace index as a subset of m_splitters */ void FilterEvents::generateSplitters(int wsindex, Kernel::TimeSplitterType& splitters) { From 27cfa2098f557a1dbeac4a40075915838de3a59d Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 12 Dec 2013 16:40:39 -0500 Subject: [PATCH 179/403] Re #8613. Remove code that bails out early if no events in a bank. We need the bank name to be added to the list even if it's empty as it's checked for if the BankNames property has been set. There's already a check that means that no LoadBankFromDiskTask is created for the bank if it's empty (the original justification for adding this code in commit [36540217]). I don't think this change has much other effect, but I'll be relying heavily on the tests to confirm that given the horrific complexity of the file. --- Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp index 1d78ba0b4b6d..dceaeb836c04 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp @@ -1425,11 +1425,6 @@ void LoadEventNexus::loadEvents(API::Progress * const prog, const bool monitors) // get the number of events std::size_t num = numEvents(file, hasTotalCounts, oldNeXusFileNames); - if (num == 0) - { - file.closeGroup(); - continue; - } bankNames.push_back( entry_name ); bankNumEvents.push_back(num); total_events += num; From e2128e7236d3895d17933187fdb438e7b54dd3a2 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 11 Dec 2013 10:25:55 +0000 Subject: [PATCH 180/403] refs #8589. Template for new algorithm and tests. --- .../Framework/Algorithms/CMakeLists.txt | 3 + .../CreateTransmissionWorkspace.h | 56 ++++++++++++++ .../src/CreateTransmissionWorkspace.cpp | 74 +++++++++++++++++++ .../test/CreateTransmissionWorkspaceTest.h | 38 ++++++++++ .../python/plugins/algorithms/CMakeLists.txt | 1 + .../CreateTransmissionWorkspaceTest.py | 13 ++++ 6 files changed, 185 insertions(+) create mode 100644 Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h create mode 100644 Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp create mode 100644 Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 369c4dc5f6e4..5e90d8ae502d 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -60,6 +60,7 @@ set ( SRC_FILES src/CreatePSDBleedMask.cpp src/CreatePeaksWorkspace.cpp src/CreateSingleValuedWorkspace.cpp + src/CreateTransmissionWorkspace.cpp src/CreateWorkspace.cpp src/CropWorkspace.cpp src/CrossCorrelate.cpp @@ -282,6 +283,7 @@ set ( INC_FILES inc/MantidAlgorithms/CreatePSDBleedMask.h inc/MantidAlgorithms/CreatePeaksWorkspace.h inc/MantidAlgorithms/CreateSingleValuedWorkspace.h + inc/MantidAlgorithms/CreateTransmissionWorkspace.h inc/MantidAlgorithms/CreateWorkspace.h inc/MantidAlgorithms/CropWorkspace.h inc/MantidAlgorithms/CrossCorrelate.h @@ -516,6 +518,7 @@ set ( TEST_FILES CreatePSDBleedMaskTest.h CreatePeaksWorkspaceTest.h CreateSingleValuedWorkspaceTest.h + CreateTransmissionWorkspaceTest.h CreateWorkspaceTest.h CropWorkspaceTest.h CuboidGaugeVolumeAbsorptionTest.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h new file mode 100644 index 000000000000..598a9dabf694 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h @@ -0,0 +1,56 @@ +#ifndef MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACE_H_ +#define MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACE_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/DataProcessorAlgorithm.h" + +namespace Mantid +{ +namespace Algorithms +{ + + /** CreateTransmissionWorkspace : Create a transmission run workspace in Wavelength given one or more TOF workspaces + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport CreateTransmissionWorkspace : public API::DataProcessorAlgorithm + { + public: + CreateTransmissionWorkspace(); + virtual ~CreateTransmissionWorkspace(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + + private: + virtual void initDocs(); + void init(); + void exec(); + + + }; + + +} // namespace Algorithms +} // namespace Mantid + +#endif /* MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACE_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp new file mode 100644 index 000000000000..aafa8f7d87a1 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -0,0 +1,74 @@ +/*WIKI* +Creates a transmission run workspace given one or more TOF workspaces and the original run Workspace. If two workspaces are provided, then +the workspaces are stitched together using [[Stitch1D]]. InputWorkspaces must be in TOF. A single output workspace is generated with x-units of Wavlength in angstroms. +*WIKI*/ + +#include "MantidAlgorithms/CreateTransmissionWorkspace.h" + +using namespace Mantid::Kernel; +using namespace Mantid::API; + +namespace Mantid +{ +namespace Algorithms +{ + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(CreateTransmissionWorkspace) + + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + CreateTransmissionWorkspace::CreateTransmissionWorkspace() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + CreateTransmissionWorkspace::~CreateTransmissionWorkspace() + { + } + + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string CreateTransmissionWorkspace::name() const { return "CreateTransmissionWorkspace";}; + + /// Algorithm's version for identification. @see Algorithm::version + int CreateTransmissionWorkspace::version() const { return 1;}; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string CreateTransmissionWorkspace::category() const { return "Reflectometry\\ISIS"; } + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void CreateTransmissionWorkspace::initDocs() + { + this->setWikiSummary("Creates a transmission run workspace in Wavelength from input TOF workspaces."); + this->setOptionalMessage(this->getWikiSummary()); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void CreateTransmissionWorkspace::init() + { + declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input), "An input workspace."); + declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace."); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void CreateTransmissionWorkspace::exec() + { + // TODO Auto-generated execute stub + } + + + +} // namespace Algorithms +} // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h b/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h new file mode 100644 index 000000000000..9a7711d0ece8 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h @@ -0,0 +1,38 @@ +#ifndef MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ +#define MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ + +#include + +#include "MantidAlgorithms/CreateTransmissionWorkspace.h" + +using Mantid::Algorithms::CreateTransmissionWorkspace; + +class CreateTransmissionWorkspaceTest : public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static CreateTransmissionWorkspaceTest *createSuite() { return new CreateTransmissionWorkspaceTest(); } + static void destroySuite( CreateTransmissionWorkspaceTest *suite ) { delete suite; } + + + void test_Init() + { + CreateTransmissionWorkspace alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_exec() + { + } + + void test_Something() + { + } + + +}; + + +#endif /* MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index c68b6d8ba1f8..7bad2236ccb5 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -7,6 +7,7 @@ set ( TEST_PY_FILES ConjoinSpectraTest.py CreateLeBailFitInputTest.py CreateWorkspaceTest.py + CreateTransmissionWorkspaceTest.py DakotaChiSquaredTest.py FilterLogByTimeTest.py FindReflectometryLinesTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py new file mode 100644 index 000000000000..696279178f65 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -0,0 +1,13 @@ +import unittest + +class CreateTransmissionWorkspaceTest(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 8843ff2e46b881957c3513790828f336974364e4 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 11 Dec 2013 10:50:53 +0000 Subject: [PATCH 181/403] refs #8589. Create a base algorithm class. --- .../Framework/Algorithms/CMakeLists.txt | 2 + .../CreateTransmissionWorkspace.h | 4 +- .../ReflectometryReductionOne.h | 4 +- .../ReflectometryWorkflowBase.h | 51 +++++++++++++++++++ .../src/ReflectometryWorkflowBase.cpp | 30 +++++++++++ 5 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h create mode 100644 Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 5e90d8ae502d..bea0d1e11a91 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -170,6 +170,7 @@ set ( SRC_FILES src/Rebunch.cpp src/RecordPythonScript.cpp src/ReflectometryReductionOne.cpp + src/ReflectometryWorkflowBase.cpp src/Regroup.cpp src/RemoveBins.cpp src/RemoveExpDecay.cpp @@ -394,6 +395,7 @@ set ( INC_FILES inc/MantidAlgorithms/Rebunch.h inc/MantidAlgorithms/RecordPythonScript.h inc/MantidAlgorithms/ReflectometryReductionOne.h + inc/MantidAlgorithms/ReflectometryWorkflowBase.h inc/MantidAlgorithms/Regroup.h inc/MantidAlgorithms/RemoveBins.h inc/MantidAlgorithms/RemoveExpDecay.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h index 598a9dabf694..ae7860037086 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h @@ -2,7 +2,7 @@ #define MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACE_H_ #include "MantidKernel/System.h" -#include "MantidAPI/DataProcessorAlgorithm.h" +#include "MantidAlgorithms/ReflectometryWorkflowBase.h" namespace Mantid { @@ -31,7 +31,7 @@ namespace Algorithms File change history is stored at: Code Documentation is available at: */ - class DLLExport CreateTransmissionWorkspace : public API::DataProcessorAlgorithm + class DLLExport CreateTransmissionWorkspace : public ReflectometryWorkflowBase { public: CreateTransmissionWorkspace(); diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index 22d53d41c4f9..8948fa9948a3 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -2,11 +2,11 @@ #define MANTID_ALGORITHMS_REFLECTOMETRYREDUCTIONONE_H_ #include "MantidKernel/System.h" -#include "MantidAPI/DataProcessorAlgorithm.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidGeometry/Instrument.h" #include "MantidGeometry/IComponent.h" #include "MantidGeometry/IDetector.h" +#include "MantidAlgorithms/ReflectometryWorkflowBase.h" #include #include #include @@ -38,7 +38,7 @@ namespace Mantid File change history is stored at: Code Documentation is available at: */ - class DLLExport ReflectometryReductionOne: public API::DataProcessorAlgorithm + class DLLExport ReflectometryReductionOne: public ReflectometryWorkflowBase { public: diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h new file mode 100644 index 000000000000..cde2f802e3a1 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -0,0 +1,51 @@ +#ifndef MANTID_ALGORITHMS_REFLECTOMETRYWORKFLOWBASE_H_ +#define MANTID_ALGORITHMS_REFLECTOMETRYWORKFLOWBASE_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/DataProcessorAlgorithm.h" + +namespace Mantid +{ +namespace Algorithms +{ + + /** ReflectometryWorkflowBase : Abstract workflow algortithm base class containing common implementation functionality usable + * by concrete reflectometry workflow algorithms. + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport ReflectometryWorkflowBase : public API::DataProcessorAlgorithm + { + public: + ReflectometryWorkflowBase(); + virtual ~ReflectometryWorkflowBase(); + + + //protected: + + + }; + + +} // namespace Algorithms +} // namespace Mantid + +#endif /* MANTID_ALGORITHMS_REFLECTOMETRYWORKFLOWBASE_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp new file mode 100644 index 000000000000..8ddee29bd5bc --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -0,0 +1,30 @@ +/*WIKI* +TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page. +*WIKI*/ + +#include "MantidAlgorithms/ReflectometryWorkflowBase.h" + +namespace Mantid +{ +namespace Algorithms +{ + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + ReflectometryWorkflowBase::ReflectometryWorkflowBase() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + ReflectometryWorkflowBase::~ReflectometryWorkflowBase() + { + } + + + + +} // namespace Algorithms +} // namespace Mantid From fbb8721407a278f229c12e8b8ce7671a7a9f4bc8 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 11 Dec 2013 12:05:11 +0000 Subject: [PATCH 182/403] refs #8589. Move common toLam to base class. Move and make adjustments to ensure that everything is still working and that tests still pass. --- .../ReflectometryReductionOne.h | 24 --- .../ReflectometryWorkflowBase.h | 82 ++++++---- .../src/ReflectometryReductionOne.cpp | 151 +----------------- .../src/ReflectometryWorkflowBase.cpp | 151 +++++++++++++++++- .../test/ReflectometryReductionOneTest.h | 4 +- 5 files changed, 208 insertions(+), 204 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index 8948fa9948a3..aa5f475b8490 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -7,9 +7,6 @@ #include "MantidGeometry/IComponent.h" #include "MantidGeometry/IDetector.h" #include "MantidAlgorithms/ReflectometryWorkflowBase.h" -#include -#include -#include namespace Mantid { @@ -42,14 +39,6 @@ namespace Mantid { public: - // Class typedefs - typedef boost::tuple MinMax; - typedef boost::optional OptionalDouble; - typedef boost::optional OptionalMatrixWorkspace_sptr; - typedef std::vector WorkspaceIndexList; - typedef boost::optional > OptionalWorkspaceIndexes; - typedef boost::tuple DetectorMonitorWorkspacePair; - /// Constructor ReflectometryReductionOne(); /// Destructor @@ -59,11 +48,6 @@ namespace Mantid virtual int version() const; virtual const std::string category() const; - /// Convert the input workspace to wavelength, splitting according to the properties provided. - DetectorMonitorWorkspacePair toLam(Mantid::API::MatrixWorkspace_sptr toConvert, - const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, - const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep); - /// Convert to an IvsQ workspace. Performs detector positional corrections based on the component name and the theta value. Mantid::API::MatrixWorkspace_sptr toIvsQ(API::MatrixWorkspace_sptr toConvert, const bool correctPosition, OptionalDouble& thetaInDeg, Geometry::IComponent_const_sptr sample, Geometry::IComponent_const_sptr detector); @@ -101,14 +85,6 @@ namespace Mantid /** Algorithm running methods **/ - /// Convert the monitor parts of the input workspace to wavelength - API::MatrixWorkspace_sptr toLamMonitor(const API::MatrixWorkspace_sptr& toConvert, - const int monitorIndex, const MinMax& backgroundMinMax); - - /// Convert the detector spectrum of the input workspace to wavelength - API::MatrixWorkspace_sptr toLamDetector(const WorkspaceIndexList& detectorIndexRange, - const API::MatrixWorkspace_sptr& toConvert, const MinMax& wavelengthMinMax, const double& wavelengthStep); - /// Perform a transmission correction on the input IvsLam workspace API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index cde2f802e3a1..842a61d56b6e 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -4,48 +4,72 @@ #include "MantidKernel/System.h" #include "MantidAPI/DataProcessorAlgorithm.h" +#include +#include +#include + namespace Mantid { -namespace Algorithms -{ + namespace Algorithms + { - /** ReflectometryWorkflowBase : Abstract workflow algortithm base class containing common implementation functionality usable - * by concrete reflectometry workflow algorithms. - - Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + /** ReflectometryWorkflowBase : Abstract workflow algortithm base class containing common implementation functionality usable + * by concrete reflectometry workflow algorithms. - This file is part of Mantid. + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + This file is part of Mantid. - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - File change history is stored at: - Code Documentation is available at: - */ - class DLLExport ReflectometryWorkflowBase : public API::DataProcessorAlgorithm - { - public: - ReflectometryWorkflowBase(); - virtual ~ReflectometryWorkflowBase(); - + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport ReflectometryWorkflowBase: public API::DataProcessorAlgorithm + { + public: + + // Class typedefs + typedef boost::tuple MinMax; + typedef boost::optional OptionalDouble; + typedef boost::optional OptionalMatrixWorkspace_sptr; + typedef std::vector WorkspaceIndexList; + typedef boost::optional > OptionalWorkspaceIndexes; + typedef boost::tuple DetectorMonitorWorkspacePair; + + ReflectometryWorkflowBase(); + virtual ~ReflectometryWorkflowBase(); + + /// Convert the input workspace to wavelength, splitting according to the properties provided. + DetectorMonitorWorkspacePair toLam(Mantid::API::MatrixWorkspace_sptr toConvert, + const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, + const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep); - //protected: + private: + /// Convert the monitor parts of the input workspace to wavelength + API::MatrixWorkspace_sptr toLamMonitor(const API::MatrixWorkspace_sptr& toConvert, + const int monitorIndex, const MinMax& backgroundMinMax); - }; + /// Convert the detector spectrum of the input workspace to wavelength + API::MatrixWorkspace_sptr toLamDetector(const WorkspaceIndexList& detectorIndexRange, + const API::MatrixWorkspace_sptr& toConvert, const MinMax& wavelengthMinMax, + const double& wavelengthStep); + }; -} // namespace Algorithms + } // namespace Algorithms } // namespace Mantid #endif /* MANTID_ALGORITHMS_REFLECTOMETRYWORKFLOWBASE_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index b6b0e1840d4f..82cba48616ee 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -58,11 +58,11 @@ namespace Mantid * @param hostWS : Workspace onto which the resulting workspace indexes will be hosted * @return Remapped wokspace indexes applicable for the host workspace. */ - ReflectometryReductionOne::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( + ReflectometryWorkflowBase::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( MatrixWorkspace_const_sptr originWS, MatrixWorkspace_const_sptr hostWS) { auto spectrumMap = originWS->getSpectrumToWorkspaceIndexMap(); - ReflectometryReductionOne::WorkspaceIndexList translatedIndexList; + ReflectometryWorkflowBase::WorkspaceIndexList translatedIndexList; for (auto it = spectrumMap.begin(); it != spectrumMap.end(); ++it) { specid_t specId = (*it).first; @@ -81,7 +81,7 @@ namespace Mantid * @param originIndexes : Indexes in terms of the origin workspace * @return WorkspaceIndexes in terms of the host workspace */ - ReflectometryReductionOne::WorkspaceIndexList getIndexesInTermsOf( + ReflectometryWorkflowBase::WorkspaceIndexList getIndexesInTermsOf( MatrixWorkspace_const_sptr hostWS, MatrixWorkspace_sptr originWS, const ReflectometryReductionOne::WorkspaceIndexList& originIndexes) { @@ -306,7 +306,7 @@ namespace Mantid * Get the workspace index list * @return Workspace index list. */ - ReflectometryReductionOne::WorkspaceIndexList ReflectometryReductionOne::getWorkspaceIndexList() const + ReflectometryWorkflowBase::WorkspaceIndexList ReflectometryReductionOne::getWorkspaceIndexList() const { WorkspaceIndexList indexList = getProperty("WorkspaceIndexList"); if (indexList.size() % 2 != 0 || indexList.size() == 0) @@ -372,7 +372,7 @@ namespace Mantid * @param maxProperty : Property name for the max property * @return A tuple consisting of min, max */ - ReflectometryReductionOne::MinMax ReflectometryReductionOne::getMinMax( + ReflectometryWorkflowBase::MinMax ReflectometryReductionOne::getMinMax( const std::string& minProperty, const std::string& maxProperty) const { const double min = getProperty(minProperty); @@ -476,147 +476,6 @@ namespace Mantid } - - /** - * Convert the TOF workspace into a monitor workspace. Crops to the monitorIndex and applying flat background correction as part of the process. - * @param toConvert : TOF wavlength to convert. - * @param monitorIndex : Monitor index to crop to - * @param backgroundMinMax : Min and Max Lambda range for Flat background correction. - * @return The cropped and corrected monitor workspace. - */ - MatrixWorkspace_sptr ReflectometryReductionOne::toLamMonitor(const MatrixWorkspace_sptr& toConvert, const int monitorIndex, const MinMax& backgroundMinMax) - { - // Convert Units. - auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); - convertUnitsAlg->initialize(); - convertUnitsAlg->setProperty("InputWorkspace", toConvert); - convertUnitsAlg->setProperty("Target", "Wavelength"); - convertUnitsAlg->setProperty("AlignBins", true); - convertUnitsAlg->execute(); - - // Crop the to the monitor index. - MatrixWorkspace_sptr monitorWS = convertUnitsAlg->getProperty("OutputWorkspace"); - auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); - cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", monitorWS); - cropWorkspaceAlg->setProperty("StartWorkspaceIndex", monitorIndex); - cropWorkspaceAlg->setProperty("EndWorkspaceIndex", monitorIndex); - cropWorkspaceAlg->execute(); - monitorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); - - // Flat background correction - auto correctMonitorsAlg = this->createChildAlgorithm("CalculateFlatBackground"); - correctMonitorsAlg->initialize(); - correctMonitorsAlg->setProperty("InputWorkspace", monitorWS); - correctMonitorsAlg->setProperty("WorkspaceIndexList", - boost::assign::list_of(0).convert_to_container >()); - correctMonitorsAlg->setProperty("StartX", backgroundMinMax.get<0>()); - correctMonitorsAlg->setProperty("EndX", backgroundMinMax.get<1>()); - correctMonitorsAlg->execute(); - monitorWS = correctMonitorsAlg->getProperty("OutputWorkspace"); - - return monitorWS; - } - - /** - * Convert to a detector workspace in lambda. - * @param detectorIndexRange : Workspace index ranges to keep - * @param toConvert : TOF wavelength to convert. - * @param wavelengthMinMax : Wavelength minmax to keep. Crop out the rest. - * @param wavelengthStep : Wavelength step for rebinning - * @return Detector workspace in wavelength - */ - MatrixWorkspace_sptr ReflectometryReductionOne::toLamDetector( - const WorkspaceIndexList& detectorIndexRange, const MatrixWorkspace_sptr& toConvert, - const MinMax& wavelengthMinMax, const double& wavelengthStep) - { - // Detector Workspace Processing - MatrixWorkspace_sptr detectorWS; - - // Loop over pairs of detector index ranges. Peform the cropping and then conjoin the results into a single workspace. - for (size_t i = 0; i < detectorIndexRange.size(); i += 2) - { - auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); - cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", toConvert); - cropWorkspaceAlg->setProperty("StartWorkspaceIndex", detectorIndexRange[i]); - cropWorkspaceAlg->setProperty("EndWorkspaceIndex", detectorIndexRange[i + 1]); - cropWorkspaceAlg->execute(); - MatrixWorkspace_sptr subRange = cropWorkspaceAlg->getProperty("OutputWorkspace"); - if (i == 0) - { - detectorWS = subRange; - } - else - { - auto conjoinWorkspaceAlg = this->createChildAlgorithm("ConjoinWorkspaces"); - conjoinWorkspaceAlg->initialize(); - conjoinWorkspaceAlg->setProperty("InputWorkspace1", detectorWS); - conjoinWorkspaceAlg->setProperty("InputWorkspace2", subRange); - conjoinWorkspaceAlg->execute(); - detectorWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1"); - } - } - // Now convert units. Do this after the conjoining step otherwise the x bins will not match up. - auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); - convertUnitsAlg->initialize(); - convertUnitsAlg->setProperty("InputWorkspace", detectorWS); - convertUnitsAlg->setProperty("Target", "Wavelength"); - convertUnitsAlg->setProperty("AlignBins", true); - convertUnitsAlg->execute(); - detectorWS = convertUnitsAlg->getProperty("OutputWorkspace"); - - // Crop out the lambda x-ranges now that the workspace is in wavelength. - auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); - cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", detectorWS); - cropWorkspaceAlg->setProperty("XMin", wavelengthMinMax.get<0>()); - cropWorkspaceAlg->setProperty("XMax", wavelengthMinMax.get<1>()); - cropWorkspaceAlg->execute(); - detectorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); - - auto rebinWorkspaceAlg = this->createChildAlgorithm("Rebin"); - rebinWorkspaceAlg->initialize(); - std::vector params = boost::assign::list_of(wavelengthStep); - rebinWorkspaceAlg->setProperty("Params", params); - rebinWorkspaceAlg->setProperty("InputWorkspace", detectorWS); - rebinWorkspaceAlg->execute(); - detectorWS = rebinWorkspaceAlg->getProperty("OutputWorkspace"); - - return detectorWS; - } - - /** - * Convert From a TOF workspace into a detector and monitor workspace both in Lambda. - * @param toConvert: TOF workspace to convert - * @param detectorIndexRange : Detector index ranges - * @param monitorIndex : Monitor index - * @param wavelengthMinMax : Wavelength min max for detector workspace - * @param backgroundMinMax : Wavelength min max for flat background correction of monitor workspace - * @param wavelengthStep : Wavlength step size for rebinning. - * @return Tuple of detector and monitor workspaces - */ - ReflectometryReductionOne::DetectorMonitorWorkspacePair ReflectometryReductionOne::toLam(MatrixWorkspace_sptr toConvert, - const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, - const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep) - { - // Detector Workspace Processing - MatrixWorkspace_sptr detectorWS = toLamDetector(detectorIndexRange, toConvert, wavelengthMinMax, wavelengthStep); - - // Monitor Workspace Processing - MatrixWorkspace_sptr monitorWS = toLamMonitor(toConvert, monitorIndex, backgroundMinMax); - - // Rebin the Monitor Workspace to match the Detector Workspace. - auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); - rebinToWorkspaceAlg->initialize(); - rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", monitorWS); - rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", detectorWS); - rebinToWorkspaceAlg->execute(); - monitorWS = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); - - return DetectorMonitorWorkspacePair( detectorWS, monitorWS ); - } - /** * Perform Transmission Corrections. * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 8ddee29bd5bc..5cb7eead147a 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -1,8 +1,10 @@ -/*WIKI* -TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page. -*WIKI*/ #include "MantidAlgorithms/ReflectometryWorkflowBase.h" +#include + +using namespace Mantid::API; +using namespace Mantid::Kernel; + namespace Mantid { @@ -25,6 +27,149 @@ namespace Algorithms + /** + * Convert the TOF workspace into a monitor workspace. Crops to the monitorIndex and applying flat background correction as part of the process. + * @param toConvert : TOF wavlength to convert. + * @param monitorIndex : Monitor index to crop to + * @param backgroundMinMax : Min and Max Lambda range for Flat background correction. + * @return The cropped and corrected monitor workspace. + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamMonitor(const MatrixWorkspace_sptr& toConvert, const int monitorIndex, const MinMax& backgroundMinMax) + { + // Convert Units. + auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); + convertUnitsAlg->initialize(); + convertUnitsAlg->setProperty("InputWorkspace", toConvert); + convertUnitsAlg->setProperty("Target", "Wavelength"); + convertUnitsAlg->setProperty("AlignBins", true); + convertUnitsAlg->execute(); + + // Crop the to the monitor index. + MatrixWorkspace_sptr monitorWS = convertUnitsAlg->getProperty("OutputWorkspace"); + auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); + cropWorkspaceAlg->initialize(); + cropWorkspaceAlg->setProperty("InputWorkspace", monitorWS); + cropWorkspaceAlg->setProperty("StartWorkspaceIndex", monitorIndex); + cropWorkspaceAlg->setProperty("EndWorkspaceIndex", monitorIndex); + cropWorkspaceAlg->execute(); + monitorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); + + // Flat background correction + auto correctMonitorsAlg = this->createChildAlgorithm("CalculateFlatBackground"); + correctMonitorsAlg->initialize(); + correctMonitorsAlg->setProperty("InputWorkspace", monitorWS); + correctMonitorsAlg->setProperty("WorkspaceIndexList", + boost::assign::list_of(0).convert_to_container >()); + correctMonitorsAlg->setProperty("StartX", backgroundMinMax.get<0>()); + correctMonitorsAlg->setProperty("EndX", backgroundMinMax.get<1>()); + correctMonitorsAlg->execute(); + monitorWS = correctMonitorsAlg->getProperty("OutputWorkspace"); + + return monitorWS; + } + + /** + * Convert to a detector workspace in lambda. + * @param detectorIndexRange : Workspace index ranges to keep + * @param toConvert : TOF wavelength to convert. + * @param wavelengthMinMax : Wavelength minmax to keep. Crop out the rest. + * @param wavelengthStep : Wavelength step for rebinning + * @return Detector workspace in wavelength + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamDetector( + const WorkspaceIndexList& detectorIndexRange, const MatrixWorkspace_sptr& toConvert, + const MinMax& wavelengthMinMax, const double& wavelengthStep) + { + // Detector Workspace Processing + MatrixWorkspace_sptr detectorWS; + + // Loop over pairs of detector index ranges. Peform the cropping and then conjoin the results into a single workspace. + for (size_t i = 0; i < detectorIndexRange.size(); i += 2) + { + auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); + cropWorkspaceAlg->initialize(); + cropWorkspaceAlg->setProperty("InputWorkspace", toConvert); + cropWorkspaceAlg->setProperty("StartWorkspaceIndex", detectorIndexRange[i]); + cropWorkspaceAlg->setProperty("EndWorkspaceIndex", detectorIndexRange[i + 1]); + cropWorkspaceAlg->execute(); + MatrixWorkspace_sptr subRange = cropWorkspaceAlg->getProperty("OutputWorkspace"); + if (i == 0) + { + detectorWS = subRange; + } + else + { + auto conjoinWorkspaceAlg = this->createChildAlgorithm("ConjoinWorkspaces"); + conjoinWorkspaceAlg->initialize(); + conjoinWorkspaceAlg->setProperty("InputWorkspace1", detectorWS); + conjoinWorkspaceAlg->setProperty("InputWorkspace2", subRange); + conjoinWorkspaceAlg->execute(); + detectorWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1"); + } + } + // Now convert units. Do this after the conjoining step otherwise the x bins will not match up. + auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); + convertUnitsAlg->initialize(); + convertUnitsAlg->setProperty("InputWorkspace", detectorWS); + convertUnitsAlg->setProperty("Target", "Wavelength"); + convertUnitsAlg->setProperty("AlignBins", true); + convertUnitsAlg->execute(); + detectorWS = convertUnitsAlg->getProperty("OutputWorkspace"); + + // Crop out the lambda x-ranges now that the workspace is in wavelength. + auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); + cropWorkspaceAlg->initialize(); + cropWorkspaceAlg->setProperty("InputWorkspace", detectorWS); + cropWorkspaceAlg->setProperty("XMin", wavelengthMinMax.get<0>()); + cropWorkspaceAlg->setProperty("XMax", wavelengthMinMax.get<1>()); + cropWorkspaceAlg->execute(); + detectorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); + + auto rebinWorkspaceAlg = this->createChildAlgorithm("Rebin"); + rebinWorkspaceAlg->initialize(); + std::vector params = boost::assign::list_of(wavelengthStep); + rebinWorkspaceAlg->setProperty("Params", params); + rebinWorkspaceAlg->setProperty("InputWorkspace", detectorWS); + rebinWorkspaceAlg->execute(); + detectorWS = rebinWorkspaceAlg->getProperty("OutputWorkspace"); + + return detectorWS; + } + + /** + * Convert From a TOF workspace into a detector and monitor workspace both in Lambda. + * @param toConvert: TOF workspace to convert + * @param detectorIndexRange : Detector index ranges + * @param monitorIndex : Monitor index + * @param wavelengthMinMax : Wavelength min max for detector workspace + * @param backgroundMinMax : Wavelength min max for flat background correction of monitor workspace + * @param wavelengthStep : Wavlength step size for rebinning. + * @return Tuple of detector and monitor workspaces + */ + ReflectometryWorkflowBase::DetectorMonitorWorkspacePair ReflectometryWorkflowBase::toLam(MatrixWorkspace_sptr toConvert, + const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, + const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep) + { + // Detector Workspace Processing + MatrixWorkspace_sptr detectorWS = toLamDetector(detectorIndexRange, toConvert, wavelengthMinMax, wavelengthStep); + + // Monitor Workspace Processing + MatrixWorkspace_sptr monitorWS = toLamMonitor(toConvert, monitorIndex, backgroundMinMax); + + // Rebin the Monitor Workspace to match the Detector Workspace. + auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); + rebinToWorkspaceAlg->initialize(); + rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", monitorWS); + rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", detectorWS); + rebinToWorkspaceAlg->execute(); + monitorWS = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); + + return DetectorMonitorWorkspacePair( detectorWS, monitorWS ); + } + + + + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h b/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h index b1b7456b1c8b..5d526b87c77f 100644 --- a/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h +++ b/Code/Mantid/Framework/Algorithms/test/ReflectometryReductionOneTest.h @@ -9,7 +9,7 @@ using namespace Mantid; using namespace Mantid::Kernel; using namespace Mantid::API; -using Mantid::Algorithms::ReflectometryReductionOne; +using namespace Mantid::Algorithms; class ReflectometryReductionOneTest: public CxxTest::TestSuite { @@ -49,7 +49,7 @@ class ReflectometryReductionOneTest: public CxxTest::TestSuite ReflectometryReductionOne alg; // Run the conversion. - ReflectometryReductionOne::DetectorMonitorWorkspacePair inLam = alg.toLam(toConvert, + ReflectometryWorkflowBase::DetectorMonitorWorkspacePair inLam = alg.toLam(toConvert, detectorIndexRange, monitorIndex, boost::tuple(wavelengthMin, wavelengthMax), boost::tuple(backgroundWavelengthMin, backgroundWavelengthMax), wavelengthStep); From 5340581d1e4681256d642002280b95473e84bdd7 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 11 Dec 2013 15:12:48 +0000 Subject: [PATCH 183/403] refs #8589. Move existing functions into base class. Will still need to do some work around these yet. --- .../ReflectometryReductionOne.h | 21 -- .../ReflectometryWorkflowBase.h | 25 ++ .../src/CreateTransmissionWorkspace.cpp | 217 +++++++++++++----- .../src/ReflectometryReductionOne.cpp | 194 ---------------- .../src/ReflectometryWorkflowBase.cpp | 202 +++++++++++++++- .../CreateTransmissionWorkspaceTest.py | 135 ++++++++++- 6 files changed, 515 insertions(+), 279 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index aa5f475b8490..987864f3def9 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -61,27 +61,6 @@ namespace Mantid void exec(); - /** Auxillary getters and validators **/ - bool isPropertyDefault(const std::string& propertyName) const; - - /// Get a workspace index list. - WorkspaceIndexList getWorkspaceIndexList() const; - - /// Get min max indexes. - void fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, bool isPointDetector, - OptionalWorkspaceIndexes& optionalUpperLower) const; - - /// Get the min/max property values - MinMax getMinMax(const std::string& minProperty, const std::string& maxProperty) const; - - /// Get the transmission correction properties - void getTransmissionRunInfo(OptionalMatrixWorkspace_sptr& firstTransmissionRun, - OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, - OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, - OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const; - - /// Validate the transmission correction property inputs - void validateTransmissionInputs() const; /** Algorithm running methods **/ diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index 842a61d56b6e..bcd43c9c1c21 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -56,8 +56,32 @@ namespace Mantid const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep); + protected: + + /// Determine if the property has it's default value. + bool isPropertyDefault(const std::string& propertyName) const; + + /// Get a workspace index list. + WorkspaceIndexList getWorkspaceIndexList() const; + + /// Get min max indexes. + void fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, bool isPointDetector, + OptionalWorkspaceIndexes& optionalUpperLower) const; + + /// Get the min/max property values + MinMax getMinMax(const std::string& minProperty, const std::string& maxProperty) const; + + /// Get the transmission correction properties + void getTransmissionRunInfo(OptionalMatrixWorkspace_sptr& firstTransmissionRun, + OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, + OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, + OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const; + private: + /// Validate the transmission correction property inputs + void validateTransmissionInputs() const; + /// Convert the monitor parts of the input workspace to wavelength API::MatrixWorkspace_sptr toLamMonitor(const API::MatrixWorkspace_sptr& toConvert, const int monitorIndex, const MinMax& backgroundMinMax); @@ -69,6 +93,7 @@ namespace Mantid }; + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index aafa8f7d87a1..6730cb1823f8 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -1,74 +1,175 @@ /*WIKI* -Creates a transmission run workspace given one or more TOF workspaces and the original run Workspace. If two workspaces are provided, then -the workspaces are stitched together using [[Stitch1D]]. InputWorkspaces must be in TOF. A single output workspace is generated with x-units of Wavlength in angstroms. -*WIKI*/ + Creates a transmission run workspace given one or more TOF workspaces and the original run Workspace. If two workspaces are provided, then + the workspaces are stitched together using [[Stitch1D]]. InputWorkspaces must be in TOF. A single output workspace is generated with x-units of Wavlength in angstroms. + *WIKI*/ #include "MantidAlgorithms/CreateTransmissionWorkspace.h" +#include "MantidAPI/WorkspaceValidators.h" +#include "MantidKernel/MandatoryValidator.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/EnabledWhenProperty.h" +#include "MantidKernel/RebinParamsValidator.h" +#include "MantidKernel/BoundedValidator.h" +#include + using namespace Mantid::Kernel; using namespace Mantid::API; namespace Mantid { -namespace Algorithms -{ + namespace Algorithms + { - // Register the algorithm into the AlgorithmFactory - DECLARE_ALGORITHM(CreateTransmissionWorkspace) - + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(CreateTransmissionWorkspace) + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + CreateTransmissionWorkspace::CreateTransmissionWorkspace() + { + } - //---------------------------------------------------------------------------------------------- - /** Constructor - */ - CreateTransmissionWorkspace::CreateTransmissionWorkspace() - { - } - - //---------------------------------------------------------------------------------------------- - /** Destructor - */ - CreateTransmissionWorkspace::~CreateTransmissionWorkspace() - { - } - - - //---------------------------------------------------------------------------------------------- - /// Algorithm's name for identification. @see Algorithm::name - const std::string CreateTransmissionWorkspace::name() const { return "CreateTransmissionWorkspace";}; - - /// Algorithm's version for identification. @see Algorithm::version - int CreateTransmissionWorkspace::version() const { return 1;}; - - /// Algorithm's category for identification. @see Algorithm::category - const std::string CreateTransmissionWorkspace::category() const { return "Reflectometry\\ISIS"; } - - //---------------------------------------------------------------------------------------------- - /// Sets documentation strings for this algorithm - void CreateTransmissionWorkspace::initDocs() - { - this->setWikiSummary("Creates a transmission run workspace in Wavelength from input TOF workspaces."); - this->setOptionalMessage(this->getWikiSummary()); - } - - //---------------------------------------------------------------------------------------------- - /** Initialize the algorithm's properties. - */ - void CreateTransmissionWorkspace::init() - { - declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input), "An input workspace."); - declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace."); - } - - //---------------------------------------------------------------------------------------------- - /** Execute the algorithm. - */ - void CreateTransmissionWorkspace::exec() - { - // TODO Auto-generated execute stub - } + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + CreateTransmissionWorkspace::~CreateTransmissionWorkspace() + { + } + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string CreateTransmissionWorkspace::name() const + { + return "CreateTransmissionWorkspace"; + } + ; + + /// Algorithm's version for identification. @see Algorithm::version + int CreateTransmissionWorkspace::version() const + { + return 1; + } + ; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string CreateTransmissionWorkspace::category() const + { + return "Reflectometry\\ISIS"; + } + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void CreateTransmissionWorkspace::initDocs() + { + this->setWikiSummary( + "Creates a transmission run workspace in Wavelength from input TOF workspaces."); + this->setOptionalMessage(this->getWikiSummary()); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void CreateTransmissionWorkspace::init() + { + boost::shared_ptr inputValidator = boost::make_shared(); + inputValidator->add(boost::make_shared("TOF")); + + declareProperty( + new WorkspaceProperty("InputWorkspace", "", Direction::Input, + PropertyMode::Mandatory, inputValidator->clone()), + "First transmission run, or the low wavelength transmision run if SecondTransmissionRun is also provided."); + + declareProperty( + new WorkspaceProperty("SecondTransmissionWorkspace", "", Direction::Input, + PropertyMode::Optional, inputValidator->clone()), + "Second, high wavelength transmission run. Optional. Causes the InputWorkspace to be treated as the low wavelength transmission run."); + + declareProperty( + new PropertyWithValue("WavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum in angstroms"); + + declareProperty( + new PropertyWithValue("WavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum in angstroms"); + + declareProperty( + new PropertyWithValue("WavelengthStep", 0.05, + boost::make_shared >(), Direction::Input), + "Wavelength rebinning step in angstroms. Defaults to 0.05. Used for rebinning intermediate workspaces converted into wavelength."); + + boost::shared_ptr mandatoryWorkspaceIndex = boost::make_shared< + CompositeValidator>(); + mandatoryWorkspaceIndex->add(boost::make_shared >()); + auto boundedIndex = boost::make_shared >(); + boundedIndex->setLower(0); + mandatoryWorkspaceIndex->add(boundedIndex); + + declareProperty( + new PropertyWithValue("I0MonitorIndex", Mantid::EMPTY_INT(), mandatoryWorkspaceIndex), + "I0 monitor index"); + + declareProperty( + new PropertyWithValue("MonitorBackgroundWavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum for monitor background in angstroms."); + + declareProperty( + new PropertyWithValue("MonitorBackgroundWavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum for monitor background in angstroms."); + + declareProperty( + new PropertyWithValue("MonitorIntegrationWavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum for integration in angstroms."); + declareProperty( + new PropertyWithValue("MonitorIntegrationWavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum for integration in angstroms."); + + declareProperty(new ArrayProperty("WorkspaceIndexList"), + "Indices of the spectra in pairs (lower, upper) that mark the ranges that correspond to detectors of interest."); + + declareProperty( + new ArrayProperty("Params", boost::make_shared(true)), + "A comma separated list of first bin boundary, width, last bin boundary. " + "These parameters are used for stitching together transmission runs. " + "Values are in q. This input is only needed if a SecondTransmission run is provided."); + + declareProperty( + new PropertyWithValue("StartOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), + "Start Q for stitching transmission runs together"); + + declareProperty( + new PropertyWithValue("EndOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), + "End Q for stitching transmission runs together"); + + declareProperty(new WorkspaceProperty("OutputWorkspace", "", Direction::Output), + "Output Workspace IvsQ."); + + setPropertySettings("Params", + new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); + + setPropertySettings("StartOverlapQ", + new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); + + setPropertySettings("EndOverlapQ", + new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); + } + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void CreateTransmissionWorkspace::exec() + { + MatrixWorkspace_sptr firstTranmsission = getProperty("InputWorkspace"); + setProperty("OutputWorkspace",firstTranmsission); + } -} // namespace Algorithms + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 82cba48616ee..6dc8a6b7fc11 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -95,16 +95,6 @@ namespace Mantid return translatedIndexList; } - /** - * Helper method used with the stl to determine whether values are negative - * @param value : Value to check - * @return : True if negative. - */ - bool checkNotPositive(const int value) - { - return value < 0; - } - const std::string multiDetectorAnalysis = "MultiDetectorAnalysis"; const std::string pointDetectorAnalysis = "PointDetectorAnalysis"; } @@ -290,191 +280,7 @@ namespace Mantid new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "MultiDetectorAnalysis")); } - /** - * Determine if the property value is the same as the default value. - * This can be used to determine if the property has not been set. - * @param propertyName : Name of property to query - * @return: True only if the property has it's default value. - */ - bool ReflectometryReductionOne::isPropertyDefault(const std::string& propertyName) const - { - Property* property = this->getProperty(propertyName); - return property->isDefault(); - } - - /** - * Get the workspace index list - * @return Workspace index list. - */ - ReflectometryWorkflowBase::WorkspaceIndexList ReflectometryReductionOne::getWorkspaceIndexList() const - { - WorkspaceIndexList indexList = getProperty("WorkspaceIndexList"); - if (indexList.size() % 2 != 0 || indexList.size() == 0) - { - throw std::invalid_argument( - "WorkspaceIndex list must be composed of pairs of min index, max index."); - } - - if (std::find_if(indexList.begin(), indexList.end(), checkNotPositive) != indexList.end()) - { - throw std::invalid_argument("WorkspaceIndexList contains negative indexes"); - } - - for (size_t i = 0; (i + 1) < indexList.size(); i += 2) - { - if (indexList[i] > indexList[i + 1]) - throw std::invalid_argument("WorkspaceIndexList pairs must be in min, max order"); - } - return indexList; - } - - /** - * Fetch min, max inputs as a vector (int) if they are non-default and set them to the optionalUpperLower object. - * Performs checks to verify that invalid indexes have not been passed in. - * @param propertyName : Property name to fetch - * @param isPointDetector : Flag indicates that the execution is in point detector mode. - * @param optionalUpperLower : Object to set min and max on. - */ - void ReflectometryReductionOne::fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, - bool isPointDetector, OptionalWorkspaceIndexes& optionalUpperLower) const - { - if (!isPropertyDefault(propertyName)) - { - // Validation of property inputs. - if (isPointDetector) - { - throw std::invalid_argument( - "Cannot have a region of interest property in point detector mode."); - } - std::vector temp = this->getProperty(propertyName); - if (temp.size() != 2) - { - const std::string message = propertyName + " requires a lower and upper boundary"; - throw std::invalid_argument(message); - } - if (temp[0] > temp[1]) - { - throw std::invalid_argument("Min must be <= Max index"); - } - if (std::find_if(temp.begin(), temp.end(), checkNotPositive) != temp.end()) - { - const std::string message = propertyName + " contains negative indexes"; - throw std::invalid_argument(message); - } - // Assignment - optionalUpperLower = temp; - } - } - /** - * Get min max pairs as a tuple. - * @param minProperty : Property name for the min property - * @param maxProperty : Property name for the max property - * @return A tuple consisting of min, max - */ - ReflectometryWorkflowBase::MinMax ReflectometryReductionOne::getMinMax( - const std::string& minProperty, const std::string& maxProperty) const - { - const double min = getProperty(minProperty); - const double max = getProperty(maxProperty); - if (min > max) - { - throw std::invalid_argument("Cannot have any WavelengthMin > WavelengthMax"); - } - return MinMax(min, max); - } - - /** - * Validate the transmission workspace inputs when a second transmission run is provided. - * Throws if any of the property values do not make sense. - */ - void ReflectometryReductionOne::validateTransmissionInputs() const - { - // Verify that all the required inputs for the second transmission run are now given. - if (isPropertyDefault("FirstTransmissionRun")) - { - throw std::invalid_argument( - "A SecondTransmissionRun is only valid if a FirstTransmissionRun is provided."); - } - if (isPropertyDefault("Params")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then stitching Params for the transmission runs are also required."); - } - if (isPropertyDefault("StartOverlapQ")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching StartOverlapQ for the transmission runs is also required."); - } - if (isPropertyDefault("EndOverlapQ")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching EndOverlapQ for the transmission runs is also required."); - } - const double startOverlapQ = this->getProperty("StartOverlapQ"); - const double endOverlapQ = this->getProperty("EndOverlapQ"); - if (startOverlapQ >= endOverlapQ) - { - throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); - } - - } - - /** - * Get the transmission run information. - * - * Transmission runs are optional, but you cannot have the second without the first. Also, stitching - * parameters are required if the second is present. This getter fetches and assigns to the optional reference arguments - * - * @param firstTransmissionRun - * @param secondTransmissionRun - * @param stitchingStartQ - * @param stitchingDeltaQ - * @param stitchingEndQ - */ - void ReflectometryReductionOne::getTransmissionRunInfo( - OptionalMatrixWorkspace_sptr& firstTransmissionRun, - OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, - OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, - OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const - { - if (!isPropertyDefault("FirstTransmissionRun")) - { - MatrixWorkspace_sptr temp = this->getProperty("FirstTransmissionRun"); - /* - if(temp->getNumberHistograms() > 1) - { - throw std::invalid_argument("Error with FirstTransmissionRun. Only one histogram is permitted for a transmission run."); - } - */ - firstTransmissionRun = temp; - } - - if (!isPropertyDefault("SecondTransmissionRun")) - { - // Check that the property values provided make sense together. - validateTransmissionInputs(); - - // Set the values. - { - MatrixWorkspace_sptr temp = this->getProperty("SecondTransmissionRun"); - secondTransmissionRun = temp; - } - { - std::vector params = getProperty("Params"); - stitchingStartQ = params[0]; - stitchingDeltaQ = params[1]; - stitchingEndQ = params[2]; - } - { - double temp = this->getProperty("StartOverlapQ"); - stitchingStartOverlapQ = temp; - temp = this->getProperty("EndOverlapQ"); - stitchingEndOverlapQ = temp; - } - } - - } /** * Perform Transmission Corrections. diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 5cb7eead147a..8e6936791c4b 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -8,8 +8,20 @@ using namespace Mantid::Kernel; namespace Mantid { -namespace Algorithms -{ + namespace Algorithms + { + namespace + { + /** + * Helper method used with the stl to determine whether values are negative + * @param value : Value to check + * @return : True if negative. + */ + bool checkNotPositive(const int value) + { + return value < 0; + } + } //---------------------------------------------------------------------------------------------- /** Constructor @@ -25,6 +37,192 @@ namespace Algorithms { } + /** + * Determine if the property value is the same as the default value. + * This can be used to determine if the property has not been set. + * @param propertyName : Name of property to query + * @return: True only if the property has it's default value. + */ + bool ReflectometryWorkflowBase::isPropertyDefault(const std::string& propertyName) const + { + Property* property = this->getProperty(propertyName); + return property->isDefault(); + } + + /** + * Get the workspace index list + * @return Workspace index list. + */ + ReflectometryWorkflowBase::WorkspaceIndexList ReflectometryWorkflowBase::getWorkspaceIndexList() const + { + WorkspaceIndexList indexList = getProperty("WorkspaceIndexList"); + if (indexList.size() % 2 != 0 || indexList.size() == 0) + { + throw std::invalid_argument( + "WorkspaceIndex list must be composed of pairs of min index, max index."); + } + + if (std::find_if(indexList.begin(), indexList.end(), checkNotPositive) != indexList.end()) + { + throw std::invalid_argument("WorkspaceIndexList contains negative indexes"); + } + + for (size_t i = 0; (i + 1) < indexList.size(); i += 2) + { + if (indexList[i] > indexList[i + 1]) + throw std::invalid_argument("WorkspaceIndexList pairs must be in min, max order"); + } + return indexList; + } + + /** + * Fetch min, max inputs as a vector (int) if they are non-default and set them to the optionalUpperLower object. + * Performs checks to verify that invalid indexes have not been passed in. + * @param propertyName : Property name to fetch + * @param isPointDetector : Flag indicates that the execution is in point detector mode. + * @param optionalUpperLower : Object to set min and max on. + */ + void ReflectometryWorkflowBase::fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, + bool isPointDetector, OptionalWorkspaceIndexes& optionalUpperLower) const + { + if (!isPropertyDefault(propertyName)) + { + // Validation of property inputs. + if (isPointDetector) + { + throw std::invalid_argument( + "Cannot have a region of interest property in point detector mode."); + } + std::vector temp = this->getProperty(propertyName); + if (temp.size() != 2) + { + const std::string message = propertyName + " requires a lower and upper boundary"; + throw std::invalid_argument(message); + } + if (temp[0] > temp[1]) + { + throw std::invalid_argument("Min must be <= Max index"); + } + if (std::find_if(temp.begin(), temp.end(), checkNotPositive) != temp.end()) + { + const std::string message = propertyName + " contains negative indexes"; + throw std::invalid_argument(message); + } + // Assignment + optionalUpperLower = temp; + } + } + + /** + * Get min max pairs as a tuple. + * @param minProperty : Property name for the min property + * @param maxProperty : Property name for the max property + * @return A tuple consisting of min, max + */ + ReflectometryWorkflowBase::MinMax ReflectometryWorkflowBase::getMinMax( + const std::string& minProperty, const std::string& maxProperty) const + { + const double min = getProperty(minProperty); + const double max = getProperty(maxProperty); + if (min > max) + { + throw std::invalid_argument("Cannot have any WavelengthMin > WavelengthMax"); + } + return MinMax(min, max); + } + + /** + * Validate the transmission workspace inputs when a second transmission run is provided. + * Throws if any of the property values do not make sense. + */ + void ReflectometryWorkflowBase::validateTransmissionInputs() const + { + // Verify that all the required inputs for the second transmission run are now given. + if (isPropertyDefault("FirstTransmissionRun")) + { + throw std::invalid_argument( + "A SecondTransmissionRun is only valid if a FirstTransmissionRun is provided."); + } + if (isPropertyDefault("Params")) + { + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then stitching Params for the transmission runs are also required."); + } + if (isPropertyDefault("StartOverlapQ")) + { + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then a stitching StartOverlapQ for the transmission runs is also required."); + } + if (isPropertyDefault("EndOverlapQ")) + { + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then a stitching EndOverlapQ for the transmission runs is also required."); + } + const double startOverlapQ = this->getProperty("StartOverlapQ"); + const double endOverlapQ = this->getProperty("EndOverlapQ"); + if (startOverlapQ >= endOverlapQ) + { + throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); + } + + } + + /** + * Get the transmission run information. + * + * Transmission runs are optional, but you cannot have the second without the first. Also, stitching + * parameters are required if the second is present. This getter fetches and assigns to the optional reference arguments + * + * @param firstTransmissionRun + * @param secondTransmissionRun + * @param stitchingStartQ + * @param stitchingDeltaQ + * @param stitchingEndQ + */ + void ReflectometryWorkflowBase::getTransmissionRunInfo( + OptionalMatrixWorkspace_sptr& firstTransmissionRun, + OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, + OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, + OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const + { + if (!isPropertyDefault("FirstTransmissionRun")) + { + MatrixWorkspace_sptr temp = this->getProperty("FirstTransmissionRun"); + /* + if(temp->getNumberHistograms() > 1) + { + throw std::invalid_argument("Error with FirstTransmissionRun. Only one histogram is permitted for a transmission run."); + } + */ + firstTransmissionRun = temp; + } + + if (!isPropertyDefault("SecondTransmissionRun")) + { + // Check that the property values provided make sense together. + validateTransmissionInputs(); + + // Set the values. + { + MatrixWorkspace_sptr temp = this->getProperty("SecondTransmissionRun"); + secondTransmissionRun = temp; + } + { + std::vector params = getProperty("Params"); + stitchingStartQ = params[0]; + stitchingDeltaQ = params[1]; + stitchingEndQ = params[2]; + } + { + double temp = this->getProperty("StartOverlapQ"); + stitchingStartOverlapQ = temp; + temp = this->getProperty("EndOverlapQ"); + stitchingEndOverlapQ = temp; + } + } + + } + /** diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index 696279178f65..1ae0a1433503 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -1,12 +1,139 @@ import unittest +from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace -class CreateTransmissionWorkspaceTest(unittest.TestCase): +import inspect +import re + +def make_decorator(algorithm_to_decorate): + """ + Dynamically create a builder pattern style decorator around a Mantid algorithm. + This allows you to separate out setting algorithm parameters from the actual method execution. Parameters may be reset multiple times. + + Usage: + rebin = make_decorator(Rebin) + rebin.set_Params([0, 0.1, 1]) + .... + rebin.execute() + + Arguments: + algorithm_to_decorate: The mantid.simpleapi algorithm to decorate. + + + + """ + + class Decorator(object): - def setUp(self): - pass + def __init__(self, alg_subject): + self.__alg_subject = alg_subject + self.__parameters__ = dict() + + def execute(self, additional=None, verbose=False): + if verbose: + print "Algorithm Parameters:" + print self.__parameters__ + print + out = self.__alg_subject(**self.__parameters__) + return out + + def set_additional(self, additional): + self.__parameters__.update(**additional) + + def add_getter_setter(type, name): + + def setter(self, x): + self.__parameters__[name] = x + + def getter(self): + return self.__parameters__[name] + + setattr(type, "set_" + name, setter) + setattr(type, "get_" + name, getter) + + + argspec = inspect.getargspec(algorithm_to_decorate) + for parameter in argspec.varargs.split(','): + m = re.search('(^\w+)', parameter) # Take the parameter key part from the defaults given as 'key=value' + if m: + parameter = m.group(0).strip() + m = re.search('\w+$', parameter) # strip off any leading numerical values produced by argspec + if m: + parameter = m.group(0).strip() + add_getter_setter(Decorator, m.group(0).strip()) + + return Decorator(algorithm_to_decorate) + + +class CreateTransmissionWorkspaceTest(unittest.TestCase): + def setUp(self): + tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + self.__tof = tof + self.__not_tof = not_tof + def tearDown(self): - pass + DeleteWorkspace(self.__tof) + DeleteWorkspace(self.__not_tof) + + def construct_standard_algorithm(self): + alg = make_decorator(CreateTransmissionWorkspace) + alg.set_InputWorkspace(self.__tof) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(1.0) + alg.set_I0MonitorIndex(0) + alg.set_WorkspaceIndexList([0, 1]) + alg.set_MonitorBackgroundWavelengthMin(0.0) + alg.set_MonitorBackgroundWavelengthMax(1.0) + alg.set_MonitorIntegrationWavelengthMin(0.0) + alg.set_MonitorIntegrationWavelengthMax(1.0) + return alg + + def test_input_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_InputWorkspace(self.__not_tof) + self.assertRaises(ValueError, alg.execute) + + def test_second_transmission_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionWorkspace(self.__not_tof) + self.assertRaises(ValueError, alg.execute) + + def test_provide_second_transmission_run_without_params_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionWorkspace(self.__tof) + self.assertRaises(ValueError, alg.execute) + + def test_provide_second_transmission_run_without_start_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_EndOverlapQ( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_provide_end_transmission_run_without_end_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlapQ( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlapQ( 0.6 ) + alg.set_EndOverlapQ( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_must_provide_wavelengths(self): + self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + + + def test_execute(self): + alg = self.construct_standard_algorithm() + alg.execute() if __name__ == '__main__': From c7868e4fd3165041ffe51cc796cb804a3042345b Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 09:15:12 +0000 Subject: [PATCH 184/403] refs #8489. Common parameter init to base class. This has involved making some names common. --- .../ReflectometryWorkflowBase.h | 7 + .../src/CreateTransmissionWorkspace.cpp | 93 +-- .../src/ReflectometryReductionOne.cpp | 60 +- .../src/ReflectometryWorkflowBase.cpp | 681 ++++++++++-------- .../CreateTransmissionWorkspaceTest.py | 55 +- 5 files changed, 462 insertions(+), 434 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index bcd43c9c1c21..6b0e685f0ddc 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -77,6 +77,13 @@ namespace Mantid OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const; + /// Init common index inputs + void initIndexInputs(); + /// Init common wavelength inputs + void initWavelengthInputs(); + /// Init common stitching inputs + void initStitchingInputs(); + private: /// Validate the transmission correction property inputs diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index 6730cb1823f8..f6b84e5d80eb 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -77,76 +77,18 @@ namespace Mantid inputValidator->add(boost::make_shared("TOF")); declareProperty( - new WorkspaceProperty("InputWorkspace", "", Direction::Input, + new WorkspaceProperty("FirstTransmissionRun", "", Direction::Input, PropertyMode::Mandatory, inputValidator->clone()), "First transmission run, or the low wavelength transmision run if SecondTransmissionRun is also provided."); declareProperty( - new WorkspaceProperty("SecondTransmissionWorkspace", "", Direction::Input, + new WorkspaceProperty("SecondTransmissionRun", "", Direction::Input, PropertyMode::Optional, inputValidator->clone()), "Second, high wavelength transmission run. Optional. Causes the InputWorkspace to be treated as the low wavelength transmission run."); - declareProperty( - new PropertyWithValue("WavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum in angstroms"); - - declareProperty( - new PropertyWithValue("WavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum in angstroms"); - - declareProperty( - new PropertyWithValue("WavelengthStep", 0.05, - boost::make_shared >(), Direction::Input), - "Wavelength rebinning step in angstroms. Defaults to 0.05. Used for rebinning intermediate workspaces converted into wavelength."); - - boost::shared_ptr mandatoryWorkspaceIndex = boost::make_shared< - CompositeValidator>(); - mandatoryWorkspaceIndex->add(boost::make_shared >()); - auto boundedIndex = boost::make_shared >(); - boundedIndex->setLower(0); - mandatoryWorkspaceIndex->add(boundedIndex); - - declareProperty( - new PropertyWithValue("I0MonitorIndex", Mantid::EMPTY_INT(), mandatoryWorkspaceIndex), - "I0 monitor index"); - - declareProperty( - new PropertyWithValue("MonitorBackgroundWavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum for monitor background in angstroms."); - - declareProperty( - new PropertyWithValue("MonitorBackgroundWavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum for monitor background in angstroms."); - - declareProperty( - new PropertyWithValue("MonitorIntegrationWavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum for integration in angstroms."); - declareProperty( - new PropertyWithValue("MonitorIntegrationWavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum for integration in angstroms."); - - declareProperty(new ArrayProperty("WorkspaceIndexList"), - "Indices of the spectra in pairs (lower, upper) that mark the ranges that correspond to detectors of interest."); - - declareProperty( - new ArrayProperty("Params", boost::make_shared(true)), - "A comma separated list of first bin boundary, width, last bin boundary. " - "These parameters are used for stitching together transmission runs. " - "Values are in q. This input is only needed if a SecondTransmission run is provided."); - - declareProperty( - new PropertyWithValue("StartOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "Start Q for stitching transmission runs together"); - - declareProperty( - new PropertyWithValue("EndOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "End Q for stitching transmission runs together"); + this->initStitchingInputs(); + this->initIndexInputs(); + this->initWavelengthInputs(); declareProperty(new WorkspaceProperty("OutputWorkspace", "", Direction::Output), "Output Workspace IvsQ."); @@ -167,8 +109,29 @@ namespace Mantid */ void CreateTransmissionWorkspace::exec() { - MatrixWorkspace_sptr firstTranmsission = getProperty("InputWorkspace"); - setProperty("OutputWorkspace",firstTranmsission); + OptionalMatrixWorkspace_sptr firstTransmissionRun; + OptionalMatrixWorkspace_sptr secondTransmissionRun; + OptionalDouble stitchingStartQ; + OptionalDouble stitchingDeltaQ; + OptionalDouble stitchingEndQ; + OptionalDouble stitchingStartOverlapQ; + OptionalDouble stitchingEndOverlapQ; + + getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStartQ, + stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ); + + const MinMax wavelengthInterval = this->getMinMax("WavelengthMin", "WavelengthMax"); + const double wavelengthStep = getProperty("WavelengthStep"); + const MinMax monitorBackgroundWavelengthInterval = getMinMax("MonitorBackgroundWavelengthMin", + "MonitorBackgroundWavelengthMax"); + const MinMax monitorIntegrationWavelengthInterval = getMinMax("MonitorIntegrationWavelengthMin", + "MonitorIntegrationWavelengthMax"); + + const WorkspaceIndexList indexList = getWorkspaceIndexList(); + + const int i0MonitorIndex = getProperty("I0MonitorIndex"); + + setProperty("OutputWorkspace", firstTransmissionRun.get()); } } // namespace Algorithms diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 6dc8a6b7fc11..9a35d95cb758 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -172,52 +172,9 @@ namespace Mantid declareProperty(new ArrayProperty("RegionOfDirectBeam"), "Indices of the spectra a pair (lower, upper) that mark the ranges that correspond to the direct beam in multi-detector mode."); - declareProperty( - new PropertyWithValue("WavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum in angstroms"); - declareProperty( - new PropertyWithValue("WavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum in angstroms"); - - declareProperty( - new PropertyWithValue("WavelengthStep", 0.05, - boost::make_shared >(), Direction::Input), - "Wavelength rebinning step in angstroms. Defaults to 0.05. Used for rebinning intermediate workspaces converted into wavelength."); - - boost::shared_ptr mandatoryWorkspaceIndex = boost::make_shared< - CompositeValidator>(); - mandatoryWorkspaceIndex->add(boost::make_shared >()); - auto boundedIndex = boost::make_shared >(); - boundedIndex->setLower(0); - mandatoryWorkspaceIndex->add(boundedIndex); - - declareProperty( - new PropertyWithValue("I0MonitorIndex", Mantid::EMPTY_INT(), mandatoryWorkspaceIndex), - "I0 monitor index"); - - declareProperty( - new PropertyWithValue("MonitorBackgroundWavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum for monitor background in angstroms. Taken to be WavelengthMin if not provided."); + this->initIndexInputs(); + this->initWavelengthInputs(); - declareProperty( - new PropertyWithValue("MonitorBackgroundWavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum for monitor background in angstroms. Taken to be WavelengthMax if not provided."); - - declareProperty( - new PropertyWithValue("MonitorIntegrationWavelengthMin", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength minimum for integration in angstroms. Taken to be WavelengthMin if not provided."); - declareProperty( - new PropertyWithValue("MonitorIntegrationWavelengthMax", Mantid::EMPTY_DBL(), - boost::make_shared >(), Direction::Input), - "Wavelength maximum for integration in angstroms. Taken to be WavelengthMax if not provided."); - - declareProperty(new ArrayProperty("WorkspaceIndexList"), - "Indices of the spectra in pairs (lower, upper) that mark the ranges that correspond to detectors of interest."); declareProperty(new PropertyWithValue("DetectorComponentName", "", Direction::Input), "Name of the detector component i.e. point-detector. If these are not specified, the algorithm will attempt lookup using a standard naming convention."); @@ -245,18 +202,7 @@ namespace Mantid PropertyMode::Optional, inputValidator->clone()), "Second, high wavelength transmission run. Optional. Causes the FirstTransmissionRun to be treated as the low wavelength transmission run."); - declareProperty( - new ArrayProperty("Params", boost::make_shared(true)), - "A comma separated list of first bin boundary, width, last bin boundary. " - "These parameters are used for stitching together transmission runs. " - "Values are in q. This input is only needed if a SecondTransmission run is provided."); - - declareProperty( - new PropertyWithValue("StartOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "Start Q for stitching transmission runs together"); - declareProperty( - new PropertyWithValue("EndOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "End Q for stitching transmission runs together"); + this->initStitchingInputs(); setPropertyGroup("FirstTransmissionRun", "Transmission"); setPropertyGroup("SecondTransmissionRun", "Transmission"); diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 8e6936791c4b..d85dabbbee35 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -1,11 +1,15 @@ - +#include "MantidAPI/WorkspaceValidators.h" +#include "MantidKernel/MandatoryValidator.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/RebinParamsValidator.h" +#include "MantidKernel/BoundedValidator.h" #include "MantidAlgorithms/ReflectometryWorkflowBase.h" + #include using namespace Mantid::API; using namespace Mantid::Kernel; - namespace Mantid { namespace Algorithms @@ -23,351 +27,422 @@ namespace Mantid } } - //---------------------------------------------------------------------------------------------- - /** Constructor - */ - ReflectometryWorkflowBase::ReflectometryWorkflowBase() - { - } - - //---------------------------------------------------------------------------------------------- - /** Destructor - */ - ReflectometryWorkflowBase::~ReflectometryWorkflowBase() - { - } - - /** - * Determine if the property value is the same as the default value. - * This can be used to determine if the property has not been set. - * @param propertyName : Name of property to query - * @return: True only if the property has it's default value. - */ - bool ReflectometryWorkflowBase::isPropertyDefault(const std::string& propertyName) const - { - Property* property = this->getProperty(propertyName); - return property->isDefault(); - } - - /** - * Get the workspace index list - * @return Workspace index list. - */ - ReflectometryWorkflowBase::WorkspaceIndexList ReflectometryWorkflowBase::getWorkspaceIndexList() const - { - WorkspaceIndexList indexList = getProperty("WorkspaceIndexList"); - if (indexList.size() % 2 != 0 || indexList.size() == 0) + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + ReflectometryWorkflowBase::ReflectometryWorkflowBase() { - throw std::invalid_argument( - "WorkspaceIndex list must be composed of pairs of min index, max index."); } - if (std::find_if(indexList.begin(), indexList.end(), checkNotPositive) != indexList.end()) + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + ReflectometryWorkflowBase::~ReflectometryWorkflowBase() { - throw std::invalid_argument("WorkspaceIndexList contains negative indexes"); } - for (size_t i = 0; (i + 1) < indexList.size(); i += 2) + /** + * + */ + void ReflectometryWorkflowBase::initIndexInputs() { - if (indexList[i] > indexList[i + 1]) - throw std::invalid_argument("WorkspaceIndexList pairs must be in min, max order"); + + boost::shared_ptr mandatoryWorkspaceIndex = boost::make_shared< + CompositeValidator>(); + mandatoryWorkspaceIndex->add(boost::make_shared >()); + auto boundedIndex = boost::make_shared >(); + boundedIndex->setLower(0); + mandatoryWorkspaceIndex->add(boundedIndex); + + declareProperty( + new PropertyWithValue("I0MonitorIndex", Mantid::EMPTY_INT(), mandatoryWorkspaceIndex), + "I0 monitor index"); + + declareProperty(new ArrayProperty("WorkspaceIndexList"), + "Indices of the spectra in pairs (lower, upper) that mark the ranges that correspond to detectors of interest."); + } - return indexList; - } - - /** - * Fetch min, max inputs as a vector (int) if they are non-default and set them to the optionalUpperLower object. - * Performs checks to verify that invalid indexes have not been passed in. - * @param propertyName : Property name to fetch - * @param isPointDetector : Flag indicates that the execution is in point detector mode. - * @param optionalUpperLower : Object to set min and max on. - */ - void ReflectometryWorkflowBase::fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, - bool isPointDetector, OptionalWorkspaceIndexes& optionalUpperLower) const - { - if (!isPropertyDefault(propertyName)) + + /** + * Init common wavlength inputs. + */ + void ReflectometryWorkflowBase::initWavelengthInputs() + { + declareProperty( + new PropertyWithValue("WavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum in angstroms"); + + declareProperty( + new PropertyWithValue("WavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum in angstroms"); + + declareProperty( + new PropertyWithValue("WavelengthStep", 0.05, + boost::make_shared >(), Direction::Input), + "Wavelength rebinning step in angstroms. Defaults to 0.05. Used for rebinning intermediate workspaces converted into wavelength."); + + declareProperty( + new PropertyWithValue("MonitorBackgroundWavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum for monitor background in angstroms."); + + declareProperty( + new PropertyWithValue("MonitorBackgroundWavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum for monitor background in angstroms."); + + declareProperty( + new PropertyWithValue("MonitorIntegrationWavelengthMin", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength minimum for integration in angstroms."); + declareProperty( + new PropertyWithValue("MonitorIntegrationWavelengthMax", Mantid::EMPTY_DBL(), + boost::make_shared >(), Direction::Input), + "Wavelength maximum for integration in angstroms."); + } + + void ReflectometryWorkflowBase::initStitchingInputs() + { + declareProperty( + new ArrayProperty("Params", boost::make_shared(true)), + "A comma separated list of first bin boundary, width, last bin boundary. " + "These parameters are used for stitching together transmission runs. " + "Values are in q. This input is only needed if a SecondTransmission run is provided."); + + declareProperty( + new PropertyWithValue("StartOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), + "Start Q for stitching transmission runs together"); + + declareProperty( + new PropertyWithValue("EndOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), + "End Q for stitching transmission runs together"); + + } + + /** + * Determine if the property value is the same as the default value. + * This can be used to determine if the property has not been set. + * @param propertyName : Name of property to query + * @return: True only if the property has it's default value. + */ + bool ReflectometryWorkflowBase::isPropertyDefault(const std::string& propertyName) const + { + Property* property = this->getProperty(propertyName); + return property->isDefault(); + } + + /** + * Get the workspace index list + * @return Workspace index list. + */ + ReflectometryWorkflowBase::WorkspaceIndexList ReflectometryWorkflowBase::getWorkspaceIndexList() const { - // Validation of property inputs. - if (isPointDetector) + WorkspaceIndexList indexList = getProperty("WorkspaceIndexList"); + if (indexList.size() % 2 != 0 || indexList.size() == 0) { throw std::invalid_argument( - "Cannot have a region of interest property in point detector mode."); - } - std::vector temp = this->getProperty(propertyName); - if (temp.size() != 2) - { - const std::string message = propertyName + " requires a lower and upper boundary"; - throw std::invalid_argument(message); + "WorkspaceIndex list must be composed of pairs of min index, max index."); } - if (temp[0] > temp[1]) + + if (std::find_if(indexList.begin(), indexList.end(), checkNotPositive) != indexList.end()) { - throw std::invalid_argument("Min must be <= Max index"); + throw std::invalid_argument("WorkspaceIndexList contains negative indexes"); } - if (std::find_if(temp.begin(), temp.end(), checkNotPositive) != temp.end()) + + for (size_t i = 0; (i + 1) < indexList.size(); i += 2) { - const std::string message = propertyName + " contains negative indexes"; - throw std::invalid_argument(message); + if (indexList[i] > indexList[i + 1]) + throw std::invalid_argument("WorkspaceIndexList pairs must be in min, max order"); } - // Assignment - optionalUpperLower = temp; - } - } - - /** - * Get min max pairs as a tuple. - * @param minProperty : Property name for the min property - * @param maxProperty : Property name for the max property - * @return A tuple consisting of min, max - */ - ReflectometryWorkflowBase::MinMax ReflectometryWorkflowBase::getMinMax( - const std::string& minProperty, const std::string& maxProperty) const - { - const double min = getProperty(minProperty); - const double max = getProperty(maxProperty); - if (min > max) - { - throw std::invalid_argument("Cannot have any WavelengthMin > WavelengthMax"); + return indexList; } - return MinMax(min, max); - } - - /** - * Validate the transmission workspace inputs when a second transmission run is provided. - * Throws if any of the property values do not make sense. - */ - void ReflectometryWorkflowBase::validateTransmissionInputs() const - { - // Verify that all the required inputs for the second transmission run are now given. - if (isPropertyDefault("FirstTransmissionRun")) - { - throw std::invalid_argument( - "A SecondTransmissionRun is only valid if a FirstTransmissionRun is provided."); - } - if (isPropertyDefault("Params")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then stitching Params for the transmission runs are also required."); - } - if (isPropertyDefault("StartOverlapQ")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching StartOverlapQ for the transmission runs is also required."); - } - if (isPropertyDefault("EndOverlapQ")) - { - throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching EndOverlapQ for the transmission runs is also required."); - } - const double startOverlapQ = this->getProperty("StartOverlapQ"); - const double endOverlapQ = this->getProperty("EndOverlapQ"); - if (startOverlapQ >= endOverlapQ) + + /** + * Fetch min, max inputs as a vector (int) if they are non-default and set them to the optionalUpperLower object. + * Performs checks to verify that invalid indexes have not been passed in. + * @param propertyName : Property name to fetch + * @param isPointDetector : Flag indicates that the execution is in point detector mode. + * @param optionalUpperLower : Object to set min and max on. + */ + void ReflectometryWorkflowBase::fetchOptionalLowerUpperPropertyValue(const std::string& propertyName, + bool isPointDetector, OptionalWorkspaceIndexes& optionalUpperLower) const { - throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); + if (!isPropertyDefault(propertyName)) + { + // Validation of property inputs. + if (isPointDetector) + { + throw std::invalid_argument( + "Cannot have a region of interest property in point detector mode."); + } + std::vector temp = this->getProperty(propertyName); + if (temp.size() != 2) + { + const std::string message = propertyName + " requires a lower and upper boundary"; + throw std::invalid_argument(message); + } + if (temp[0] > temp[1]) + { + throw std::invalid_argument("Min must be <= Max index"); + } + if (std::find_if(temp.begin(), temp.end(), checkNotPositive) != temp.end()) + { + const std::string message = propertyName + " contains negative indexes"; + throw std::invalid_argument(message); + } + // Assignment + optionalUpperLower = temp; + } } - } - - /** - * Get the transmission run information. - * - * Transmission runs are optional, but you cannot have the second without the first. Also, stitching - * parameters are required if the second is present. This getter fetches and assigns to the optional reference arguments - * - * @param firstTransmissionRun - * @param secondTransmissionRun - * @param stitchingStartQ - * @param stitchingDeltaQ - * @param stitchingEndQ - */ - void ReflectometryWorkflowBase::getTransmissionRunInfo( - OptionalMatrixWorkspace_sptr& firstTransmissionRun, - OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, - OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, - OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const - { - if (!isPropertyDefault("FirstTransmissionRun")) + /** + * Get min max pairs as a tuple. + * @param minProperty : Property name for the min property + * @param maxProperty : Property name for the max property + * @return A tuple consisting of min, max + */ + ReflectometryWorkflowBase::MinMax ReflectometryWorkflowBase::getMinMax( + const std::string& minProperty, const std::string& maxProperty) const { - MatrixWorkspace_sptr temp = this->getProperty("FirstTransmissionRun"); - /* - if(temp->getNumberHistograms() > 1) - { - throw std::invalid_argument("Error with FirstTransmissionRun. Only one histogram is permitted for a transmission run."); - } - */ - firstTransmissionRun = temp; + const double min = getProperty(minProperty); + const double max = getProperty(maxProperty); + if (min > max) + { + throw std::invalid_argument("Cannot have any WavelengthMin > WavelengthMax"); + } + return MinMax(min, max); } - if (!isPropertyDefault("SecondTransmissionRun")) + /** + * Validate the transmission workspace inputs when a second transmission run is provided. + * Throws if any of the property values do not make sense. + */ + void ReflectometryWorkflowBase::validateTransmissionInputs() const { - // Check that the property values provided make sense together. - validateTransmissionInputs(); - - // Set the values. + // Verify that all the required inputs for the second transmission run are now given. + if (isPropertyDefault("FirstTransmissionRun")) { - MatrixWorkspace_sptr temp = this->getProperty("SecondTransmissionRun"); - secondTransmissionRun = temp; + throw std::invalid_argument( + "A SecondTransmissionRun is only valid if a FirstTransmissionRun is provided."); } + if (isPropertyDefault("Params")) { - std::vector params = getProperty("Params"); - stitchingStartQ = params[0]; - stitchingDeltaQ = params[1]; - stitchingEndQ = params[2]; + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then stitching Params for the transmission runs are also required."); } + if (isPropertyDefault("StartOverlapQ")) { - double temp = this->getProperty("StartOverlapQ"); - stitchingStartOverlapQ = temp; - temp = this->getProperty("EndOverlapQ"); - stitchingEndOverlapQ = temp; + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then a stitching StartOverlapQ for the transmission runs is also required."); + } + if (isPropertyDefault("EndOverlapQ")) + { + throw std::invalid_argument( + "If a SecondTransmissionRun has been given, then a stitching EndOverlapQ for the transmission runs is also required."); + } + const double startOverlapQ = this->getProperty("StartOverlapQ"); + const double endOverlapQ = this->getProperty("EndOverlapQ"); + if (startOverlapQ >= endOverlapQ) + { + throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); } - } - } + } + /** + * Get the transmission run information. + * + * Transmission runs are optional, but you cannot have the second without the first. Also, stitching + * parameters are required if the second is present. This getter fetches and assigns to the optional reference arguments + * + * @param firstTransmissionRun + * @param secondTransmissionRun + * @param stitchingStartQ + * @param stitchingDeltaQ + * @param stitchingEndQ + */ + void ReflectometryWorkflowBase::getTransmissionRunInfo( + OptionalMatrixWorkspace_sptr& firstTransmissionRun, + OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, + OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, + OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const + { + if (!isPropertyDefault("FirstTransmissionRun")) + { + MatrixWorkspace_sptr temp = this->getProperty("FirstTransmissionRun"); + firstTransmissionRun = temp; + } + if (!isPropertyDefault("SecondTransmissionRun")) + { + // Check that the property values provided make sense together. + validateTransmissionInputs(); + + // Set the values. + { + MatrixWorkspace_sptr temp = this->getProperty("SecondTransmissionRun"); + secondTransmissionRun = temp; + } + { + std::vector params = getProperty("Params"); + stitchingStartQ = params[0]; + stitchingDeltaQ = params[1]; + stitchingEndQ = params[2]; + } + { + double temp = this->getProperty("StartOverlapQ"); + stitchingStartOverlapQ = temp; + temp = this->getProperty("EndOverlapQ"); + stitchingEndOverlapQ = temp; + } + } - /** - * Convert the TOF workspace into a monitor workspace. Crops to the monitorIndex and applying flat background correction as part of the process. - * @param toConvert : TOF wavlength to convert. - * @param monitorIndex : Monitor index to crop to - * @param backgroundMinMax : Min and Max Lambda range for Flat background correction. - * @return The cropped and corrected monitor workspace. - */ - MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamMonitor(const MatrixWorkspace_sptr& toConvert, const int monitorIndex, const MinMax& backgroundMinMax) - { - // Convert Units. - auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); - convertUnitsAlg->initialize(); - convertUnitsAlg->setProperty("InputWorkspace", toConvert); - convertUnitsAlg->setProperty("Target", "Wavelength"); - convertUnitsAlg->setProperty("AlignBins", true); - convertUnitsAlg->execute(); - - // Crop the to the monitor index. - MatrixWorkspace_sptr monitorWS = convertUnitsAlg->getProperty("OutputWorkspace"); - auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); - cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", monitorWS); - cropWorkspaceAlg->setProperty("StartWorkspaceIndex", monitorIndex); - cropWorkspaceAlg->setProperty("EndWorkspaceIndex", monitorIndex); - cropWorkspaceAlg->execute(); - monitorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); - - // Flat background correction - auto correctMonitorsAlg = this->createChildAlgorithm("CalculateFlatBackground"); - correctMonitorsAlg->initialize(); - correctMonitorsAlg->setProperty("InputWorkspace", monitorWS); - correctMonitorsAlg->setProperty("WorkspaceIndexList", - boost::assign::list_of(0).convert_to_container >()); - correctMonitorsAlg->setProperty("StartX", backgroundMinMax.get<0>()); - correctMonitorsAlg->setProperty("EndX", backgroundMinMax.get<1>()); - correctMonitorsAlg->execute(); - monitorWS = correctMonitorsAlg->getProperty("OutputWorkspace"); - - return monitorWS; - } - - /** - * Convert to a detector workspace in lambda. - * @param detectorIndexRange : Workspace index ranges to keep - * @param toConvert : TOF wavelength to convert. - * @param wavelengthMinMax : Wavelength minmax to keep. Crop out the rest. - * @param wavelengthStep : Wavelength step for rebinning - * @return Detector workspace in wavelength - */ - MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamDetector( - const WorkspaceIndexList& detectorIndexRange, const MatrixWorkspace_sptr& toConvert, - const MinMax& wavelengthMinMax, const double& wavelengthStep) - { - // Detector Workspace Processing - MatrixWorkspace_sptr detectorWS; + } - // Loop over pairs of detector index ranges. Peform the cropping and then conjoin the results into a single workspace. - for (size_t i = 0; i < detectorIndexRange.size(); i += 2) + /** + * Convert the TOF workspace into a monitor workspace. Crops to the monitorIndex and applying flat background correction as part of the process. + * @param toConvert : TOF wavlength to convert. + * @param monitorIndex : Monitor index to crop to + * @param backgroundMinMax : Min and Max Lambda range for Flat background correction. + * @return The cropped and corrected monitor workspace. + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamMonitor(const MatrixWorkspace_sptr& toConvert, + const int monitorIndex, const MinMax& backgroundMinMax) { + // Convert Units. + auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); + convertUnitsAlg->initialize(); + convertUnitsAlg->setProperty("InputWorkspace", toConvert); + convertUnitsAlg->setProperty("Target", "Wavelength"); + convertUnitsAlg->setProperty("AlignBins", true); + convertUnitsAlg->execute(); + + // Crop the to the monitor index. + MatrixWorkspace_sptr monitorWS = convertUnitsAlg->getProperty("OutputWorkspace"); auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", toConvert); - cropWorkspaceAlg->setProperty("StartWorkspaceIndex", detectorIndexRange[i]); - cropWorkspaceAlg->setProperty("EndWorkspaceIndex", detectorIndexRange[i + 1]); + cropWorkspaceAlg->setProperty("InputWorkspace", monitorWS); + cropWorkspaceAlg->setProperty("StartWorkspaceIndex", monitorIndex); + cropWorkspaceAlg->setProperty("EndWorkspaceIndex", monitorIndex); cropWorkspaceAlg->execute(); - MatrixWorkspace_sptr subRange = cropWorkspaceAlg->getProperty("OutputWorkspace"); - if (i == 0) - { - detectorWS = subRange; - } - else - { - auto conjoinWorkspaceAlg = this->createChildAlgorithm("ConjoinWorkspaces"); - conjoinWorkspaceAlg->initialize(); - conjoinWorkspaceAlg->setProperty("InputWorkspace1", detectorWS); - conjoinWorkspaceAlg->setProperty("InputWorkspace2", subRange); - conjoinWorkspaceAlg->execute(); - detectorWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1"); - } + monitorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); + + // Flat background correction + auto correctMonitorsAlg = this->createChildAlgorithm("CalculateFlatBackground"); + correctMonitorsAlg->initialize(); + correctMonitorsAlg->setProperty("InputWorkspace", monitorWS); + correctMonitorsAlg->setProperty("WorkspaceIndexList", + boost::assign::list_of(0).convert_to_container >()); + correctMonitorsAlg->setProperty("StartX", backgroundMinMax.get<0>()); + correctMonitorsAlg->setProperty("EndX", backgroundMinMax.get<1>()); + correctMonitorsAlg->execute(); + monitorWS = correctMonitorsAlg->getProperty("OutputWorkspace"); + + return monitorWS; } - // Now convert units. Do this after the conjoining step otherwise the x bins will not match up. - auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); - convertUnitsAlg->initialize(); - convertUnitsAlg->setProperty("InputWorkspace", detectorWS); - convertUnitsAlg->setProperty("Target", "Wavelength"); - convertUnitsAlg->setProperty("AlignBins", true); - convertUnitsAlg->execute(); - detectorWS = convertUnitsAlg->getProperty("OutputWorkspace"); - - // Crop out the lambda x-ranges now that the workspace is in wavelength. - auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); - cropWorkspaceAlg->initialize(); - cropWorkspaceAlg->setProperty("InputWorkspace", detectorWS); - cropWorkspaceAlg->setProperty("XMin", wavelengthMinMax.get<0>()); - cropWorkspaceAlg->setProperty("XMax", wavelengthMinMax.get<1>()); - cropWorkspaceAlg->execute(); - detectorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); - - auto rebinWorkspaceAlg = this->createChildAlgorithm("Rebin"); - rebinWorkspaceAlg->initialize(); - std::vector params = boost::assign::list_of(wavelengthStep); - rebinWorkspaceAlg->setProperty("Params", params); - rebinWorkspaceAlg->setProperty("InputWorkspace", detectorWS); - rebinWorkspaceAlg->execute(); - detectorWS = rebinWorkspaceAlg->getProperty("OutputWorkspace"); - - return detectorWS; - } - - /** - * Convert From a TOF workspace into a detector and monitor workspace both in Lambda. - * @param toConvert: TOF workspace to convert - * @param detectorIndexRange : Detector index ranges - * @param monitorIndex : Monitor index - * @param wavelengthMinMax : Wavelength min max for detector workspace - * @param backgroundMinMax : Wavelength min max for flat background correction of monitor workspace - * @param wavelengthStep : Wavlength step size for rebinning. - * @return Tuple of detector and monitor workspaces - */ - ReflectometryWorkflowBase::DetectorMonitorWorkspacePair ReflectometryWorkflowBase::toLam(MatrixWorkspace_sptr toConvert, - const WorkspaceIndexList& detectorIndexRange, const int monitorIndex, - const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, const double& wavelengthStep) - { - // Detector Workspace Processing - MatrixWorkspace_sptr detectorWS = toLamDetector(detectorIndexRange, toConvert, wavelengthMinMax, wavelengthStep); - - // Monitor Workspace Processing - MatrixWorkspace_sptr monitorWS = toLamMonitor(toConvert, monitorIndex, backgroundMinMax); - // Rebin the Monitor Workspace to match the Detector Workspace. - auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); - rebinToWorkspaceAlg->initialize(); - rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", monitorWS); - rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", detectorWS); - rebinToWorkspaceAlg->execute(); - monitorWS = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); - - return DetectorMonitorWorkspacePair( detectorWS, monitorWS ); - } + /** + * Convert to a detector workspace in lambda. + * @param detectorIndexRange : Workspace index ranges to keep + * @param toConvert : TOF wavelength to convert. + * @param wavelengthMinMax : Wavelength minmax to keep. Crop out the rest. + * @param wavelengthStep : Wavelength step for rebinning + * @return Detector workspace in wavelength + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::toLamDetector( + const WorkspaceIndexList& detectorIndexRange, const MatrixWorkspace_sptr& toConvert, + const MinMax& wavelengthMinMax, const double& wavelengthStep) + { + // Detector Workspace Processing + MatrixWorkspace_sptr detectorWS; + // Loop over pairs of detector index ranges. Peform the cropping and then conjoin the results into a single workspace. + for (size_t i = 0; i < detectorIndexRange.size(); i += 2) + { + auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); + cropWorkspaceAlg->initialize(); + cropWorkspaceAlg->setProperty("InputWorkspace", toConvert); + cropWorkspaceAlg->setProperty("StartWorkspaceIndex", detectorIndexRange[i]); + cropWorkspaceAlg->setProperty("EndWorkspaceIndex", detectorIndexRange[i + 1]); + cropWorkspaceAlg->execute(); + MatrixWorkspace_sptr subRange = cropWorkspaceAlg->getProperty("OutputWorkspace"); + if (i == 0) + { + detectorWS = subRange; + } + else + { + auto conjoinWorkspaceAlg = this->createChildAlgorithm("ConjoinWorkspaces"); + conjoinWorkspaceAlg->initialize(); + conjoinWorkspaceAlg->setProperty("InputWorkspace1", detectorWS); + conjoinWorkspaceAlg->setProperty("InputWorkspace2", subRange); + conjoinWorkspaceAlg->execute(); + detectorWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1"); + } + } + // Now convert units. Do this after the conjoining step otherwise the x bins will not match up. + auto convertUnitsAlg = this->createChildAlgorithm("ConvertUnits"); + convertUnitsAlg->initialize(); + convertUnitsAlg->setProperty("InputWorkspace", detectorWS); + convertUnitsAlg->setProperty("Target", "Wavelength"); + convertUnitsAlg->setProperty("AlignBins", true); + convertUnitsAlg->execute(); + detectorWS = convertUnitsAlg->getProperty("OutputWorkspace"); + + // Crop out the lambda x-ranges now that the workspace is in wavelength. + auto cropWorkspaceAlg = this->createChildAlgorithm("CropWorkspace"); + cropWorkspaceAlg->initialize(); + cropWorkspaceAlg->setProperty("InputWorkspace", detectorWS); + cropWorkspaceAlg->setProperty("XMin", wavelengthMinMax.get<0>()); + cropWorkspaceAlg->setProperty("XMax", wavelengthMinMax.get<1>()); + cropWorkspaceAlg->execute(); + detectorWS = cropWorkspaceAlg->getProperty("OutputWorkspace"); + auto rebinWorkspaceAlg = this->createChildAlgorithm("Rebin"); + rebinWorkspaceAlg->initialize(); + std::vector params = boost::assign::list_of(wavelengthStep); + rebinWorkspaceAlg->setProperty("Params", params); + rebinWorkspaceAlg->setProperty("InputWorkspace", detectorWS); + rebinWorkspaceAlg->execute(); + detectorWS = rebinWorkspaceAlg->getProperty("OutputWorkspace"); + return detectorWS; + } + /** + * Convert From a TOF workspace into a detector and monitor workspace both in Lambda. + * @param toConvert: TOF workspace to convert + * @param detectorIndexRange : Detector index ranges + * @param monitorIndex : Monitor index + * @param wavelengthMinMax : Wavelength min max for detector workspace + * @param backgroundMinMax : Wavelength min max for flat background correction of monitor workspace + * @param wavelengthStep : Wavlength step size for rebinning. + * @return Tuple of detector and monitor workspaces + */ + ReflectometryWorkflowBase::DetectorMonitorWorkspacePair ReflectometryWorkflowBase::toLam( + MatrixWorkspace_sptr toConvert, const WorkspaceIndexList& detectorIndexRange, + const int monitorIndex, const MinMax& wavelengthMinMax, const MinMax& backgroundMinMax, + const double& wavelengthStep) + { + // Detector Workspace Processing + MatrixWorkspace_sptr detectorWS = toLamDetector(detectorIndexRange, toConvert, wavelengthMinMax, + wavelengthStep); + + // Monitor Workspace Processing + MatrixWorkspace_sptr monitorWS = toLamMonitor(toConvert, monitorIndex, backgroundMinMax); + + // Rebin the Monitor Workspace to match the Detector Workspace. + auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); + rebinToWorkspaceAlg->initialize(); + rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", monitorWS); + rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", detectorWS); + rebinToWorkspaceAlg->execute(); + monitorWS = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); + + return DetectorMonitorWorkspacePair(detectorWS, monitorWS); + } -} // namespace Algorithms + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index 1ae0a1433503..a0b936e35ed3 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -78,7 +78,7 @@ def tearDown(self): def construct_standard_algorithm(self): alg = make_decorator(CreateTransmissionWorkspace) - alg.set_InputWorkspace(self.__tof) + alg.set_FirstTransmissionRun(self.__tof) alg.set_WavelengthMin(0.0) alg.set_WavelengthMax(1.0) alg.set_I0MonitorIndex(0) @@ -91,45 +91,82 @@ def construct_standard_algorithm(self): def test_input_workspace_not_tof_throws(self): alg = self.construct_standard_algorithm() - alg.set_InputWorkspace(self.__not_tof) + alg.set_FirstTransmissionRun(self.__not_tof) self.assertRaises(ValueError, alg.execute) def test_second_transmission_workspace_not_tof_throws(self): alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionWorkspace(self.__not_tof) + alg.set_SecondTransmissionRun(self.__not_tof) self.assertRaises(ValueError, alg.execute) def test_provide_second_transmission_run_without_params_throws(self): alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) self.assertRaises(ValueError, alg.execute) def test_provide_second_transmission_run_without_start_overlap_q_throws(self): alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) alg.set_EndOverlapQ( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_provide_end_transmission_run_without_end_overlap_q_throws(self): alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) alg.set_StartOverlapQ( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionWorkspace(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) alg.set_StartOverlapQ( 0.6 ) alg.set_EndOverlapQ( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + self.assertRaises(RuntimeError, CreateTransmissionWorkspace, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, CreateTransmissionWorkspace, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + def test_wavelength_min_greater_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WavelengthMin(1.0) + alg.set_WavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorBackgroundWavelengthMin(1.0) + alg.set_MonitorBackgroundWavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorIntegrationWavelengthMin(1.0) + alg.set_MonitorIntegrationWavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_index_positive(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_throw_if_not_pairs(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([0]) + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_values_not_positive_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 + self.assertRaises(ValueError, alg.execute) def test_execute(self): alg = self.construct_standard_algorithm() From bcc2ae5d4c86faa9f3bab71e240915a6bcbce1e6 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 09:44:40 +0000 Subject: [PATCH 185/403] refs #8589. Move transmission correction code into base class. More work will need to be done here because we yet need to separate out the making from the utilisation parts in order for this to be useful to both Correction and Reduction algorithms which use it. --- .../ReflectometryReductionOne.h | 14 -- .../ReflectometryWorkflowBase.h | 11 ++ .../src/ReflectometryReductionOne.cpp | 102 -------------- .../src/ReflectometryWorkflowBase.cpp | 128 ++++++++++++++++++ 4 files changed, 139 insertions(+), 116 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index 987864f3def9..4332402d1889 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -61,20 +61,6 @@ namespace Mantid void exec(); - - /** Algorithm running methods **/ - - /// Perform a transmission correction on the input IvsLam workspace - API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, - const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, - API::MatrixWorkspace_sptr firstTransmissionRun, - OptionalMatrixWorkspace_sptr secondTransmissionRun, const OptionalDouble& stitchingStartQ, - const OptionalDouble& stitchingDeltaQ, const OptionalDouble& stitchingEndQ, - const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, - const double& wavelengthStep - ); - /// Get the surface sample component Mantid::Geometry::IComponent_const_sptr getSurfaceSampleComponent(Mantid::Geometry::Instrument_const_sptr inst); diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index 6b0e685f0ddc..a4fd4e67425d 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -84,6 +84,17 @@ namespace Mantid /// Init common stitching inputs void initStitchingInputs(); + + /// Perform a transmission correction on the input IvsLam workspace + API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, + const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + API::MatrixWorkspace_sptr firstTransmissionRun, + OptionalMatrixWorkspace_sptr secondTransmissionRun, const OptionalDouble& stitchingStartQ, + const OptionalDouble& stitchingDeltaQ, const OptionalDouble& stitchingEndQ, + const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, + const double& wavelengthStep ); + private: /// Validate the transmission correction property inputs diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 9a35d95cb758..408bd9c0323b 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -227,108 +227,6 @@ namespace Mantid } - - /** - * Perform Transmission Corrections. - * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. - * @param wavelengthInterval : Wavelength interval for the run workspace. - * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background - * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration - * @param i0MonitorIndex : Monitor index for the I0 monitor - * @param firstTransmissionRun : The first transmission run - * @param secondTransmissionRun : The second transmission run (optional) - * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) - * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) - * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) - * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) - * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) - * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. - * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. - */ - MatrixWorkspace_sptr ReflectometryReductionOne::transmissonCorrection(MatrixWorkspace_sptr IvsLam, - const MinMax& wavelengthInterval, - const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, - const int& i0MonitorIndex, - MatrixWorkspace_sptr firstTransmissionRun, - OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, - const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, - const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, - const double& wavelengthStep - ) - { - g_log.debug("Extracting first transmission run workspace indexes from spectra"); - const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, firstTransmissionRun); - auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, wavelengthMonitorBackgroundInterval, wavelengthStep); - MatrixWorkspace_sptr trans1Detector = trans1InLam.get<0>(); - MatrixWorkspace_sptr trans1Monitor = trans1InLam.get<1>(); - - // Monitor integration ... can this happen inside the toLam routine? - auto integrationAlg = this->createChildAlgorithm("Integration"); - integrationAlg->initialize(); - integrationAlg->setProperty("InputWorkspace", trans1Monitor); - integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); - integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); - integrationAlg->execute(); - trans1Monitor = integrationAlg->getProperty("OutputWorkspace"); - - MatrixWorkspace_sptr denominator = trans1Detector / trans1Monitor; - - if (secondTransmissionRun.is_initialized()) - { - auto transRun2 = secondTransmissionRun.get(); - g_log.debug("Extracting second transmission run workspace indexes from spectra"); - const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, transRun2); - - auto trans2InLam = toLam(transRun2, detectorIndexes, i0MonitorIndex, wavelengthInterval, - wavelengthMonitorBackgroundInterval, wavelengthStep); - - // Unpack the conversion results. - MatrixWorkspace_sptr trans2Detector = trans2InLam.get<0>(); - MatrixWorkspace_sptr trans2Monitor = trans2InLam.get<1>(); - - // Monitor integration ... can this happen inside the toLam routine? - auto integrationAlg = this->createChildAlgorithm("Integration"); - integrationAlg->initialize(); - integrationAlg->setProperty("InputWorkspace", trans2Monitor); - integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); - integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); - integrationAlg->execute(); - trans2Monitor = integrationAlg->getProperty("OutputWorkspace"); - - MatrixWorkspace_sptr normalizedTrans2 = trans2Detector / trans2Monitor; - - // Stitch the results. - auto stitch1DAlg = this->createChildAlgorithm("Stitch1D"); - stitch1DAlg->initialize(); - AnalysisDataService::Instance().addOrReplace("denominator", denominator); - AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); - stitch1DAlg->setProperty("LHSWorkspace", denominator); - stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); - stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get() ); - stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get() ); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())(stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); - stitch1DAlg->setProperty("Params", params); - stitch1DAlg->execute(); - denominator = stitch1DAlg->getProperty("OutputWorkspace"); - AnalysisDataService::Instance().remove("denominator"); - AnalysisDataService::Instance().remove("normalizedTrans2"); - } - - auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); - rebinToWorkspaceAlg->initialize(); - rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); - rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); - rebinToWorkspaceAlg->execute(); - denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); - - MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; - return normalizedIvsLam; - } - /** * Correct the position of the detectors based on the input theta value. * @param toCorrect : Workspace to correct detector posisitions on. diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index d85dabbbee35..710c7f281cea 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -16,6 +16,29 @@ namespace Mantid { namespace { + /** + * Helper non-member function for translating all the workspace indexes in an origin workspace into workspace indexes + * of a host end-point workspace. This is done using spectrum numbers as the intermediate. + * + * This function will throw a runtime error if the specId are not found to exist on the host end-point workspace. + * + * @param originWS : Origin workspace, which provides the original workspace index to spectrum id mapping. + * @param hostWS : Workspace onto which the resulting workspace indexes will be hosted + * @return Remapped wokspace indexes applicable for the host workspace. + */ + ReflectometryWorkflowBase::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( + MatrixWorkspace_const_sptr originWS, MatrixWorkspace_const_sptr hostWS) + { + auto spectrumMap = originWS->getSpectrumToWorkspaceIndexMap(); + ReflectometryWorkflowBase::WorkspaceIndexList translatedIndexList; + for (auto it = spectrumMap.begin(); it != spectrumMap.end(); ++it) + { + specid_t specId = (*it).first; + translatedIndexList.push_back(static_cast(hostWS->getIndexFromSpectrumNumber(specId))); // Could be slow to do it like this. + } + return translatedIndexList; + } + /** * Helper method used with the stl to determine whether values are negative * @param value : Value to check @@ -444,5 +467,110 @@ namespace Mantid return DetectorMonitorWorkspacePair(detectorWS, monitorWS); } + + + + /** + * Perform Transmission Corrections. + * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. + * @param wavelengthInterval : Wavelength interval for the run workspace. + * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background + * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration + * @param i0MonitorIndex : Monitor index for the I0 monitor + * @param firstTransmissionRun : The first transmission run + * @param secondTransmissionRun : The second transmission run (optional) + * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) + * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) + * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. + * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::transmissonCorrection(MatrixWorkspace_sptr IvsLam, + const MinMax& wavelengthInterval, + const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, + const int& i0MonitorIndex, + MatrixWorkspace_sptr firstTransmissionRun, + OptionalMatrixWorkspace_sptr secondTransmissionRun, + const OptionalDouble& stitchingStartQ, + const OptionalDouble& stitchingDeltaQ, + const OptionalDouble& stitchingEndQ, + const OptionalDouble& stitchingStartOverlapQ, + const OptionalDouble& stitchingEndOverlapQ, + const double& wavelengthStep + ) + { + g_log.debug("Extracting first transmission run workspace indexes from spectra"); + const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, firstTransmissionRun); + auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, wavelengthMonitorBackgroundInterval, wavelengthStep); + MatrixWorkspace_sptr trans1Detector = trans1InLam.get<0>(); + MatrixWorkspace_sptr trans1Monitor = trans1InLam.get<1>(); + + // Monitor integration ... can this happen inside the toLam routine? + auto integrationAlg = this->createChildAlgorithm("Integration"); + integrationAlg->initialize(); + integrationAlg->setProperty("InputWorkspace", trans1Monitor); + integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); + integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); + integrationAlg->execute(); + trans1Monitor = integrationAlg->getProperty("OutputWorkspace"); + + MatrixWorkspace_sptr denominator = trans1Detector / trans1Monitor; + + if (secondTransmissionRun.is_initialized()) + { + auto transRun2 = secondTransmissionRun.get(); + g_log.debug("Extracting second transmission run workspace indexes from spectra"); + const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, transRun2); + + auto trans2InLam = toLam(transRun2, detectorIndexes, i0MonitorIndex, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthStep); + + // Unpack the conversion results. + MatrixWorkspace_sptr trans2Detector = trans2InLam.get<0>(); + MatrixWorkspace_sptr trans2Monitor = trans2InLam.get<1>(); + + // Monitor integration ... can this happen inside the toLam routine? + auto integrationAlg = this->createChildAlgorithm("Integration"); + integrationAlg->initialize(); + integrationAlg->setProperty("InputWorkspace", trans2Monitor); + integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); + integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); + integrationAlg->execute(); + trans2Monitor = integrationAlg->getProperty("OutputWorkspace"); + + MatrixWorkspace_sptr normalizedTrans2 = trans2Detector / trans2Monitor; + + // Stitch the results. + auto stitch1DAlg = this->createChildAlgorithm("Stitch1D"); + stitch1DAlg->initialize(); + AnalysisDataService::Instance().addOrReplace("denominator", denominator); + AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); + stitch1DAlg->setProperty("LHSWorkspace", denominator); + stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); + stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get() ); + stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get() ); + const std::vector params = boost::assign::list_of(stitchingStartQ.get())(stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + stitch1DAlg->setProperty("Params", params); + stitch1DAlg->execute(); + denominator = stitch1DAlg->getProperty("OutputWorkspace"); + AnalysisDataService::Instance().remove("denominator"); + AnalysisDataService::Instance().remove("normalizedTrans2"); + } + + auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); + rebinToWorkspaceAlg->initialize(); + rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); + rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); + rebinToWorkspaceAlg->execute(); + denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); + + // Do normalization. + MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; + return normalizedIvsLam; + } + } // namespace Algorithms } // namespace Mantid From 9833ce578e81d1a6f11ed7d1effd34b88cf772fe Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 10:11:57 +0000 Subject: [PATCH 186/403] refs #8589. Separate make transmission method. This method is used by current transmission run method, can also be used by Correction algorithm separately. --- .../ReflectometryWorkflowBase.h | 10 ++ .../src/ReflectometryReductionOne.cpp | 22 ----- .../src/ReflectometryWorkflowBase.cpp | 98 +++++++++++++------ 3 files changed, 80 insertions(+), 50 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index a4fd4e67425d..68fe2544e40b 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -84,6 +84,16 @@ namespace Mantid /// Init common stitching inputs void initStitchingInputs(); + /// Make a transmission correction workspace + API::MatrixWorkspace_sptr makeTransmissionCorrection( + const WorkspaceIndexList& detectorIndexes, const MinMax& wavelengthInterval, + const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + API::MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, + const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, + const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, + const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep); + /// Perform a transmission correction on the input IvsLam workspace API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 408bd9c0323b..cdd3ef1db1cd 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -48,28 +48,6 @@ namespace Mantid /*Anonomous namespace */ namespace { - /** - * Helper non-member function for translating all the workspace indexes in an origin workspace into workspace indexes - * of a host end-point workspace. This is done using spectrum numbers as the intermediate. - * - * This function will throw a runtime error if the specId are not found to exist on the host end-point workspace. - * - * @param originWS : Origin workspace, which provides the original workspace index to spectrum id mapping. - * @param hostWS : Workspace onto which the resulting workspace indexes will be hosted - * @return Remapped wokspace indexes applicable for the host workspace. - */ - ReflectometryWorkflowBase::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( - MatrixWorkspace_const_sptr originWS, MatrixWorkspace_const_sptr hostWS) - { - auto spectrumMap = originWS->getSpectrumToWorkspaceIndexMap(); - ReflectometryWorkflowBase::WorkspaceIndexList translatedIndexList; - for (auto it = spectrumMap.begin(); it != spectrumMap.end(); ++it) - { - specid_t specId = (*it).first; - translatedIndexList.push_back(static_cast(hostWS->getIndexFromSpectrumNumber(specId))); // Could be slow to do it like this. - } - return translatedIndexList; - } /** * Helper non-member function diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 710c7f281cea..4652b985612c 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -468,10 +468,11 @@ namespace Mantid } - - /** - * Perform Transmission Corrections. + * Create a transmission corrections workspace utilising one or two workspaces. + * + * Input workspaces are in TOF. These are converted to lambda, normalized and stitched together (if two given). + * * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. * @param wavelengthInterval : Wavelength interval for the run workspace. * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background @@ -485,9 +486,10 @@ namespace Mantid * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. - * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. + * @return A transmission workspace in Wavelength units. */ - MatrixWorkspace_sptr ReflectometryWorkflowBase::transmissonCorrection(MatrixWorkspace_sptr IvsLam, + MatrixWorkspace_sptr ReflectometryWorkflowBase::makeTransmissionCorrection( + const WorkspaceIndexList& detectorIndexes, const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, const MinMax& wavelengthMonitorIntegrationInterval, @@ -499,12 +501,10 @@ namespace Mantid const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, - const double& wavelengthStep - ) + const double& wavelengthStep) { - g_log.debug("Extracting first transmission run workspace indexes from spectra"); - const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, firstTransmissionRun); - auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, wavelengthMonitorBackgroundInterval, wavelengthStep); + auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthStep); MatrixWorkspace_sptr trans1Detector = trans1InLam.get<0>(); MatrixWorkspace_sptr trans1Monitor = trans1InLam.get<1>(); @@ -517,13 +517,14 @@ namespace Mantid integrationAlg->execute(); trans1Monitor = integrationAlg->getProperty("OutputWorkspace"); - MatrixWorkspace_sptr denominator = trans1Detector / trans1Monitor; + MatrixWorkspace_sptr transmissionWS = trans1Detector / trans1Monitor; if (secondTransmissionRun.is_initialized()) { + // TODO check that the spectra to workspace index maps match for both First and Second transmsisson runs. If they don't THROW because the detectorIndexList won't work. + auto transRun2 = secondTransmissionRun.get(); g_log.debug("Extracting second transmission run workspace indexes from spectra"); - const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, transRun2); auto trans2InLam = toLam(transRun2, detectorIndexes, i0MonitorIndex, wavelengthInterval, wavelengthMonitorBackgroundInterval, wavelengthStep); @@ -546,30 +547,71 @@ namespace Mantid // Stitch the results. auto stitch1DAlg = this->createChildAlgorithm("Stitch1D"); stitch1DAlg->initialize(); - AnalysisDataService::Instance().addOrReplace("denominator", denominator); + AnalysisDataService::Instance().addOrReplace("transmissionWS", transmissionWS); AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); - stitch1DAlg->setProperty("LHSWorkspace", denominator); + stitch1DAlg->setProperty("LHSWorkspace", transmissionWS); stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); - stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get() ); - stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get() ); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())(stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get()); + stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get()); + const std::vector params = boost::assign::list_of(stitchingStartQ.get())( + stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); stitch1DAlg->setProperty("Params", params); stitch1DAlg->execute(); - denominator = stitch1DAlg->getProperty("OutputWorkspace"); - AnalysisDataService::Instance().remove("denominator"); + transmissionWS = stitch1DAlg->getProperty("OutputWorkspace"); + AnalysisDataService::Instance().remove("transmissionWS"); AnalysisDataService::Instance().remove("normalizedTrans2"); } - auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); - rebinToWorkspaceAlg->initialize(); - rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); - rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); - rebinToWorkspaceAlg->execute(); - denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); + return transmissionWS; + } + + + /** + * Perform Transmission Corrections. + * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. + * @param wavelengthInterval : Wavelength interval for the run workspace. + * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background + * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration + * @param i0MonitorIndex : Monitor index for the I0 monitor + * @param firstTransmissionRun : The first transmission run + * @param secondTransmissionRun : The second transmission run (optional) + * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) + * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) + * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. + * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. + */ + MatrixWorkspace_sptr ReflectometryWorkflowBase::transmissonCorrection(MatrixWorkspace_sptr IvsLam, + const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, + const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, + const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, + const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep) + { + g_log.debug("Extracting first transmission run workspace indexes from spectra"); + const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, + firstTransmissionRun); + + // Make the transmission run. + MatrixWorkspace_sptr denominator = makeTransmissionCorrection(detectorIndexes, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthMonitorIntegrationInterval, i0MonitorIndex, + firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, + stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + + // Rebin the transmission run to be the same as the input. + auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); + rebinToWorkspaceAlg->initialize(); + rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); + rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); + rebinToWorkspaceAlg->execute(); + denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); - // Do normalization. - MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; - return normalizedIvsLam; + // Do normalization. + MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; + return normalizedIvsLam; } } // namespace Algorithms From c0035476bdc925d568cc4a38a51ca779ca79782d Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 11:27:59 +0000 Subject: [PATCH 187/403] refs #8589. Check spectrum numbers of input trans workspaces. Add unit tests to demonstrate happy-paths for the CreateTransmissionWorkspace alg. --- .../src/CreateTransmissionWorkspace.cpp | 13 ++- .../src/ReflectometryWorkflowBase.cpp | 15 +++- .../CreateTransmissionWorkspaceTest.py | 90 +++++++++++++++++-- .../ReflectometryReductionOneTest.py | 21 +++-- 4 files changed, 125 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index f6b84e5d80eb..a367e946fa43 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -117,9 +117,11 @@ namespace Mantid OptionalDouble stitchingStartOverlapQ; OptionalDouble stitchingEndOverlapQ; + // Get the transmission run property information. getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ); + // Get wavelength intervals. const MinMax wavelengthInterval = this->getMinMax("WavelengthMin", "WavelengthMax"); const double wavelengthStep = getProperty("WavelengthStep"); const MinMax monitorBackgroundWavelengthInterval = getMinMax("MonitorBackgroundWavelengthMin", @@ -127,11 +129,20 @@ namespace Mantid const MinMax monitorIntegrationWavelengthInterval = getMinMax("MonitorIntegrationWavelengthMin", "MonitorIntegrationWavelengthMax"); + // Get the index list const WorkspaceIndexList indexList = getWorkspaceIndexList(); + // Get the monitor i0 index const int i0MonitorIndex = getProperty("I0MonitorIndex"); - setProperty("OutputWorkspace", firstTransmissionRun.get()); + // Create the transmission workspace. + MatrixWorkspace_sptr outWS = this->makeTransmissionCorrection(indexList, wavelengthInterval, + monitorBackgroundWavelengthInterval, monitorIntegrationWavelengthInterval, i0MonitorIndex, + firstTransmissionRun.get(), secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, + stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + + + setProperty("OutputWorkspace", outWS); } } // namespace Algorithms diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 4652b985612c..19183e573248 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -272,6 +272,19 @@ namespace Mantid throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); } + if( !isPropertyDefault("SecondTransmissionRun") ) + { + MatrixWorkspace_sptr trans1 = this->getProperty("FirstTransmissionRun"); + MatrixWorkspace_sptr trans2 = this->getProperty("SecondTransmissionRun"); + + auto firstMap = trans1->getSpectrumToWorkspaceIndexMap(); + auto secondMap = trans2->getSpectrumToWorkspaceIndexMap(); + if(firstMap != secondMap) + { + throw std::invalid_argument("Spectrum maps differ between the transmission runs. They must be the same."); + } + } + } /** @@ -521,8 +534,6 @@ namespace Mantid if (secondTransmissionRun.is_initialized()) { - // TODO check that the spectra to workspace index maps match for both First and Second transmsisson runs. If they don't THROW because the detectorIndexList won't work. - auto transRun2 = secondTransmissionRun.get(); g_log.debug("Extracting second transmission run workspace indexes from spectra"); diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index a0b936e35ed3..787a91078ef8 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -1,5 +1,6 @@ import unittest -from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace +import mantid.api +from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace, Load import inspect import re @@ -127,8 +128,8 @@ def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): self.assertRaises(ValueError, alg.execute) def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, CreateTransmissionWorkspace, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, CreateTransmissionWorkspace, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + self.assertRaises(RuntimeError, CreateTransmissionWorkspace, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, CreateTransmissionWorkspace, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) def test_wavelength_min_greater_wavelength_max_throws(self): alg = self.construct_standard_algorithm() @@ -168,9 +169,88 @@ def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 self.assertRaises(ValueError, alg.execute) - def test_execute(self): + def test_spectrum_map_mismatch_throws(self): alg = self.construct_standard_algorithm() - alg.execute() + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlapQ(1) + alg.set_EndOverlapQ(2) + self.assertRaises(ValueError, alg.execute) + + DeleteWorkspace(trans_run1) + + def test_execute_one_tranmission(self): + alg = make_decorator(CreateTransmissionWorkspace) + + trans_run1 = Load('INTER00013463.nxs') + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_I0MonitorIndex(0) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(17.9) + alg.set_WavelengthStep(0.5) + alg.set_MonitorBackgroundWavelengthMin(15.0) + alg.set_MonitorBackgroundWavelengthMax(17.0) + alg.set_MonitorIntegrationWavelengthMin(4.0) + alg.set_MonitorIntegrationWavelengthMax(10.0) + + transmission_ws = alg.execute() + + self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) + + # Because we have one transmission workspaces, binning should come from the WavelengthStep. + x = transmission_ws.readX(0) + actual_binning = x[1] - x[0] + step = alg.get_WavelengthStep() + self.assertAlmostEqual( actual_binning, step, 6) + + DeleteWorkspace(trans_run1) + DeleteWorkspace(transmission_ws) + + def test_execute_two_tranmissions(self): + alg = make_decorator(CreateTransmissionWorkspace) + + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = Load('INTER00013464.nxs') + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + alg.set_I0MonitorIndex(0) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(17.9) + alg.set_WavelengthStep(0.5) + alg.set_MonitorBackgroundWavelengthMin(15.0) + alg.set_MonitorBackgroundWavelengthMax(17.0) + alg.set_MonitorIntegrationWavelengthMin(4.0) + alg.set_MonitorIntegrationWavelengthMax(10.0) + alg.set_Params([1.5, 0.02, 17]) + alg.set_StartOverlapQ( 10.0 ) + alg.set_EndOverlapQ( 12.0 ) + + transmission_ws = alg.execute() + + self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) + + # Because we have two transmission workspaces, binning should come from the Params for stitching. + x = transmission_ws.readX(0) + actual_binning = x[1] - x[0] + params = alg.get_Params() + self.assertAlmostEqual( actual_binning, params[1], 6) + self.assertAlmostEqual( 1.5, params[0], 6) + self.assertAlmostEqual( 17, params[2], 6) + + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + DeleteWorkspace(transmission_ws) if __name__ == '__main__': diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index e8da251aae62..7c52ef825e47 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -205,6 +205,7 @@ def test_point_detector_run_with_two_transmission_workspaces(self): alg.set_WorkspaceIndexList([3,4]) alg.set_FirstTransmissionRun(trans_run1) alg.set_SecondTransmissionRun(trans_run2) + alg.set_Params([1.5, 0.02, 17]) alg.set_StartOverlapQ( 10.0 ) alg.set_EndOverlapQ( 12.0 ) @@ -212,17 +213,25 @@ def test_point_detector_run_with_two_transmission_workspaces(self): out_ws_q, out_ws_lam, theta = alg.execute() - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + + def test_spectrum_map_mismatch_throws(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + self.assertRaises(ValueError, alg.execute) - self.assertEqual(2, out_ws_lam.getNumberHistograms()) DeleteWorkspace(real_run) DeleteWorkspace(trans_run1) - DeleteWorkspace(trans_run2) def test_calculate_theta(self): alg = self.construct_standard_algorithm() From ae7bab4351315de14b3a03dffade074e6e625e0a Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 11:34:42 +0000 Subject: [PATCH 188/403] refs #8589. Move trans corr to utilising algorithm class. The bit that is actually applying the trans corr is not required in the base class. --- .../ReflectometryReductionOne.h | 10 +++ .../ReflectometryWorkflowBase.h | 11 --- .../src/ReflectometryReductionOne.cpp | 72 +++++++++++++++++++ .../src/ReflectometryWorkflowBase.cpp | 71 ------------------ 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h index 4332402d1889..b890bdc7317d 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne.h @@ -74,6 +74,16 @@ namespace Mantid /// Sum spectra. Mantid::API::MatrixWorkspace_sptr sumSpectraOverRange(API::MatrixWorkspace_sptr inWS, const int startIndex, const int endIndex); + /// Perform a transmission correction on the input IvsLam workspace + API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, + const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + API::MatrixWorkspace_sptr firstTransmissionRun, + OptionalMatrixWorkspace_sptr secondTransmissionRun, const OptionalDouble& stitchingStartQ, + const OptionalDouble& stitchingDeltaQ, const OptionalDouble& stitchingEndQ, + const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, + const double& wavelengthStep ); + }; } // namespace Algorithms diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index 68fe2544e40b..f5e9b36fded6 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -94,17 +94,6 @@ namespace Mantid const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep); - - /// Perform a transmission correction on the input IvsLam workspace - API::MatrixWorkspace_sptr transmissonCorrection(API::MatrixWorkspace_sptr IvsLam, - const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, - API::MatrixWorkspace_sptr firstTransmissionRun, - OptionalMatrixWorkspace_sptr secondTransmissionRun, const OptionalDouble& stitchingStartQ, - const OptionalDouble& stitchingDeltaQ, const OptionalDouble& stitchingEndQ, - const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, - const double& wavelengthStep ); - private: /// Validate the transmission correction property inputs diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index cdd3ef1db1cd..768ca482cadb 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -48,6 +48,29 @@ namespace Mantid /*Anonomous namespace */ namespace { + /** + * Helper non-member function for translating all the workspace indexes in an origin workspace into workspace indexes + * of a host end-point workspace. This is done using spectrum numbers as the intermediate. + * + * This function will throw a runtime error if the specId are not found to exist on the host end-point workspace. + * + * @param originWS : Origin workspace, which provides the original workspace index to spectrum id mapping. + * @param hostWS : Workspace onto which the resulting workspace indexes will be hosted + * @return Remapped wokspace indexes applicable for the host workspace. + */ + ReflectometryWorkflowBase::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( + MatrixWorkspace_const_sptr originWS, MatrixWorkspace_const_sptr hostWS) + { + auto spectrumMap = originWS->getSpectrumToWorkspaceIndexMap(); + ReflectometryWorkflowBase::WorkspaceIndexList translatedIndexList; + for (auto it = spectrumMap.begin(); it != spectrumMap.end(); ++it) + { + specid_t specId = (*it).first; + translatedIndexList.push_back(static_cast(hostWS->getIndexFromSpectrumNumber(specId))); // Could be slow to do it like this. + } + return translatedIndexList; + } + /** * Helper non-member function @@ -467,5 +490,54 @@ namespace Mantid } + + /** + * Perform Transmission Corrections. + * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. + * @param wavelengthInterval : Wavelength interval for the run workspace. + * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background + * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration + * @param i0MonitorIndex : Monitor index for the I0 monitor + * @param firstTransmissionRun : The first transmission run + * @param secondTransmissionRun : The second transmission run (optional) + * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) + * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) + * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. + * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. + */ + MatrixWorkspace_sptr ReflectometryReductionOne::transmissonCorrection(MatrixWorkspace_sptr IvsLam, + const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, + const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, + const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, + const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep) + { + g_log.debug("Extracting first transmission run workspace indexes from spectra"); + const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, + firstTransmissionRun); + + // Make the transmission run. + MatrixWorkspace_sptr denominator = makeTransmissionCorrection(detectorIndexes, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthMonitorIntegrationInterval, i0MonitorIndex, + firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, + stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + + // Rebin the transmission run to be the same as the input. + auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); + rebinToWorkspaceAlg->initialize(); + rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); + rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); + rebinToWorkspaceAlg->execute(); + denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); + + // Do normalization. + MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; + return normalizedIvsLam; + } + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 19183e573248..4c71e133e82f 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -16,28 +16,6 @@ namespace Mantid { namespace { - /** - * Helper non-member function for translating all the workspace indexes in an origin workspace into workspace indexes - * of a host end-point workspace. This is done using spectrum numbers as the intermediate. - * - * This function will throw a runtime error if the specId are not found to exist on the host end-point workspace. - * - * @param originWS : Origin workspace, which provides the original workspace index to spectrum id mapping. - * @param hostWS : Workspace onto which the resulting workspace indexes will be hosted - * @return Remapped wokspace indexes applicable for the host workspace. - */ - ReflectometryWorkflowBase::WorkspaceIndexList createWorkspaceIndexListFromDetectorWorkspace( - MatrixWorkspace_const_sptr originWS, MatrixWorkspace_const_sptr hostWS) - { - auto spectrumMap = originWS->getSpectrumToWorkspaceIndexMap(); - ReflectometryWorkflowBase::WorkspaceIndexList translatedIndexList; - for (auto it = spectrumMap.begin(); it != spectrumMap.end(); ++it) - { - specid_t specId = (*it).first; - translatedIndexList.push_back(static_cast(hostWS->getIndexFromSpectrumNumber(specId))); // Could be slow to do it like this. - } - return translatedIndexList; - } /** * Helper method used with the stl to determine whether values are negative @@ -576,54 +554,5 @@ namespace Mantid return transmissionWS; } - - /** - * Perform Transmission Corrections. - * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. - * @param wavelengthInterval : Wavelength interval for the run workspace. - * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background - * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration - * @param i0MonitorIndex : Monitor index for the I0 monitor - * @param firstTransmissionRun : The first transmission run - * @param secondTransmissionRun : The second transmission run (optional) - * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) - * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) - * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) - * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) - * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) - * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. - * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. - */ - MatrixWorkspace_sptr ReflectometryWorkflowBase::transmissonCorrection(MatrixWorkspace_sptr IvsLam, - const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, - MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep) - { - g_log.debug("Extracting first transmission run workspace indexes from spectra"); - const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, - firstTransmissionRun); - - // Make the transmission run. - MatrixWorkspace_sptr denominator = makeTransmissionCorrection(detectorIndexes, wavelengthInterval, - wavelengthMonitorBackgroundInterval, wavelengthMonitorIntegrationInterval, i0MonitorIndex, - firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, - stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); - - // Rebin the transmission run to be the same as the input. - auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); - rebinToWorkspaceAlg->initialize(); - rebinToWorkspaceAlg->setProperty("WorkspaceToMatch", IvsLam); - rebinToWorkspaceAlg->setProperty("WorkspaceToRebin", denominator); - rebinToWorkspaceAlg->execute(); - denominator = rebinToWorkspaceAlg->getProperty("OutputWorkspace"); - - // Do normalization. - MatrixWorkspace_sptr normalizedIvsLam = IvsLam / denominator; - return normalizedIvsLam; - } - } // namespace Algorithms } // namespace Mantid From 6f05e9ce12f01cc740fdfbc403f8af7a91a78ad2 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 12:06:33 +0000 Subject: [PATCH 189/403] refs #8589. Call make transmission via algorithm. This is a better strategy particularly when nested histories become possible. --- .../src/ReflectometryReductionOne.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 768ca482cadb..7e9a31749387 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -520,11 +520,37 @@ namespace Mantid const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, firstTransmissionRun); + // Make the transmission run. + auto alg = this->createChildAlgorithm("CreateTransmissionWorkspace"); + alg->initialize(); + alg->setProperty("FirstTransmissionRun", firstTransmissionRun); + if(secondTransmissionRun.is_initialized()) + { + alg->setProperty("SecondTransmissionRun", secondTransmissionRun.get()); + const std::vector params = boost::assign::list_of(stitchingStartQ.get())(stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + alg->setProperty("Params", params); + alg->setProperty("StartOverlapQ", stitchingStartOverlapQ.get()); + alg->setProperty("EndOverlapQ", stitchingEndOverlapQ.get()); + } + alg->setProperty("WorkspaceIndexList", detectorIndexes); + alg->setProperty("I0MonitorIndex", i0MonitorIndex); + alg->setProperty("WavelengthMin", wavelengthInterval.get<0>()); + alg->setProperty("WavelengthMax", wavelengthInterval.get<1>()); + alg->setProperty("WavelengthStep", wavelengthStep); + alg->setProperty("MonitorBackgroundWavelengthMin", wavelengthMonitorBackgroundInterval.get<0>()); + alg->setProperty("MonitorBackgroundWavelengthMax", wavelengthMonitorBackgroundInterval.get<1>()); + alg->setProperty("MonitorIntegrationWavelengthMin", wavelengthMonitorIntegrationInterval.get<0>()); + alg->setProperty("MonitorIntegrationWavelengthMax", wavelengthMonitorIntegrationInterval.get<1>()); + alg->execute(); + MatrixWorkspace_sptr denominator = alg->getProperty("OutputWorkspace"); + + /* // Make the transmission run. MatrixWorkspace_sptr denominator = makeTransmissionCorrection(detectorIndexes, wavelengthInterval, wavelengthMonitorBackgroundInterval, wavelengthMonitorIntegrationInterval, i0MonitorIndex, firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + */ // Rebin the transmission run to be the same as the input. auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); From e63d50f4cf3a9590d31fca12cd37ca51d4227bbb Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 12 Dec 2013 12:12:09 +0000 Subject: [PATCH 190/403] refs #8589. Make transmission runs not needed on base. Make transmission runs can be private to the creation algorithm now that the workflow algorithm is calling the creational algorithm rather than using a shared method on the base class. --- .../CreateTransmissionWorkspace.h | 77 ++++++++------- .../ReflectometryWorkflowBase.h | 10 -- .../src/CreateTransmissionWorkspace.cpp | 98 +++++++++++++++++++ .../src/ReflectometryReductionOne.cpp | 8 -- .../src/ReflectometryWorkflowBase.cpp | 96 ------------------ 5 files changed, 141 insertions(+), 148 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h index ae7860037086..965a2aa15694 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CreateTransmissionWorkspace.h @@ -6,51 +6,60 @@ namespace Mantid { -namespace Algorithms -{ + namespace Algorithms + { - /** CreateTransmissionWorkspace : Create a transmission run workspace in Wavelength given one or more TOF workspaces - - Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + /** CreateTransmissionWorkspace : Create a transmission run workspace in Wavelength given one or more TOF workspaces - This file is part of Mantid. + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + This file is part of Mantid. - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - File change history is stored at: - Code Documentation is available at: - */ - class DLLExport CreateTransmissionWorkspace : public ReflectometryWorkflowBase - { - public: - CreateTransmissionWorkspace(); - virtual ~CreateTransmissionWorkspace(); - - virtual const std::string name() const; - virtual int version() const; - virtual const std::string category() const; + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport CreateTransmissionWorkspace: public ReflectometryWorkflowBase + { + public: + CreateTransmissionWorkspace(); + virtual ~CreateTransmissionWorkspace(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; - private: - virtual void initDocs(); - void init(); - void exec(); + private: + /// Make a transmission correction workspace + API::MatrixWorkspace_sptr makeTransmissionCorrection(const WorkspaceIndexList& detectorIndexes, + const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, + API::MatrixWorkspace_sptr firstTransmissionRun, + OptionalMatrixWorkspace_sptr secondTransmissionRun, const OptionalDouble& stitchingStartQ, + const OptionalDouble& stitchingDeltaQ, const OptionalDouble& stitchingEndQ, + const OptionalDouble& stitchingStartOverlapQ, const OptionalDouble& stitchingEndOverlapQ, + const double& wavelengthStep); - }; + virtual void initDocs(); + void init(); + void exec(); + }; -} // namespace Algorithms + } // namespace Algorithms } // namespace Mantid #endif /* MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACE_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index f5e9b36fded6..6b0e685f0ddc 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -84,16 +84,6 @@ namespace Mantid /// Init common stitching inputs void initStitchingInputs(); - /// Make a transmission correction workspace - API::MatrixWorkspace_sptr makeTransmissionCorrection( - const WorkspaceIndexList& detectorIndexes, const MinMax& wavelengthInterval, - const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, - API::MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep); - private: /// Validate the transmission correction property inputs diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index a367e946fa43..0e44c62cbeba 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -12,6 +12,7 @@ #include "MantidKernel/RebinParamsValidator.h" #include "MantidKernel/BoundedValidator.h" #include +#include using namespace Mantid::Kernel; using namespace Mantid::API; @@ -145,5 +146,102 @@ namespace Mantid setProperty("OutputWorkspace", outWS); } + + + /** + * Create a transmission corrections workspace utilising one or two workspaces. + * + * Input workspaces are in TOF. These are converted to lambda, normalized and stitched together (if two given). + * + * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. + * @param wavelengthInterval : Wavelength interval for the run workspace. + * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background + * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration + * @param i0MonitorIndex : Monitor index for the I0 monitor + * @param firstTransmissionRun : The first transmission run + * @param secondTransmissionRun : The second transmission run (optional) + * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) + * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) + * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. + * @return A transmission workspace in Wavelength units. + */ + MatrixWorkspace_sptr CreateTransmissionWorkspace::makeTransmissionCorrection( + const WorkspaceIndexList& detectorIndexes, + const MinMax& wavelengthInterval, + const MinMax& wavelengthMonitorBackgroundInterval, + const MinMax& wavelengthMonitorIntegrationInterval, + const int& i0MonitorIndex, + MatrixWorkspace_sptr firstTransmissionRun, + OptionalMatrixWorkspace_sptr secondTransmissionRun, + const OptionalDouble& stitchingStartQ, + const OptionalDouble& stitchingDeltaQ, + const OptionalDouble& stitchingEndQ, + const OptionalDouble& stitchingStartOverlapQ, + const OptionalDouble& stitchingEndOverlapQ, + const double& wavelengthStep) + { + auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthStep); + MatrixWorkspace_sptr trans1Detector = trans1InLam.get<0>(); + MatrixWorkspace_sptr trans1Monitor = trans1InLam.get<1>(); + + // Monitor integration ... can this happen inside the toLam routine? + auto integrationAlg = this->createChildAlgorithm("Integration"); + integrationAlg->initialize(); + integrationAlg->setProperty("InputWorkspace", trans1Monitor); + integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); + integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); + integrationAlg->execute(); + trans1Monitor = integrationAlg->getProperty("OutputWorkspace"); + + MatrixWorkspace_sptr transmissionWS = trans1Detector / trans1Monitor; + + if (secondTransmissionRun.is_initialized()) + { + auto transRun2 = secondTransmissionRun.get(); + g_log.debug("Extracting second transmission run workspace indexes from spectra"); + + auto trans2InLam = toLam(transRun2, detectorIndexes, i0MonitorIndex, wavelengthInterval, + wavelengthMonitorBackgroundInterval, wavelengthStep); + + // Unpack the conversion results. + MatrixWorkspace_sptr trans2Detector = trans2InLam.get<0>(); + MatrixWorkspace_sptr trans2Monitor = trans2InLam.get<1>(); + + // Monitor integration ... can this happen inside the toLam routine? + auto integrationAlg = this->createChildAlgorithm("Integration"); + integrationAlg->initialize(); + integrationAlg->setProperty("InputWorkspace", trans2Monitor); + integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); + integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); + integrationAlg->execute(); + trans2Monitor = integrationAlg->getProperty("OutputWorkspace"); + + MatrixWorkspace_sptr normalizedTrans2 = trans2Detector / trans2Monitor; + + // Stitch the results. + auto stitch1DAlg = this->createChildAlgorithm("Stitch1D"); + stitch1DAlg->initialize(); + AnalysisDataService::Instance().addOrReplace("transmissionWS", transmissionWS); + AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); + stitch1DAlg->setProperty("LHSWorkspace", transmissionWS); + stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); + stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get()); + stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get()); + const std::vector params = boost::assign::list_of(stitchingStartQ.get())( + stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + stitch1DAlg->setProperty("Params", params); + stitch1DAlg->execute(); + transmissionWS = stitch1DAlg->getProperty("OutputWorkspace"); + AnalysisDataService::Instance().remove("transmissionWS"); + AnalysisDataService::Instance().remove("normalizedTrans2"); + } + + return transmissionWS; + } + } // namespace Algorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 7e9a31749387..06847c2de3f8 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -544,14 +544,6 @@ namespace Mantid alg->execute(); MatrixWorkspace_sptr denominator = alg->getProperty("OutputWorkspace"); - /* - // Make the transmission run. - MatrixWorkspace_sptr denominator = makeTransmissionCorrection(detectorIndexes, wavelengthInterval, - wavelengthMonitorBackgroundInterval, wavelengthMonitorIntegrationInterval, i0MonitorIndex, - firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, - stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); - */ - // Rebin the transmission run to be the same as the input. auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); rebinToWorkspaceAlg->initialize(); diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 4c71e133e82f..be9f0895a3b3 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -458,101 +458,5 @@ namespace Mantid return DetectorMonitorWorkspacePair(detectorWS, monitorWS); } - - /** - * Create a transmission corrections workspace utilising one or two workspaces. - * - * Input workspaces are in TOF. These are converted to lambda, normalized and stitched together (if two given). - * - * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. - * @param wavelengthInterval : Wavelength interval for the run workspace. - * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background - * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration - * @param i0MonitorIndex : Monitor index for the I0 monitor - * @param firstTransmissionRun : The first transmission run - * @param secondTransmissionRun : The second transmission run (optional) - * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) - * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) - * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) - * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) - * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) - * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. - * @return A transmission workspace in Wavelength units. - */ - MatrixWorkspace_sptr ReflectometryWorkflowBase::makeTransmissionCorrection( - const WorkspaceIndexList& detectorIndexes, - const MinMax& wavelengthInterval, - const MinMax& wavelengthMonitorBackgroundInterval, - const MinMax& wavelengthMonitorIntegrationInterval, - const int& i0MonitorIndex, - MatrixWorkspace_sptr firstTransmissionRun, - OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, - const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, - const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, - const double& wavelengthStep) - { - auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, - wavelengthMonitorBackgroundInterval, wavelengthStep); - MatrixWorkspace_sptr trans1Detector = trans1InLam.get<0>(); - MatrixWorkspace_sptr trans1Monitor = trans1InLam.get<1>(); - - // Monitor integration ... can this happen inside the toLam routine? - auto integrationAlg = this->createChildAlgorithm("Integration"); - integrationAlg->initialize(); - integrationAlg->setProperty("InputWorkspace", trans1Monitor); - integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); - integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); - integrationAlg->execute(); - trans1Monitor = integrationAlg->getProperty("OutputWorkspace"); - - MatrixWorkspace_sptr transmissionWS = trans1Detector / trans1Monitor; - - if (secondTransmissionRun.is_initialized()) - { - auto transRun2 = secondTransmissionRun.get(); - g_log.debug("Extracting second transmission run workspace indexes from spectra"); - - auto trans2InLam = toLam(transRun2, detectorIndexes, i0MonitorIndex, wavelengthInterval, - wavelengthMonitorBackgroundInterval, wavelengthStep); - - // Unpack the conversion results. - MatrixWorkspace_sptr trans2Detector = trans2InLam.get<0>(); - MatrixWorkspace_sptr trans2Monitor = trans2InLam.get<1>(); - - // Monitor integration ... can this happen inside the toLam routine? - auto integrationAlg = this->createChildAlgorithm("Integration"); - integrationAlg->initialize(); - integrationAlg->setProperty("InputWorkspace", trans2Monitor); - integrationAlg->setProperty("RangeLower", wavelengthMonitorIntegrationInterval.get<0>()); - integrationAlg->setProperty("RangeUpper", wavelengthMonitorIntegrationInterval.get<1>()); - integrationAlg->execute(); - trans2Monitor = integrationAlg->getProperty("OutputWorkspace"); - - MatrixWorkspace_sptr normalizedTrans2 = trans2Detector / trans2Monitor; - - // Stitch the results. - auto stitch1DAlg = this->createChildAlgorithm("Stitch1D"); - stitch1DAlg->initialize(); - AnalysisDataService::Instance().addOrReplace("transmissionWS", transmissionWS); - AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); - stitch1DAlg->setProperty("LHSWorkspace", transmissionWS); - stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); - stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get()); - stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get()); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())( - stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); - stitch1DAlg->setProperty("Params", params); - stitch1DAlg->execute(); - transmissionWS = stitch1DAlg->getProperty("OutputWorkspace"); - AnalysisDataService::Instance().remove("transmissionWS"); - AnalysisDataService::Instance().remove("normalizedTrans2"); - } - - return transmissionWS; - } - } // namespace Algorithms } // namespace Mantid From 772363c95337f00ef53729b5d829d304b4f445d0 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Fri, 13 Dec 2013 09:35:31 +0000 Subject: [PATCH 191/403] refs #8589. Use rather than make transmission workspaces. Use rather than make a transmission workspace if the units are in wavelength. --- .../ReflectometryWorkflowBase.h | 5 +- .../src/ReflectometryReductionOne.cpp | 56 +++++++++++-------- .../src/ReflectometryWorkflowBase.cpp | 37 +++++++++++- .../ReflectometryReductionOneTest.py | 2 +- 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index 6b0e685f0ddc..ca6e49198da5 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -87,7 +87,10 @@ namespace Mantid private: /// Validate the transmission correction property inputs - void validateTransmissionInputs() const; + void validateSecondTransmissionInputs(const bool firstTransmissionInWavelength) const; + + /// Validate the the first transmission workspace. + bool validateFirstTransmissionInputs() const; /// Convert the monitor parts of the input workspace to wavelength API::MatrixWorkspace_sptr toLamMonitor(const API::MatrixWorkspace_sptr& toConvert, diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 06847c2de3f8..d3fd6bc6b641 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -98,6 +98,8 @@ namespace Mantid const std::string multiDetectorAnalysis = "MultiDetectorAnalysis"; const std::string pointDetectorAnalysis = "PointDetectorAnalysis"; + const std::string tofUnitId = "TOF"; + const std::string wavelengthUnitId = "Wavelength"; } /* End of ananomous namespace */ @@ -196,7 +198,7 @@ namespace Mantid declareProperty( new WorkspaceProperty("FirstTransmissionRun", "", Direction::Input, - PropertyMode::Optional, inputValidator->clone()), + PropertyMode::Optional), "First transmission run, or the low wavelength transmision run if SecondTransmissionRun is also provided."); declareProperty( new WorkspaceProperty("SecondTransmissionRun", "", Direction::Input, @@ -520,29 +522,39 @@ namespace Mantid const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, firstTransmissionRun); - // Make the transmission run. - auto alg = this->createChildAlgorithm("CreateTransmissionWorkspace"); - alg->initialize(); - alg->setProperty("FirstTransmissionRun", firstTransmissionRun); - if(secondTransmissionRun.is_initialized()) + // TODO if firstInputWorkspace is in wavelength, do not create the transmission workspace, just do the division. + + MatrixWorkspace_sptr denominator = firstTransmissionRun; + Unit_const_sptr xUnit = firstTransmissionRun->getAxis(0)->unit(); + if (xUnit->unitID() == tofUnitId) { - alg->setProperty("SecondTransmissionRun", secondTransmissionRun.get()); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())(stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); - alg->setProperty("Params", params); - alg->setProperty("StartOverlapQ", stitchingStartOverlapQ.get()); - alg->setProperty("EndOverlapQ", stitchingEndOverlapQ.get()); + // Make the transmission run. + auto alg = this->createChildAlgorithm("CreateTransmissionWorkspace"); + alg->initialize(); + alg->setProperty("FirstTransmissionRun", firstTransmissionRun); + if (secondTransmissionRun.is_initialized()) + { + alg->setProperty("SecondTransmissionRun", secondTransmissionRun.get()); + const std::vector params = boost::assign::list_of(stitchingStartQ.get())( + stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + alg->setProperty("Params", params); + alg->setProperty("StartOverlapQ", stitchingStartOverlapQ.get()); + alg->setProperty("EndOverlapQ", stitchingEndOverlapQ.get()); + } + alg->setProperty("WorkspaceIndexList", detectorIndexes); + alg->setProperty("I0MonitorIndex", i0MonitorIndex); + alg->setProperty("WavelengthMin", wavelengthInterval.get<0>()); + alg->setProperty("WavelengthMax", wavelengthInterval.get<1>()); + alg->setProperty("WavelengthStep", wavelengthStep); + alg->setProperty("MonitorBackgroundWavelengthMin", wavelengthMonitorBackgroundInterval.get<0>()); + alg->setProperty("MonitorBackgroundWavelengthMax", wavelengthMonitorBackgroundInterval.get<1>()); + alg->setProperty("MonitorIntegrationWavelengthMin", + wavelengthMonitorIntegrationInterval.get<0>()); + alg->setProperty("MonitorIntegrationWavelengthMax", + wavelengthMonitorIntegrationInterval.get<1>()); + alg->execute(); + denominator = alg->getProperty("OutputWorkspace"); } - alg->setProperty("WorkspaceIndexList", detectorIndexes); - alg->setProperty("I0MonitorIndex", i0MonitorIndex); - alg->setProperty("WavelengthMin", wavelengthInterval.get<0>()); - alg->setProperty("WavelengthMax", wavelengthInterval.get<1>()); - alg->setProperty("WavelengthStep", wavelengthStep); - alg->setProperty("MonitorBackgroundWavelengthMin", wavelengthMonitorBackgroundInterval.get<0>()); - alg->setProperty("MonitorBackgroundWavelengthMax", wavelengthMonitorBackgroundInterval.get<1>()); - alg->setProperty("MonitorIntegrationWavelengthMin", wavelengthMonitorIntegrationInterval.get<0>()); - alg->setProperty("MonitorIntegrationWavelengthMax", wavelengthMonitorIntegrationInterval.get<1>()); - alg->execute(); - MatrixWorkspace_sptr denominator = alg->getProperty("OutputWorkspace"); // Rebin the transmission run to be the same as the input. auto rebinToWorkspaceAlg = this->createChildAlgorithm("RebinToWorkspace"); diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index be9f0895a3b3..572767cb77b6 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -216,17 +216,47 @@ namespace Mantid return MinMax(min, max); } + /** + * Check the first transmission run units. + * + * @return True only if the units of the first transmission run are in wavelength. + * + */ + bool ReflectometryWorkflowBase::validateFirstTransmissionInputs() const + { + WorkspaceUnitValidator tofValidator("TOF"); + WorkspaceUnitValidator wavelengthValidator("Wavelength"); + MatrixWorkspace_sptr firstTransmissionRun = this->getProperty("FirstTransmissionRun"); + if (!tofValidator.isValid(firstTransmissionRun).empty() + && !wavelengthValidator.isValid(firstTransmissionRun).empty()) + { + throw std::invalid_argument("FirstTransmissionRun must be either in TOF or Wavelength"); + } + + const bool bInWavelength = (!wavelengthValidator.isValid(firstTransmissionRun).empty()); + return bInWavelength; + } + /** * Validate the transmission workspace inputs when a second transmission run is provided. * Throws if any of the property values do not make sense. + * @param firstTransmissionInWavelength: Indicates that the first transmission run is in units of wavlength. */ - void ReflectometryWorkflowBase::validateTransmissionInputs() const + void ReflectometryWorkflowBase::validateSecondTransmissionInputs(const bool firstTransmissionInWavelength) const { // Verify that all the required inputs for the second transmission run are now given. if (isPropertyDefault("FirstTransmissionRun")) { throw std::invalid_argument( "A SecondTransmissionRun is only valid if a FirstTransmissionRun is provided."); + if (firstTransmissionInWavelength) + { + this->g_log.warning( + "The first transmission run is in wavelength so is assumed to be correctly stitched in wavelength. " + "The second transmission run and associated inputs will be ignored." + "Run CreateTransmissionWorkspace to create a transmission workspace from TOF runs."); + return; + } } if (isPropertyDefault("Params")) { @@ -283,8 +313,11 @@ namespace Mantid OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const { + bool bFirstTransInWavelength = false; if (!isPropertyDefault("FirstTransmissionRun")) { + bFirstTransInWavelength = validateFirstTransmissionInputs(); + MatrixWorkspace_sptr temp = this->getProperty("FirstTransmissionRun"); firstTransmissionRun = temp; } @@ -292,7 +325,7 @@ namespace Mantid if (!isPropertyDefault("SecondTransmissionRun")) { // Check that the property values provided make sense together. - validateTransmissionInputs(); + validateSecondTransmissionInputs(bFirstTransInWavelength); // Set the values. { diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index 7c52ef825e47..150cab2109a2 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -36,7 +36,7 @@ def test_check_input_workpace_not_tof_throws(self): alg.set_InputWorkspace(self.__not_tof) self.assertRaises(ValueError, alg.execute) - def test_check_first_transmission_workspace_not_tof_throws(self): + def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): alg = self.construct_standard_algorithm() alg.set_FirstTransmissionRun(self.__not_tof) self.assertRaises(ValueError, alg.execute) From 19f56949194af1749d233e189fb49d4a69a59dee Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Fri, 13 Dec 2013 09:40:22 +0000 Subject: [PATCH 192/403] refs #8589. Remove unused test files. --- .../Framework/Algorithms/CMakeLists.txt | 1 - .../test/CreateTransmissionWorkspaceTest.h | 38 ------------------- 2 files changed, 39 deletions(-) delete mode 100644 Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index bea0d1e11a91..82a22cf9a427 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -520,7 +520,6 @@ set ( TEST_FILES CreatePSDBleedMaskTest.h CreatePeaksWorkspaceTest.h CreateSingleValuedWorkspaceTest.h - CreateTransmissionWorkspaceTest.h CreateWorkspaceTest.h CropWorkspaceTest.h CuboidGaugeVolumeAbsorptionTest.h diff --git a/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h b/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h deleted file mode 100644 index 9a7711d0ece8..000000000000 --- a/Code/Mantid/Framework/Algorithms/test/CreateTransmissionWorkspaceTest.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ -#define MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ - -#include - -#include "MantidAlgorithms/CreateTransmissionWorkspace.h" - -using Mantid::Algorithms::CreateTransmissionWorkspace; - -class CreateTransmissionWorkspaceTest : public CxxTest::TestSuite -{ -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static CreateTransmissionWorkspaceTest *createSuite() { return new CreateTransmissionWorkspaceTest(); } - static void destroySuite( CreateTransmissionWorkspaceTest *suite ) { delete suite; } - - - void test_Init() - { - CreateTransmissionWorkspace alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - } - - void test_exec() - { - } - - void test_Something() - { - } - - -}; - - -#endif /* MANTID_ALGORITHMS_CREATETRANSMISSIONWORKSPACETEST_H_ */ From d05a1240d3c2bdbb71a533609d3990a18ffcb93c Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Fri, 13 Dec 2013 10:00:48 +0000 Subject: [PATCH 193/403] refs #8589. Improve documentation where possible. --- .../Framework/Algorithms/src/ReflectometryReductionOne.cpp | 2 +- .../Framework/Algorithms/src/ReflectometryWorkflowBase.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index d3fd6bc6b641..a499d3315cbf 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -156,7 +156,7 @@ namespace Mantid void ReflectometryReductionOne::init() { boost::shared_ptr inputValidator = boost::make_shared(); - inputValidator->add(boost::make_shared("TOF")); + inputValidator->add(boost::make_shared(tofUnitId)); declareProperty( new WorkspaceProperty("InputWorkspace", "", Direction::Input, inputValidator), diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 572767cb77b6..e940cd9559c7 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -43,7 +43,7 @@ namespace Mantid } /** - * + * Init index properties. */ void ReflectometryWorkflowBase::initIndexInputs() { @@ -65,7 +65,7 @@ namespace Mantid } /** - * Init common wavlength inputs. + * Init common wavelength inputs. */ void ReflectometryWorkflowBase::initWavelengthInputs() { @@ -104,6 +104,9 @@ namespace Mantid "Wavelength maximum for integration in angstroms."); } + /** + * Init stitching inputs + */ void ReflectometryWorkflowBase::initStitchingInputs() { declareProperty( From fe9ac6f1f913b5ce9c075658a205f0b6c95809c1 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Fri, 13 Dec 2013 11:18:03 +0000 Subject: [PATCH 194/403] refs #8589. Bad property names. Stitching is actually happening with workspaces in wavelength not in Q. Parameter names and documentation needs to reflect this. --- .../ReflectometryWorkflowBase.h | 6 +- .../src/CreateTransmissionWorkspace.cpp | 50 ++++++------ .../src/ReflectometryReductionOne.cpp | 46 +++++------ .../src/ReflectometryWorkflowBase.cpp | 52 ++++++------- .../CreateTransmissionWorkspaceTest.py | 77 +++---------------- .../ReflectometryReductionOneTest.py | 12 +-- 6 files changed, 92 insertions(+), 151 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h index ca6e49198da5..5b81afd47ce9 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase.h @@ -73,9 +73,9 @@ namespace Mantid /// Get the transmission correction properties void getTransmissionRunInfo(OptionalMatrixWorkspace_sptr& firstTransmissionRun, - OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, - OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, - OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const; + OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStart, + OptionalDouble& stitchingDelta, OptionalDouble& stitchingEnd, + OptionalDouble& stitchingStartOverlap, OptionalDouble& stitchingEndOverlap) const; /// Init common index inputs void initIndexInputs(); diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index 0e44c62cbeba..5678f0c86bbd 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -97,10 +97,10 @@ namespace Mantid setPropertySettings("Params", new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); - setPropertySettings("StartOverlapQ", + setPropertySettings("StartOverlap", new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); - setPropertySettings("EndOverlapQ", + setPropertySettings("EndOverlap", new Kernel::EnabledWhenProperty("SecondTransmissionWorkspace", IS_NOT_DEFAULT)); } @@ -112,15 +112,15 @@ namespace Mantid { OptionalMatrixWorkspace_sptr firstTransmissionRun; OptionalMatrixWorkspace_sptr secondTransmissionRun; - OptionalDouble stitchingStartQ; - OptionalDouble stitchingDeltaQ; - OptionalDouble stitchingEndQ; - OptionalDouble stitchingStartOverlapQ; - OptionalDouble stitchingEndOverlapQ; + OptionalDouble stitchingStart; + OptionalDouble stitchingDelta; + OptionalDouble stitchingEnd; + OptionalDouble stitchingStartOverlap; + OptionalDouble stitchingEndOverlap; // Get the transmission run property information. - getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStartQ, - stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ); + getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStart, + stitchingDelta, stitchingEnd, stitchingStartOverlap, stitchingEndOverlap); // Get wavelength intervals. const MinMax wavelengthInterval = this->getMinMax("WavelengthMin", "WavelengthMax"); @@ -139,8 +139,8 @@ namespace Mantid // Create the transmission workspace. MatrixWorkspace_sptr outWS = this->makeTransmissionCorrection(indexList, wavelengthInterval, monitorBackgroundWavelengthInterval, monitorIntegrationWavelengthInterval, i0MonitorIndex, - firstTransmissionRun.get(), secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, - stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + firstTransmissionRun.get(), secondTransmissionRun, stitchingStart, stitchingDelta, stitchingEnd, + stitchingStartOverlap, stitchingEndOverlap, wavelengthStep); setProperty("OutputWorkspace", outWS); @@ -160,11 +160,11 @@ namespace Mantid * @param i0MonitorIndex : Monitor index for the I0 monitor * @param firstTransmissionRun : The first transmission run * @param secondTransmissionRun : The second transmission run (optional) - * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) - * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) - * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) - * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) - * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingStart : Stitching start (optional but dependent on secondTransmissionRun) + * @param stitchingDelta : Stitching delta (optional but dependent on secondTransmissionRun) + * @param stitchingEnd : Stitching end (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlap : Stitching start overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlap : Stitching end overlap (optional but dependent on secondTransmissionRun) * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. * @return A transmission workspace in Wavelength units. */ @@ -176,11 +176,11 @@ namespace Mantid const int& i0MonitorIndex, MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, - const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, - const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, + const OptionalDouble& stitchingStart, + const OptionalDouble& stitchingDelta, + const OptionalDouble& stitchingEnd, + const OptionalDouble& stitchingStartOverlap, + const OptionalDouble& stitchingEndOverlap, const double& wavelengthStep) { auto trans1InLam = toLam(firstTransmissionRun, detectorIndexes, i0MonitorIndex, wavelengthInterval, @@ -229,10 +229,10 @@ namespace Mantid AnalysisDataService::Instance().addOrReplace("normalizedTrans2", normalizedTrans2); stitch1DAlg->setProperty("LHSWorkspace", transmissionWS); stitch1DAlg->setProperty("RHSWorkspace", normalizedTrans2); - stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlapQ.get()); - stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlapQ.get()); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())( - stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + stitch1DAlg->setProperty("StartOverlap", stitchingStartOverlap.get()); + stitch1DAlg->setProperty("EndOverlap", stitchingEndOverlap.get()); + const std::vector params = boost::assign::list_of(stitchingStart.get())( + stitchingDelta.get())(stitchingEnd.get()).convert_to_container >(); stitch1DAlg->setProperty("Params", params); stitch1DAlg->execute(); transmissionWS = stitch1DAlg->getProperty("OutputWorkspace"); diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index a499d3315cbf..02d788913448 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -210,15 +210,15 @@ namespace Mantid setPropertyGroup("FirstTransmissionRun", "Transmission"); setPropertyGroup("SecondTransmissionRun", "Transmission"); setPropertyGroup("Params", "Transmission"); - setPropertyGroup("StartOverlapQ", "Transmission"); - setPropertyGroup("EndOverlapQ", "Transmission"); + setPropertyGroup("StartOverlap", "Transmission"); + setPropertyGroup("EndOverlap", "Transmission"); // Only do transmission corrections when point detector. setPropertySettings("FirstTransmissionRun", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); setPropertySettings("SecondTransmissionRun", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); setPropertySettings("Params", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); - setPropertySettings("StartOverlapQ", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); - setPropertySettings("EndOverlapQ", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); + setPropertySettings("StartOverlap", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); + setPropertySettings("EndOverlap", new Kernel::EnabledWhenProperty("AnalysisMode", IS_EQUAL_TO, "PointDetectorAnalysis")); // Only use region of interest when in multi-detector analysis mode setPropertySettings("RegionOfInterest", @@ -395,13 +395,13 @@ namespace Mantid OptionalMatrixWorkspace_sptr firstTransmissionRun; OptionalMatrixWorkspace_sptr secondTransmissionRun; - OptionalDouble stitchingStartQ; - OptionalDouble stitchingDeltaQ; - OptionalDouble stitchingEndQ; - OptionalDouble stitchingStartOverlapQ; - OptionalDouble stitchingEndOverlapQ; + OptionalDouble stitchingStart; + OptionalDouble stitchingDelta; + OptionalDouble stitchingEnd; + OptionalDouble stitchingStartOverlap; + OptionalDouble stitchingEndOverlap; - getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ); + getTransmissionRunInfo(firstTransmissionRun, secondTransmissionRun, stitchingStart, stitchingDelta, stitchingEnd, stitchingStartOverlap, stitchingEndOverlap); OptionalDouble theta; if (!isPropertyDefault("ThetaIn")) @@ -457,7 +457,7 @@ namespace Mantid // Perform transmission correction. IvsLam = this->transmissonCorrection(IvsLam, wavelengthInterval, monitorBackgroundWavelengthInterval, monitorIntegrationWavelengthInterval, - i0MonitorIndex, firstTransmissionRun.get(), secondTransmissionRun, stitchingStartQ, stitchingDeltaQ, stitchingEndQ, stitchingStartOverlapQ, stitchingEndOverlapQ, wavelengthStep); + i0MonitorIndex, firstTransmissionRun.get(), secondTransmissionRun, stitchingStart, stitchingDelta, stitchingEnd, stitchingStartOverlap, stitchingEndOverlap, wavelengthStep); } else @@ -502,11 +502,11 @@ namespace Mantid * @param i0MonitorIndex : Monitor index for the I0 monitor * @param firstTransmissionRun : The first transmission run * @param secondTransmissionRun : The second transmission run (optional) - * @param stitchingStartQ : Stitching start Q (optional but dependent on secondTransmissionRun) - * @param stitchingDeltaQ : Stitching delta Q (optional but dependent on secondTransmissionRun) - * @param stitchingEndQ : Stitching end Q (optional but dependent on secondTransmissionRun) - * @param stitchingStartOverlapQ : Stitching start Q overlap (optional but dependent on secondTransmissionRun) - * @param stitchingEndOverlapQ : Stitching end Q overlap (optional but dependent on secondTransmissionRun) + * @param stitchingStart : Stitching start in wavelength (optional but dependent on secondTransmissionRun) + * @param stitchingDelta : Stitching delta in wavelength (optional but dependent on secondTransmissionRun) + * @param stitchingEnd : Stitching end in wavelength (optional but dependent on secondTransmissionRun) + * @param stitchingStartOverlap : Stitching start wavelength overlap (optional but dependent on secondTransmissionRun) + * @param stitchingEndOverlap : Stitching end wavelength overlap (optional but dependent on secondTransmissionRun) * @param wavelengthStep : Step in angstroms for rebinning for workspaces converted into wavelength. * @return Normalized run workspace by the transmission workspace, which have themselves been converted to Lam, normalized by monitors and possibly stitched together. */ @@ -514,9 +514,9 @@ namespace Mantid const MinMax& wavelengthInterval, const MinMax& wavelengthMonitorBackgroundInterval, const MinMax& wavelengthMonitorIntegrationInterval, const int& i0MonitorIndex, MatrixWorkspace_sptr firstTransmissionRun, OptionalMatrixWorkspace_sptr secondTransmissionRun, - const OptionalDouble& stitchingStartQ, const OptionalDouble& stitchingDeltaQ, - const OptionalDouble& stitchingEndQ, const OptionalDouble& stitchingStartOverlapQ, - const OptionalDouble& stitchingEndOverlapQ, const double& wavelengthStep) + const OptionalDouble& stitchingStart, const OptionalDouble& stitchingDelta, + const OptionalDouble& stitchingEnd, const OptionalDouble& stitchingStartOverlap, + const OptionalDouble& stitchingEndOverlap, const double& wavelengthStep) { g_log.debug("Extracting first transmission run workspace indexes from spectra"); const WorkspaceIndexList detectorIndexes = createWorkspaceIndexListFromDetectorWorkspace(IvsLam, @@ -535,11 +535,11 @@ namespace Mantid if (secondTransmissionRun.is_initialized()) { alg->setProperty("SecondTransmissionRun", secondTransmissionRun.get()); - const std::vector params = boost::assign::list_of(stitchingStartQ.get())( - stitchingDeltaQ.get())(stitchingEndQ.get()).convert_to_container >(); + const std::vector params = boost::assign::list_of(stitchingStart.get())( + stitchingDelta.get())(stitchingEnd.get()).convert_to_container >(); alg->setProperty("Params", params); - alg->setProperty("StartOverlapQ", stitchingStartOverlapQ.get()); - alg->setProperty("EndOverlapQ", stitchingEndOverlapQ.get()); + alg->setProperty("StartOverlap", stitchingStartOverlap.get()); + alg->setProperty("EndOverlap", stitchingEndOverlap.get()); } alg->setProperty("WorkspaceIndexList", detectorIndexes); alg->setProperty("I0MonitorIndex", i0MonitorIndex); diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index e940cd9559c7..9ef98e83c82a 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -113,15 +113,15 @@ namespace Mantid new ArrayProperty("Params", boost::make_shared(true)), "A comma separated list of first bin boundary, width, last bin boundary. " "These parameters are used for stitching together transmission runs. " - "Values are in q. This input is only needed if a SecondTransmission run is provided."); + "Values are in wavelength (angstroms). This input is only needed if a SecondTransmission run is provided."); declareProperty( - new PropertyWithValue("StartOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "Start Q for stitching transmission runs together"); + new PropertyWithValue("StartOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "Start wavelength for stitching transmission runs together"); declareProperty( - new PropertyWithValue("EndOverlapQ", Mantid::EMPTY_DBL(), Direction::Input), - "End Q for stitching transmission runs together"); + new PropertyWithValue("EndOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "End wavelength (angstroms) for stitching transmission runs together"); } @@ -266,21 +266,21 @@ namespace Mantid throw std::invalid_argument( "If a SecondTransmissionRun has been given, then stitching Params for the transmission runs are also required."); } - if (isPropertyDefault("StartOverlapQ")) + if (isPropertyDefault("StartOverlap")) { throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching StartOverlapQ for the transmission runs is also required."); + "If a SecondTransmissionRun has been given, then a stitching StartOverlap for the transmission runs is also required."); } - if (isPropertyDefault("EndOverlapQ")) + if (isPropertyDefault("EndOverlap")) { throw std::invalid_argument( - "If a SecondTransmissionRun has been given, then a stitching EndOverlapQ for the transmission runs is also required."); + "If a SecondTransmissionRun has been given, then a stitching EndOverlap for the transmission runs is also required."); } - const double startOverlapQ = this->getProperty("StartOverlapQ"); - const double endOverlapQ = this->getProperty("EndOverlapQ"); - if (startOverlapQ >= endOverlapQ) + const double startOverlap = this->getProperty("StartOverlap"); + const double endOverlap = this->getProperty("EndOverlap"); + if (startOverlap >= endOverlap) { - throw std::invalid_argument("EndOverlapQ must be > StartOverlapQ"); + throw std::invalid_argument("EndOverlap must be > StartOverlap"); } if( !isPropertyDefault("SecondTransmissionRun") ) @@ -306,15 +306,15 @@ namespace Mantid * * @param firstTransmissionRun * @param secondTransmissionRun - * @param stitchingStartQ - * @param stitchingDeltaQ - * @param stitchingEndQ + * @param stitchingStart + * @param stitchingDelta + * @param stitchingEnd */ void ReflectometryWorkflowBase::getTransmissionRunInfo( OptionalMatrixWorkspace_sptr& firstTransmissionRun, - OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStartQ, - OptionalDouble& stitchingDeltaQ, OptionalDouble& stitchingEndQ, - OptionalDouble& stitchingStartOverlapQ, OptionalDouble& stitchingEndOverlapQ) const + OptionalMatrixWorkspace_sptr& secondTransmissionRun, OptionalDouble& stitchingStart, + OptionalDouble& stitchingDelta, OptionalDouble& stitchingEnd, + OptionalDouble& stitchingStartOverlap, OptionalDouble& stitchingEndOverlap) const { bool bFirstTransInWavelength = false; if (!isPropertyDefault("FirstTransmissionRun")) @@ -337,15 +337,15 @@ namespace Mantid } { std::vector params = getProperty("Params"); - stitchingStartQ = params[0]; - stitchingDeltaQ = params[1]; - stitchingEndQ = params[2]; + stitchingStart = params[0]; + stitchingDelta = params[1]; + stitchingEnd = params[2]; } { - double temp = this->getProperty("StartOverlapQ"); - stitchingStartOverlapQ = temp; - temp = this->getProperty("EndOverlapQ"); - stitchingEndOverlapQ = temp; + double temp = this->getProperty("StartOverlap"); + stitchingStartOverlap = temp; + temp = this->getProperty("EndOverlap"); + stitchingEndOverlap = temp; } } diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index 787a91078ef8..7ceca8566a6e 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -1,70 +1,11 @@ import unittest import mantid.api from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace, Load +from testhelpers.algorithm_decorator import make_decorator import inspect import re -def make_decorator(algorithm_to_decorate): - """ - Dynamically create a builder pattern style decorator around a Mantid algorithm. - This allows you to separate out setting algorithm parameters from the actual method execution. Parameters may be reset multiple times. - - Usage: - rebin = make_decorator(Rebin) - rebin.set_Params([0, 0.1, 1]) - .... - rebin.execute() - - Arguments: - algorithm_to_decorate: The mantid.simpleapi algorithm to decorate. - - - - """ - - class Decorator(object): - - def __init__(self, alg_subject): - self.__alg_subject = alg_subject - self.__parameters__ = dict() - - def execute(self, additional=None, verbose=False): - if verbose: - print "Algorithm Parameters:" - print self.__parameters__ - print - out = self.__alg_subject(**self.__parameters__) - return out - - def set_additional(self, additional): - self.__parameters__.update(**additional) - - def add_getter_setter(type, name): - - def setter(self, x): - self.__parameters__[name] = x - - def getter(self): - return self.__parameters__[name] - - setattr(type, "set_" + name, setter) - setattr(type, "get_" + name, getter) - - - argspec = inspect.getargspec(algorithm_to_decorate) - for parameter in argspec.varargs.split(','): - m = re.search('(^\w+)', parameter) # Take the parameter key part from the defaults given as 'key=value' - if m: - parameter = m.group(0).strip() - m = re.search('\w+$', parameter) # strip off any leading numerical values produced by argspec - if m: - parameter = m.group(0).strip() - add_getter_setter(Decorator, m.group(0).strip()) - - return Decorator(algorithm_to_decorate) - - class CreateTransmissionWorkspaceTest(unittest.TestCase): def setUp(self): @@ -109,22 +50,22 @@ def test_provide_second_transmission_run_without_start_overlap_q_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlapQ( 0.4 ) + alg.set_EndOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_provide_end_transmission_run_without_end_overlap_q_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlapQ( 0.4 ) + alg.set_StartOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlapQ( 0.6 ) - alg.set_EndOverlapQ( 0.4 ) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_must_provide_wavelengths(self): @@ -178,8 +119,8 @@ def test_spectrum_map_mismatch_throws(self): alg.set_FirstTransmissionRun(trans_run1) alg.set_SecondTransmissionRun(trans_run2) alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlapQ(1) - alg.set_EndOverlapQ(2) + alg.set_StartOverlap(1) + alg.set_EndOverlap(2) self.assertRaises(ValueError, alg.execute) DeleteWorkspace(trans_run1) @@ -232,8 +173,8 @@ def test_execute_two_tranmissions(self): alg.set_MonitorIntegrationWavelengthMin(4.0) alg.set_MonitorIntegrationWavelengthMax(10.0) alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlapQ( 10.0 ) - alg.set_EndOverlapQ( 12.0 ) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) transmission_ws = alg.execute() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index 150cab2109a2..104c18accbf9 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -62,7 +62,7 @@ def test_provide_second_transmission_run_without_start_overlap_q_throws(self): alg.set_FirstTransmissionRun(self.__tof) alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlapQ( 0.4 ) + alg.set_EndOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_provide_end_transmission_run_without_end_overlap_q_throws(self): @@ -70,7 +70,7 @@ def test_provide_end_transmission_run_without_end_overlap_q_throws(self): alg.set_FirstTransmissionRun(self.__tof) alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlapQ( 0.4 ) + alg.set_StartOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): @@ -78,8 +78,8 @@ def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): alg.set_FirstTransmissionRun(self.__tof) alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlapQ( 0.6 ) - alg.set_EndOverlapQ( 0.4 ) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) self.assertRaises(ValueError, alg.execute) def test_must_provide_wavelengths(self): @@ -207,8 +207,8 @@ def test_point_detector_run_with_two_transmission_workspaces(self): alg.set_SecondTransmissionRun(trans_run2) alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlapQ( 10.0 ) - alg.set_EndOverlapQ( 12.0 ) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) alg.set_ThetaIn(0.2) out_ws_q, out_ws_lam, theta = alg.execute() From 5a126c0614dd0f1f02ed969cffcf76eb1ec91dad Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Fri, 13 Dec 2013 12:07:32 +0000 Subject: [PATCH 195/403] Make filename optional & add ScriptText property. Refs #8599. --- .../Algorithms/src/GeneratePythonScript.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp index eec03cd04c85..def422709e07 100644 --- a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp @@ -58,8 +58,9 @@ void GeneratePythonScript::init() std::vector exts; exts.push_back(".py"); - declareProperty(new API::FileProperty("Filename","", API::FileProperty::Save, exts), + declareProperty(new API::FileProperty("Filename","", API::FileProperty::OptionalSave, exts), "The file into which the Python script will be generated."); + declareProperty("ScriptText", "",Direction::Output); } //---------------------------------------------------------------------------------------------- @@ -104,9 +105,15 @@ void GeneratePythonScript::exec() generatedScript += *m3_pIter + "\n"; } - file << generatedScript; - file.flush(); - file.close(); + setPropertyValue("ScriptText", generatedScript); + + if (!filename.empty()) + { + file << generatedScript; + file.flush(); + file.close(); + } + } //---------------------------------------------------------------------------------------------- /** Generate the line of script corresponding to the given AlgorithmHistory From ec75e47ae2a8418998877977c3ae41eed563430b Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Fri, 13 Dec 2013 12:08:41 +0000 Subject: [PATCH 196/403] Updated unit test to verify ScriptText is correct. Refs #8599. --- .../Framework/Algorithms/test/GeneratePythonScriptTest.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/Algorithms/test/GeneratePythonScriptTest.h b/Code/Mantid/Framework/Algorithms/test/GeneratePythonScriptTest.h index a7e49bfdbcf7..e93ae3f49679 100644 --- a/Code/Mantid/Framework/Algorithms/test/GeneratePythonScriptTest.h +++ b/Code/Mantid/Framework/Algorithms/test/GeneratePythonScriptTest.h @@ -52,21 +52,26 @@ class GeneratePythonScriptTest : public CxxTest::TestSuite TS_ASSERT( alg.isInitialized() ); TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", workspaceName) ); TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "GeneratePythonScriptTest.py") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("ScriptText", "") ); TS_ASSERT_THROWS_NOTHING( alg.execute(); ); TS_ASSERT( alg.isExecuted() ); - // Compare the contents of the file to the expected result line-by-line. std::string filename = alg.getProperty("Filename"); std::ifstream file(filename.c_str(), std::ifstream::in); std::string scriptLine; int lineCount(0); + while(std::getline(file, scriptLine)) { TS_ASSERT_EQUALS(scriptLine,result[lineCount]); lineCount++; } + // Verify that if we set the content of ScriptText that it is set correctly. + alg.setPropertyValue("ScriptText", result[4]); + TS_ASSERT_EQUALS(alg.getPropertyValue("ScriptText"), "CropWorkspace(InputWorkspace='testGeneratePython',OutputWorkspace='testGeneratePython',XMin='2',XMax='5')"); + file.close(); if (Poco::File(filename).exists()) Poco::File(filename).remove(); } From b28b209ee29e203b03d23f5fcebac8e9f019f0bc Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:11:29 +0000 Subject: [PATCH 197/403] Refs #6473. Changed the way the sequential dialog is opened. --- .../inc/MantidQtCustomInterfaces/MuonAnalysis.h | 2 ++ .../MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 13 +++++++++++++ .../MantidQtMantidWidgets/MuonFitPropertyBrowser.h | 3 +++ .../MantidWidgets/src/MuonFitPropertyBrowser.cpp | 5 +---- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index 3e5d3c69822a..1e4e56440c41 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -214,6 +214,8 @@ private slots: /// Saves the value of the widget which called the slot void saveWidgetValue(); + /// Opens a sequential fit dialog + void openSequentialFitDialog(); private: diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 19397c9e2a32..0f2cca8ffd4b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -28,6 +28,7 @@ #include "MantidQtCustomInterfaces/MuonAnalysisResultTableTab.h" #include "MantidQtMantidWidgets/FitPropertyBrowser.h" #include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" +#include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" #include #include @@ -148,6 +149,8 @@ void MuonAnalysis::initLayout() } m_uiForm.fitBrowser->init(); + connect( m_uiForm.fitBrowser, SIGNAL(sequentialFitRequested()), + this, SLOT(openSequentialFitDialog()) ); // alow appending files m_uiForm.mwRunFiles->allowMultipleFiles(true); @@ -3678,5 +3681,15 @@ void MuonAnalysis::setGrouping(ITableWorkspace_sptr detGroupingTable) updateFrontAndCombo(); } +/** + * Opens a sequential fit dialog. + */ +void MuonAnalysis::openSequentialFitDialog() +{ + MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(m_uiForm.fitBrowser, loadAlg); + dialog->exec(); + +} + }//namespace MantidQT }//namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h index 13e7bb4e6165..1d05b1422cd2 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h @@ -50,6 +50,9 @@ public slots: /// Open sequential fit dialog virtual void sequentialFit(); +signals: + /// Emitted when sequential fit is requested by user + void sequentialFitRequested(); protected: virtual void showEvent(QShowEvent* e); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp index ecdd89bde2ba..dc853b2978ae 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp @@ -1,5 +1,4 @@ #include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" -#include "MantidQtMantidWidgets/MuonSequentialFitDialog.h" #include "MantidQtMantidWidgets/PropertyHandler.h" #include "MantidAPI/FunctionFactory.h" @@ -316,8 +315,7 @@ void MuonFitPropertyBrowser::fit() */ void MuonFitPropertyBrowser::sequentialFit() { - MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(this); - dialog->exec(); + emit sequentialFitRequested(); } /** @@ -346,6 +344,5 @@ bool MuonFitPropertyBrowser::isWorkspaceValid(Mantid::API::Workspace_sptr ws)con return false; } - } // MantidQt } // API From 78debd201b2d43c479e94fa4fc4a105db39815bc Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:14:46 +0000 Subject: [PATCH 198/403] Refs #6473. Pass loading algorithm to the dialog. --- .../MuonSequentialFitDialog.h | 5 +- .../src/MuonSequentialFitDialog.cpp | 53 ++++++++----------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 4a8a96c20f2c..9ffc8609aef5 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -45,7 +45,7 @@ namespace MantidWidgets Q_OBJECT public: - MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser); + MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser, Algorithm_sptr loadAlg); virtual ~MuonSequentialFitDialog(); enum DialogState @@ -88,6 +88,9 @@ namespace MantidWidgets /// Whether user requested fitting to be stopped bool m_stopRequested; + /// Algorithm the dialog should use for loading + Algorithm_sptr m_loadAlg; + // -- STATIC MEMBERS ------------------------------------------------------ /// Checks if specified name is valid as a name for label. diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index aba3c9a7b674..ecab7a4fb028 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -2,6 +2,7 @@ #include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" #include "MantidAPI/AnalysisDataService.h" +#include "MantidAPI/AlgorithmProxy.h" namespace MantidQt { @@ -12,11 +13,11 @@ namespace MantidWidgets Logger& MuonSequentialFitDialog::g_log(Logger::get("MuonSequentialFitDialog")); /** - * Constructor */ - MuonSequentialFitDialog::MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser) : - QDialog(fitPropBrowser), m_fitPropBrowser(fitPropBrowser) + MuonSequentialFitDialog::MuonSequentialFitDialog(MuonFitPropertyBrowser* fitPropBrowser, + Algorithm_sptr loadAlg) : + QDialog(fitPropBrowser), m_fitPropBrowser(fitPropBrowser), m_loadAlg(loadAlg) { m_ui.setupUi(this); @@ -292,20 +293,26 @@ namespace MantidWidgets if ( m_stopRequested ) break; - Workspace_sptr loadedWS; + MatrixWorkspace_sptr ws; + + auto load = boost::dynamic_pointer_cast( AlgorithmManager::Instance().create("MuonLoad") ); + load->setChild(true); + load->setRethrows(true); + load->copyPropertiesFrom(*m_loadAlg); try { - // TODO: should be MuonLoad here - IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); - loadAlg->setChild(true); - loadAlg->setRethrows(true); - loadAlg->initialize(); - loadAlg->setPropertyValue( "Filename", fileIt->toStdString() ); - loadAlg->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used - loadAlg->execute(); - - loadedWS = loadAlg->getProperty("OutputWorkspace"); + load->initialize(); + + load->setPropertyValue( "Filename", fileIt->toStdString() ); + load->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used + + if ( m_fitPropBrowser->rawData() ) // TODO: or vice verca? + load->setPropertyValue( "RebinParams", "" ); + + load->execute(); + + ws = load->getProperty("OutputWorkspace"); } catch(std::exception& e) { @@ -314,22 +321,9 @@ namespace MantidWidgets break; } - MatrixWorkspace_sptr ws; - - if ( auto single = boost::dynamic_pointer_cast(loadedWS) ) - { - ws = single; - } - else if ( auto group = boost::dynamic_pointer_cast(loadedWS) ) - { - auto first = boost::dynamic_pointer_cast( group->getItem(0) ); - ws = first; - } - const std::string runTitle = getRunTitle(ws); const std::string wsBaseName = labelGroupName + "_" + runTitle; - IFunction_sptr functionToFit; if ( useInitFitFunction ) @@ -339,12 +333,11 @@ namespace MantidWidgets // Use the same function over and over, so that previous fitted params are used for the next fit functionToFit = fitFunction; - IAlgorithm_sptr fit = AlgorithmManager::Instance().createUnmanaged("Fit"); + IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit"); + fit->setRethrows(true); try { - fit->initialize(); - fit->setRethrows(true); // Set function. Gets updated when fit is done. fit->setProperty("Function", functionToFit); From 57fa1287464365daabae1d49c6f6063d63b16d9c Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:19:06 +0000 Subject: [PATCH 199/403] Refs #6473. Helper functions to create load algorithm. --- .../MantidQtCustomInterfaces/MuonAnalysis.h | 9 + .../CustomInterfaces/src/MuonAnalysis.cpp | 155 ++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index 1e4e56440c41..eaeebf397563 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -322,6 +322,15 @@ private slots: /// Return number of groups defined (not including pairs) int numGroups(); + /// Returns custom dead time table file name as set on the interface + std::string deadTimeFilename(); + + /// Loads dead time table (group of tables) from the file. + Workspace_sptr loadDeadTimes(const std::string& filename); + + /// Creates and algorithm with all the properties set according to widget values on the interface + Algorithm_sptr createLoadAlgorithm(); + // TODO: wsIndex can be removed from functions below if we put only one group to the workspace // (as we are doing with pairs) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 0f2cca8ffd4b..b97b6a5b4f91 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -3689,6 +3689,161 @@ void MuonAnalysis::openSequentialFitDialog() MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(m_uiForm.fitBrowser, loadAlg); dialog->exec(); + +/** + * Returns custom dead time table file name as set on the interface. + * @return The filename + */ +std::string MuonAnalysis::deadTimeFilename() +{ + if(!m_uiForm.mwRunDeadTimeFile->isValid()) + throw std::runtime_error("Specified Dead Time file is not valid."); + + return m_uiForm.mwRunDeadTimeFile->getFirstFilename().toStdString(); +} + +/** + * Loads dead time table (group of table) from the file. + * @param filename :: File to load dead times from + * @return Table (group of tables) with dead times + */ +Workspace_sptr MuonAnalysis::loadDeadTimes(const std::string& filename) +{ + try + { + IAlgorithm_sptr loadDeadTimes = AlgorithmManager::Instance().create("LoadNexusProcessed"); + loadDeadTimes->setChild(true); + loadDeadTimes->setPropertyValue("Filename", filename); + loadDeadTimes->setPropertyValue("OutputWorkspace", "__NotUsed"); + loadDeadTimes->execute(); + + return loadDeadTimes->getProperty("OutputWorkspace"); + } + catch(...) + { + throw std::runtime_error("Unable to load dead times from the spefied file"); + } +} + +/** + * Creates and algorithm with all the properties set according to widget values on the interface. + * @return The algorithm with properties set + */ +Algorithm_sptr MuonAnalysis::createLoadAlgorithm() +{ + Algorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("MuonLoad"); + loadAlg->initialize(); + + // -- Dead Time Correction -------------------------------------------------- + + if (m_uiForm.deadTimeType->currentIndex() != 0) + { + loadAlg->setProperty("ApplyDeadTimeCorrection", true); + + if (m_uiForm.deadTimeType->currentIndex() == 2) // From Specified File + { + + Workspace_sptr deadTimes = loadDeadTimes( deadTimeFilename() ); + + loadAlg->setProperty("CustomDeadTimeTable", deadTimes); + } + } + + // -- Grouping -------------------------------------------------------------- + + ITableWorkspace_sptr grouping = parseGrouping(); + loadAlg->setProperty("DetectorGroupingTable", grouping); + + // -- X axis options -------------------------------------------------------- + + double Xmin = m_uiForm.timeAxisStartAtInput->text().toDouble(); + loadAlg->setProperty("Xmin", Xmin); + + double Xmax = m_uiForm.timeAxisFinishAtInput->text().toDouble(); + loadAlg->setProperty("Xmax", Xmax); + + double timeZero = m_uiForm.timeZeroFront->text().toDouble(); + loadAlg->setProperty("TimeZero", timeZero); + + // -- Rebin options --------------------------------------------------------- + + if ( m_uiForm.rebinComboBox->currentIndex() != 0) + { + std::string rebinParams; + + if(m_uiForm.rebinComboBox->currentIndex() == 1) // Fixed + { + auto loadedWS = AnalysisDataService::Instance().retrieveWS(m_grouped_name); + MatrixWorkspace_sptr ws; + + if ( ! ( ws = boost::dynamic_pointer_cast(loadedWS) ) ) + { + auto group = boost::dynamic_pointer_cast(loadedWS); + ws = boost::dynamic_pointer_cast(group->getItem(0)); + } + + double binSize = ws->dataX(0)[1] - ws->dataX(0)[0]; + + double bunchedBinSize = binSize * m_uiForm.optionStepSizeText->text().toDouble(); + + rebinParams = boost::lexical_cast(bunchedBinSize); + } + else // Variable + { + rebinParams = m_uiForm.binBoundaries->text().toStdString(); + } + + loadAlg->setPropertyValue("RebinParams", rebinParams); + } + + // -- Group/pair properties ------------------------------------------------- + + int index = m_uiForm.frontGroupGroupPairComboBox->currentIndex(); + + if (index >= numGroups()) + { + loadAlg->setProperty("OutputType", "PairAsymmetry"); + int tableRow = m_pairToRow[index - numGroups()]; + + QTableWidget* t = m_uiForm.pairTable; + + double alpha = t->item(tableRow,3)->text().toDouble(); + int index1 = static_cast( t->cellWidget(tableRow,1) )->currentIndex(); + int index2 = static_cast( t->cellWidget(tableRow,2) )->currentIndex(); + + loadAlg->setProperty("PairFirstIndex", index1); + loadAlg->setProperty("PairSecondIndex", index2); + loadAlg->setProperty("Alpha", alpha); + } + else + { + if ( parsePlotType(m_uiForm.frontPlotFuncs) == Asymmetry ) + loadAlg->setProperty("OutputType", "GroupAsymmetry"); + else + loadAlg->setProperty("OutputType", "GroupCounts"); + + int groupIndex = getGroupNumberFromRow(m_groupToRow[index]); + loadAlg->setProperty("GroupIndex", groupIndex); + } + + // -- Period options -------------------------------------------------------- + + QString periodLabel1 = m_uiForm.homePeriodBox1->currentText(); + + int periodIndex1 = periodLabel1.toInt() - 1; + loadAlg->setProperty("FirstPeriod", periodIndex1); + + QString periodLabel2 = m_uiForm.homePeriodBox2->currentText(); + if ( periodLabel2 != "None" ) + { + int periodIndex2 = periodLabel2.toInt() - 1; + loadAlg->setProperty("SecondPeriod", periodIndex2); + + std::string op = m_uiForm.homePeriodBoxMath->currentText().toStdString(); + loadAlg->setProperty("PeriodOperation", op); + } + + return loadAlg; } }//namespace MantidQT From 88673f3d4407ec3fa80ea3d62d8ed8a56a1557f4 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:19:28 +0000 Subject: [PATCH 200/403] Refs #6473. Creating and passing the algorithm to the dialog. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index b97b6a5b4f91..bea6556b53ba 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -3686,9 +3686,25 @@ void MuonAnalysis::setGrouping(ITableWorkspace_sptr detGroupingTable) */ void MuonAnalysis::openSequentialFitDialog() { + Algorithm_sptr loadAlg; + + try + { + loadAlg = createLoadAlgorithm(); + } + catch(...) + { + QMessageBox::critical(this, "Unable to open dialog", "Error while setting load properties"); + return; + } + + m_uiForm.fitBrowser->blockSignals(true); + MuonSequentialFitDialog* dialog = new MuonSequentialFitDialog(m_uiForm.fitBrowser, loadAlg); dialog->exec(); + m_uiForm.fitBrowser->blockSignals(false); +} /** * Returns custom dead time table file name as set on the interface. From 697229c27c6f80ba0c6f84153382ff7d25b42bf0 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:20:06 +0000 Subject: [PATCH 201/403] Refs #6473. Refactored dead time correction a bit. So it now uses the same routines as algorithm creation function. --- .../CustomInterfaces/src/MuonAnalysis.cpp | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index bea6556b53ba..f0b6b362d922 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -1535,38 +1535,28 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) if (m_uiForm.instrSelector->currentText().toUpper() == "ARGUS") throw std::runtime_error("Dead times are currently not implemented in ARGUS files."); - IAlgorithm_sptr applyCorrAlg = AlgorithmManager::Instance().create("ApplyDeadTimeCorr"); - - applyCorrAlg->setPropertyValue("InputWorkspace", m_workspace_name); - applyCorrAlg->setPropertyValue("OutputWorkspace", m_workspace_name); - - ScopedWorkspace customDeadTimes; + ScopedWorkspace deadTimes; if (m_uiForm.deadTimeType->currentIndex() == 1) // From Run Data { if( ! loadedDeadTimes ) throw std::runtime_error("Data file doesn't appear to contain dead time values"); - - applyCorrAlg->setPropertyValue("DeadTimeTable", loadedDeadTimes.name()); + + Workspace_sptr ws = loadedDeadTimes.retrieve(); + loadedDeadTimes.remove(); + + deadTimes.set(ws); } else if (m_uiForm.deadTimeType->currentIndex() == 2) // From Specified File { - if(!m_uiForm.mwRunDeadTimeFile->isValid()) - throw std::runtime_error("Specified Dead Time file is not valid."); - - std::string deadTimeFile = m_uiForm.mwRunDeadTimeFile->getFirstFilename().toStdString(); - - IAlgorithm_sptr loadDeadTimes = AlgorithmManager::Instance().create("LoadNexusProcessed"); - loadDeadTimes->setPropertyValue("Filename", deadTimeFile); - loadDeadTimes->setPropertyValue("OutputWorkspace", customDeadTimes.name()); - loadDeadTimes->execute(); - - if ( ! customDeadTimes ) - throw std::runtime_error("Unable to load dead times from the spefied file"); - - applyCorrAlg->setPropertyValue("DeadTimeTable", customDeadTimes.name()); + Workspace_sptr ws = loadDeadTimes( deadTimeFilename() ); + deadTimes.set(ws); } + IAlgorithm_sptr applyCorrAlg = AlgorithmManager::Instance().create("ApplyDeadTimeCorr"); + applyCorrAlg->setPropertyValue("InputWorkspace", m_workspace_name); + applyCorrAlg->setPropertyValue("OutputWorkspace", m_workspace_name); + applyCorrAlg->setPropertyValue("DeadTimeTable", deadTimes.name()); applyCorrAlg->execute(); } catch(std::exception& e) From cccb358c42472ccde02ab9ccb7cc44244dcacaaf Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:20:22 +0000 Subject: [PATCH 202/403] Refs #6473. Minor fixes in MuonAnalysis. --- Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index f0b6b362d922..98f3ac73a9e9 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -508,10 +508,7 @@ MatrixWorkspace_sptr MuonAnalysis::createAnalysisWorkspace(ItemType itemType, in alg->initialize(); - // TODO: should really be global - const std::string loadedWSName = m_workspace_name + "Grouped"; - - auto loadedWS = AnalysisDataService::Instance().retrieveWS(loadedWSName); + auto loadedWS = AnalysisDataService::Instance().retrieveWS(m_grouped_name); if ( auto group = boost::dynamic_pointer_cast(loadedWS) ) { @@ -576,7 +573,7 @@ MatrixWorkspace_sptr MuonAnalysis::createAnalysisWorkspace(ItemType itemType, in QTableWidget* t = m_uiForm.pairTable; - double alpha = t->item(m_pairTableRowInFocus,3)->text().toDouble(); + double alpha = t->item(tableRow,3)->text().toDouble(); int index1 = static_cast( t->cellWidget(tableRow,1) )->currentIndex(); int index2 = static_cast( t->cellWidget(tableRow,2) )->currentIndex(); From 9e620c25c53a33dc7b9b9869d3185857bcf9712b Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Fri, 13 Dec 2013 12:47:43 +0000 Subject: [PATCH 203/403] Remove file error checking. Refs #8599. --- .../Framework/Algorithms/src/GeneratePythonScript.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp index def422709e07..f753dc5e021c 100644 --- a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp @@ -72,13 +72,6 @@ void GeneratePythonScript::exec() const std::string filename = getPropertyValue("Filename"); std::ofstream file(filename.c_str(), std::ofstream::trunc); - - if (NULL == file) - { - g_log.error("Unable to create file: " + filename); - throw Exception::FileError("Unable to create file: " , filename); - } - // Get the algorithm histories of the workspace. const WorkspaceHistory wsHistory = ws->getHistory(); From 27eb18a3467adf49cd317aa585b999eb002a637e Mon Sep 17 00:00:00 2001 From: Jay Rainey Date: Fri, 13 Dec 2013 12:53:43 +0000 Subject: [PATCH 204/403] Only attempt to open file if property set. Refs #8599. --- .../Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp index f753dc5e021c..073b92f855c6 100644 --- a/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GeneratePythonScript.cpp @@ -69,8 +69,6 @@ void GeneratePythonScript::init() void GeneratePythonScript::exec() { const Workspace_const_sptr ws = getProperty("InputWorkspace"); - const std::string filename = getPropertyValue("Filename"); - std::ofstream file(filename.c_str(), std::ofstream::trunc); // Get the algorithm histories of the workspace. const WorkspaceHistory wsHistory = ws->getHistory(); @@ -100,8 +98,11 @@ void GeneratePythonScript::exec() setPropertyValue("ScriptText", generatedScript); + const std::string filename = getPropertyValue("Filename"); + if (!filename.empty()) { + std::ofstream file(filename.c_str(), std::ofstream::trunc); file << generatedScript; file.flush(); file.close(); From c2d304f18d34a54c255aa239bb1b087b8e31d4c9 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 12:59:03 +0000 Subject: [PATCH 205/403] Refs #6473. Fix for windows error and warnings. --- Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 4 ++-- .../inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h | 2 +- .../MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 98f3ac73a9e9..9bcc31629ef5 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -398,7 +398,7 @@ void MuonAnalysis::plotItem(ItemType itemType, int tableRow, PlotType plotType) setCurrentDataName( wsNameQ ); } - catch(std::exception& e) + catch(...) { QMessageBox::critical( this, "MuonAnalysis - Error", "Unable to plot the item. Check log for details." ); } @@ -3706,7 +3706,7 @@ std::string MuonAnalysis::deadTimeFilename() } /** - * Loads dead time table (group of table) from the file. + * Loads dead time table (group of tables) from the file. * @param filename :: File to load dead times from * @return Table (group of tables) with dead times */ diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index 9ffc8609aef5..a8b33894de78 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -39,7 +39,7 @@ namespace MantidWidgets File change history is stored at: Code Documentation is available at: */ - class DLLExport MuonSequentialFitDialog : public QDialog + class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS MuonSequentialFitDialog : public QDialog { Q_OBJECT diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index ecab7a4fb028..7e0a76677d9c 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -314,7 +314,7 @@ namespace MantidWidgets ws = load->getProperty("OutputWorkspace"); } - catch(std::exception& e) + catch(...) { QMessageBox::critical(this, "Loading failed", "Unable to load one of the files.\n\nCheck log for details"); @@ -356,7 +356,7 @@ namespace MantidWidgets fit->execute(); } - catch(std::exception& e) + catch(...) { QMessageBox::critical(this, "Fitting failed", "Unable to fit one of the files.\n\nCheck log for details"); From 21aacb3980e153004bdc4565005548c34e554b77 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 13:30:39 +0000 Subject: [PATCH 206/403] Refs #6473. Ability to export results on the Results Tab. --- .../src/MuonAnalysisResultTableTab.cpp | 39 ++++++++++++++++++- .../src/MuonSequentialFitDialog.cpp | 3 ++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisResultTableTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisResultTableTab.cpp index 46744811542f..3bd15f1c8f8c 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisResultTableTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisResultTableTab.cpp @@ -9,6 +9,7 @@ #include "MantidQtAPI/UserSubWindow.h" #include +#include #include #include @@ -27,8 +28,10 @@ namespace CustomInterfaces { namespace Muon { - using namespace MantidQt::API; using namespace Mantid::Kernel; + using namespace Mantid::API; + + using namespace MantidQt::API; using namespace MantidQt::MantidWidgets; const std::string MuonAnalysisResultTableTab::RUN_NO_LOG = "run_number"; @@ -207,6 +210,7 @@ void MuonAnalysisResultTableTab::populateTables(const QStringList& wsList) // Clear the previous table values m_logValues.clear(); QVector fittedWsList; + // Get all the workspaces from the fitPropertyBrowser and find out whether they have had fitting done to them. for (int i(0); i items = + Mantid::API::AnalysisDataService::Instance().topLevelItems(); + + for ( auto it = items.begin(); it != items.end(); ++it ) + { + if ( ! boost::starts_with(it->first, "MuonSeqFit_") ) + continue; + + auto group = boost::dynamic_pointer_cast(it->second); + + if ( ! group ) + continue; + + for ( size_t i = 0; i < group->size(); ++i ) + { + auto ws = boost::dynamic_pointer_cast( group->getItem(i) ); + + if ( ! ws ) + continue; + + std::string name = ws->name(); + size_t pos = name.find("_Workspace"); + + if ( pos == std::string::npos) + continue; + + name.erase(pos); + + fittedWsList << QString::fromStdString(name); + } + } + if(fittedWsList.size() > 0) { // Make sure all params match. diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 7e0a76677d9c..9fc4c5a01a70 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -324,6 +324,9 @@ namespace MantidWidgets const std::string runTitle = getRunTitle(ws); const std::string wsBaseName = labelGroupName + "_" + runTitle; + ads.add(wsBaseName, ws); + ads.addToGroup(labelGroupName, wsBaseName); + IFunction_sptr functionToFit; if ( useInitFitFunction ) From 9a6c3a05f4efe81f98e1a59881d3957f4ff5a9b2 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 14:11:33 +0000 Subject: [PATCH 207/403] Refs #6473. Fixed the Raw workspace names. This naming is assumed in other places as it turns out. --- Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 9bcc31629ef5..dd37288a0b30 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -370,7 +370,7 @@ void MuonAnalysis::plotItem(ItemType itemType, int tableRow, PlotType plotType) // Find names for new workspaces const std::string wsName = getNewAnalysisWSName(groupName, itemType, tableRow, plotType); - const std::string wsRawName = wsName + "; Raw"; + const std::string wsRawName = wsName + "_Raw"; // Make sure they end up in the ADS ads.addOrReplace(wsName, ws); From 4b68be5a84a5e4008b309523a05e53eb235a47fa Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 14:16:01 +0000 Subject: [PATCH 208/403] Refs #6473. Spelling mistake fix. --- Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index dd37288a0b30..c187824512f4 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -1758,10 +1758,10 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) infoStr += ss.str(); } else // Show appropriate error message. - infoStr += "Errror - Not set in data file."; + infoStr += "Error - Not set in data file."; } else // Show appropriate error message. - infoStr += "Errror - Not found in data file."; + infoStr += "Error - Not found in data file."; // Include all the run information. m_uiForm.infoBrowser->setText(infoStr.c_str()); From 3d5a2b6a769be9dd17d7abb36f30540cf6fcf624 Mon Sep 17 00:00:00 2001 From: Arturs Bekasovs Date: Fri, 13 Dec 2013 14:56:04 +0000 Subject: [PATCH 209/403] Refs #6473. Cosmetic diagnosis table improvements. --- .../MuonSequentialFitDialog.h | 3 +++ .../src/MuonSequentialFitDialog.cpp | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h index a8b33894de78..1a3e76a190d0 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h @@ -74,6 +74,9 @@ namespace MantidWidgets void addDiagnosisEntry(const std::string& runTitle, double fitQuality, IFunction_sptr fittedFunction); + /// Helper function to create new item for Diagnosis table + QTableWidgetItem* createTableWidgetItem(const QString& text); + // -- VARIABLES ----------------------------------------------------------- /// UI form diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp index 9fc4c5a01a70..96a56e001b8c 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonSequentialFitDialog.cpp @@ -120,7 +120,6 @@ namespace MantidWidgets m_ui.diagnosisTable->setHorizontalHeaderLabels(headerLabels); // Make the table fill all the available space and columns be resized to fit contents - m_ui.diagnosisTable->horizontalHeader()->setStretchLastSection(true); m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); // Make rows alternate bg colors for better user experience @@ -140,8 +139,11 @@ namespace MantidWidgets m_ui.diagnosisTable->insertRow(newRow); - m_ui.diagnosisTable->setItem(newRow, 0, new QTableWidgetItem( QString::fromStdString(runTitle) ) ); - m_ui.diagnosisTable->setItem(newRow, 1, new QTableWidgetItem( QString::number(fitQuality) ) ); + QString runTitleDisplay = QString::fromStdString(runTitle); + m_ui.diagnosisTable->setItem( newRow, 0, createTableWidgetItem(runTitleDisplay) ); + + QString fitQualityDisplay = QString::number(fitQuality); + m_ui.diagnosisTable->setItem( newRow, 1, createTableWidgetItem(fitQualityDisplay) ); for(int i = 2; i < m_ui.diagnosisTable->columnCount(); i += 2) { @@ -151,13 +153,24 @@ namespace MantidWidgets QString value = QString::number( fittedFunction->getParameter(paramIndex) ); QString error = QString::number( fittedFunction->getError(paramIndex) ); - m_ui.diagnosisTable->setItem(newRow, i, new QTableWidgetItem(value) ); - m_ui.diagnosisTable->setItem(newRow, i + 1, new QTableWidgetItem(error) ); + m_ui.diagnosisTable->setItem(newRow, i, createTableWidgetItem(value) ); + m_ui.diagnosisTable->setItem(newRow, i + 1, createTableWidgetItem(error) ); } m_ui.diagnosisTable->scrollToBottom(); } + /** + * Helper function to create new item for Diagnosis table. + * @return Created and initialized item with text + */ + QTableWidgetItem* MuonSequentialFitDialog::createTableWidgetItem(const QString& text) + { + auto newItem = new QTableWidgetItem(text); + newItem->setFlags(newItem->flags() ^ Qt::ItemIsEditable); + return newItem; + } + /** * Updates visibility/tooltip of label error asterisk. * @param label :: New label as specified by user From 82f7899853d96a9a57aca3a3351d1c7a25c870c5 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Fri, 13 Dec 2013 10:40:52 -0500 Subject: [PATCH 210/403] Refs #8502 rest of refactor tasks --- Code/Mantid/Framework/Geometry/CMakeLists.txt | 3 + .../MantidGeometry/Crystal/IndexingUtils.h | 10 +- .../inc/MantidGeometry/Crystal/NiggliCell.h | 77 ++++ .../Geometry/src/Crystal/IndexingUtils.cpp | 283 +------------- .../Geometry/src/Crystal/NiggliCell.cpp | 360 ++++++++++++++++++ .../Geometry/test/IndexingUtilsTest.h | 106 +----- .../Framework/Geometry/test/NiggliCellTest.h | 132 +++++++ 7 files changed, 594 insertions(+), 377 deletions(-) create mode 100644 Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/NiggliCell.h create mode 100644 Code/Mantid/Framework/Geometry/src/Crystal/NiggliCell.cpp create mode 100644 Code/Mantid/Framework/Geometry/test/NiggliCellTest.h diff --git a/Code/Mantid/Framework/Geometry/CMakeLists.txt b/Code/Mantid/Framework/Geometry/CMakeLists.txt index 78f507b3f5bb..8d6e8d0e1eba 100644 --- a/Code/Mantid/Framework/Geometry/CMakeLists.txt +++ b/Code/Mantid/Framework/Geometry/CMakeLists.txt @@ -3,6 +3,7 @@ set ( SRC_FILES src/ComponentParser.cpp src/Crystal/ConventionalCell.cpp src/Crystal/IndexingUtils.cpp + src/Crystal/NiggliCell.cpp src/Crystal/OrientedLattice.cpp src/Crystal/PointGroup.cpp src/Crystal/ReducedCell.cpp @@ -101,6 +102,7 @@ set ( INC_FILES inc/MantidGeometry/ComponentParser.h inc/MantidGeometry/Crystal/ConventionalCell.h inc/MantidGeometry/Crystal/IndexingUtils.h + inc/MantidGeometry/Crystal/NiggliCell.h inc/MantidGeometry/Crystal/OrientedLattice.h inc/MantidGeometry/Crystal/PointGroup.h inc/MantidGeometry/Crystal/ReducedCell.h @@ -233,6 +235,7 @@ set ( TEST_FILES ObjCompAssemblyTest.h ObjComponentTest.h ObjectTest.h + NiggliCellTest.h OrientedLatticeTest.h ParCompAssemblyTest.h ParComponentFactoryTest.h diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h index 80a9add7d9ee..c253550879ad 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h @@ -274,15 +274,7 @@ class MANTID_GEOMETRY_DLL IndexingUtils static std::string GetLatticeParameterString( const Kernel::DblMatrix & UB ); - /// Check if a,b,c cell has angles satifying Niggli condition within epsilon - static bool HasNiggliAngles( const Kernel::V3D & a_dir, - const Kernel::V3D & b_dir, - const Kernel::V3D & c_dir, - double epsilon ); - - /// Construct a newUB corresponding to a Niggli cell from the given UB - static bool MakeNiggliUB( const Kernel::DblMatrix & UB, - Kernel::DblMatrix & newUB ); + private: /// Static reference to the logger class diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/NiggliCell.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/NiggliCell.h new file mode 100644 index 000000000000..a0cf0b981506 --- /dev/null +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/NiggliCell.h @@ -0,0 +1,77 @@ +#ifndef MANTID_GEOMETRY_NiggliCell_H_ +#define MANTID_GEOMETRY_NiggliCell_H_ + +#include "MantidGeometry/Crystal/UnitCell.h" +#include + +namespace Mantid +{ +namespace Geometry +{ + /** @class NiggliCell NiggliCell.h Geometry/Crystal/NiggliCell.h + Class to implement UB matrix. + See documentation about UB matrix in the Mantid repository.\n + + @author Andrei Savici, SNS, ORNL + @date 2011-04-15 + Copyright © 2007-8 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: . + Code Documentation is available at: + */ + class MANTID_GEOMETRY_DLL NiggliCell: public UnitCell + { + public: + // Default constructor. a = b = c = 1, alpha = beta = gamma = 90 degrees + NiggliCell(const Kernel::DblMatrix & Umatrix = Kernel::DblMatrix(3,3,true)); + //Copy constructor + NiggliCell(const NiggliCell& other); + // a,b,c constructor + NiggliCell(const double _a,const double _b,const double _c, + const Kernel::DblMatrix & Umatrix = Kernel::DblMatrix(3,3,true)); + //a,b,c,alpha,beta,gamma constructor + NiggliCell(const double _a,const double _b,const double _c,const double _alpha,const double _beta, + const double _gamma, const Kernel::DblMatrix & Umatrix = Kernel::DblMatrix(3,3,true), + const int angleunit=angDegrees); + //UnitCell constructor + NiggliCell(const UnitCell & uc , const Kernel::DblMatrix & Umatrix = Kernel::DblMatrix(3,3,true)); + //UnitCell constructor + NiggliCell(const UnitCell * uc , const Kernel::DblMatrix & Umatrix = Kernel::DblMatrix(3,3,true)); + // Destructor + virtual ~NiggliCell(); + + // Access private variables + /// Check if a,b,c cell has angles satifying Niggli condition within epsilon + static bool HasNiggliAngles( const Kernel::V3D & a_dir, + const Kernel::V3D & b_dir, + const Kernel::V3D & c_dir, + double epsilon ); + + /// Construct a newUB corresponding to a Niggli cell from the given UB + static bool MakeNiggliUB( const Kernel::DblMatrix & UB, + Kernel::DblMatrix & newUB ); + + private: + Kernel::DblMatrix U; + Kernel::DblMatrix UB; + + + }; +} // namespace Mantid +} // namespace Geometry +#endif /* MANTID_GEOMETRY_UNITCELL_H_ */ diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp index e912cff68942..a31425045958 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp @@ -1,4 +1,5 @@ #include "MantidGeometry/Crystal/IndexingUtils.h" +#include "MantidGeometry/Crystal/NiggliCell.h" #include "MantidKernel/Quat.h" #include #include "MantidGeometry/Crystal/OrientedLattice.h" @@ -29,69 +30,6 @@ namespace const double RAD_TO_DEG = 180. / M_PI; } -/** - Comparator function for sorting list of UB matrices based on the sum - of the lengths of the corresponding real space cell edge lengths - |a|+|b|+|C| - */ -static bool CompareABCsum( const DblMatrix & UB_1, const DblMatrix & UB_2 ) -{ - V3D a1; - V3D b1; - V3D c1; - V3D a2; - V3D b2; - V3D c2; - OrientedLattice::GetABC( UB_1, a1, b1, c1 ); - OrientedLattice::GetABC( UB_2, a2, b2, c2 ); - - double sum_1 = a1.norm() + b1.norm() + c1.norm(); - double sum_2 = a2.norm() + b2.norm() + c2.norm(); - - return (sum_1 < sum_2); -} - - -/** - Get the cell angles for the unit cell corresponding to matrix UB - and calculate the sum of the differences of the cell angles from 90 - degrees. - @param UB the UB matrix - @return The sum of the difference of the cell angles from 90 degrees. - */ -static double GetDiffFrom90Sum( const DblMatrix & UB ) -{ - V3D a; - V3D b; - V3D c; - - if ( !OrientedLattice::GetABC( UB, a, b, c ) ) - return -1; - - double alpha = b.angle( c ) * RAD_TO_DEG; - double beta = c.angle( a ) * RAD_TO_DEG; - double gamma = a.angle( b ) * RAD_TO_DEG; - - double sum = fabs( alpha - 90.0 ) + - fabs( beta - 90.0 ) + - fabs( gamma - 90.0 ); - - return sum; -} - - -/** - Comparator to sort a list of UBs in decreasing order based on - the difference of cell angles from 90 degrees. -*/ -static bool CompareDiffFrom90( const DblMatrix & UB_1, const DblMatrix & UB_2 ) -{ - double sum_1 = GetDiffFrom90Sum( UB_1 ); - double sum_2 = GetDiffFrom90Sum( UB_2 ); - - return ( sum_2 < sum_1 ); -} - /** @@ -518,7 +456,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, } } - if ( MakeNiggliUB( UB, temp_UB ) ) + if ( NiggliCell::MakeNiggliUB( UB, temp_UB ) ) UB = temp_UB; return fit_error; @@ -664,7 +602,7 @@ double IndexingUtils::Find_UB( DblMatrix & UB, } } - if ( MakeNiggliUB( UB, temp_UB ) ) + if ( NiggliCell::MakeNiggliUB( UB, temp_UB ) ) UB = temp_UB; return fit_error; @@ -2962,34 +2900,22 @@ int IndexingUtils::SelectDirection( V3D & best_direction, bool IndexingUtils::GetLatticeParameters( const DblMatrix & UB, std::vector & lattice_par ) { - V3D a_dir; - V3D b_dir; - V3D c_dir; + OrientedLattice o_lattice; + o_lattice.setUB( UB ); - if ( ! OrientedLattice::GetABC( UB, a_dir, b_dir, c_dir ) ) - { - return false; - } + lattice_par.clear(); + lattice_par.push_back( o_lattice.a() ); + lattice_par.push_back( o_lattice.b() ); + lattice_par.push_back( o_lattice.c() ); - lattice_par.clear(); - lattice_par.push_back( a_dir.norm() ); - lattice_par.push_back( b_dir.norm() ); - lattice_par.push_back( c_dir.norm() ); - - double alpha = b_dir.angle( c_dir ) * RAD_TO_DEG; - double beta = c_dir.angle( a_dir ) * RAD_TO_DEG; - double gamma = a_dir.angle( b_dir ) * RAD_TO_DEG; - lattice_par.push_back( alpha ); - lattice_par.push_back( beta ); - lattice_par.push_back( gamma ); + lattice_par.push_back( o_lattice.alpha() ); + lattice_par.push_back( o_lattice.beta() ); + lattice_par.push_back( o_lattice.gamma() ); - V3D acrossb = a_dir.cross_prod( b_dir ); - double volume = acrossb.scalar_prod( c_dir ); - - lattice_par.push_back( fabs(volume) ); // keep volume > 0 even if - // cell is left handed - return true; + lattice_par.push_back( o_lattice.volume() ); // keep volume > 0 even if + // cell is left handed + return true; } @@ -3016,182 +2942,3 @@ std::string IndexingUtils::GetLatticeParameterString( const DblMatrix & UB ) } -/** - Check if a,b,c cell has angles satifying Niggli condition within epsilon. - Specifically, check if all angles are strictly less than 90 degrees, - or all angles are greater than or equal to 90 degrees. The inequality - requirements are relaxed by an amount specified by the paramter epsilon - to accommodate some experimental and/or rounding error in the calculated - angles. - - @param a_dir Vector in the direction of the real cell edge vector 'a' - @param b_dir Vector in the direction of the real cell edge vector 'b' - @param c_dir Vector in the direction of the real cell edge vector 'c' - @param epsilon Tolerance (in degrees) around 90 degrees. For example - an angle theta will be considered strictly less than 90 - degrees, if it is less than 90+epsilon. - @return true if all angles are less than 90 degrees, or if all angles - are greater than or equal to 90 degrees. - */ -bool IndexingUtils::HasNiggliAngles( const V3D & a_dir, - const V3D & b_dir, - const V3D & c_dir, - double epsilon ) -{ - double alpha = b_dir.angle( c_dir ) * RAD_TO_DEG; - double beta = c_dir.angle( a_dir ) * RAD_TO_DEG; - double gamma = a_dir.angle( b_dir ) * RAD_TO_DEG; - - if ( alpha < 90+epsilon && beta < 90+epsilon && gamma < 90+epsilon ) - { - return true; - } - - if ( alpha >= 90-epsilon && beta >= 90-epsilon && gamma >= 90-epsilon ) - { - return true; - } - - return false; -} - - -/** - * Try to find a UB that is equivalent to the original UB, but corresponds - * to a Niggli reduced cell with the smallest sum of edge lengths and - * with angles that are farthest from 90 degrees. - * - * @param UB The original UB - * @param newUB Returns the newUB - * - * @return True if a possibly constructive change was made and newUB has been - * set to a new matrix. It returns false if no constructive change was found - * and newUB is just set to the original UB. - */ - -bool IndexingUtils::MakeNiggliUB( const DblMatrix & UB, - DblMatrix & newUB ) -{ - V3D a; - V3D b; - V3D c; - - if ( !OrientedLattice::GetABC( UB, a, b, c ) ) - { - return false; - } - - V3D v1; - V3D v2; - V3D v3; - // first make a list of linear combinations - // of vectors a,b,c with coefficients up to 5 - std::vector directions; - int N_coeff = 5; - for ( int i = -N_coeff; i <= N_coeff; i++ ) - { - for ( int j = -N_coeff; j <= N_coeff; j++ ) - { - for ( int k = -N_coeff; k <= N_coeff; k++ ) - { - if ( i != 0 || j != 0 || k != 0 ) - { - v1 = a * i; - v2 = b * j; - v3 = c * k; - V3D sum(v1); - sum += v2; - sum += v3; - directions.push_back( sum ); - } - } - } - } - // next sort the list of linear combinations - // in order of increasing length - std::sort( directions.begin(), directions.end(), V3D::CompareMagnitude ); - - // next form a list of possible UB matrices - // using sides from the list of linear - // combinations, using shorter directions first. - // Keep trying more until 25 UBs are found. - // Only keep UBs corresponding to cells with - // at least a minimum cell volume - std::vector UB_list; - - size_t num_needed = 25; - size_t max_to_try = 5; - while ( UB_list.size() < num_needed && max_to_try < directions.size() ) - { - max_to_try *= 2; - size_t num_to_try = std::min( max_to_try, directions.size() ); - - V3D acrossb; - double vol = 0; - double min_vol = .1f; // what should this be? 0.1 works OK, but...? - for ( size_t i = 0; i < num_to_try-2; i++ ) - { - a = directions[i]; - for ( size_t j = i+1; j < num_to_try-1; j++ ) - { - b = directions[j]; - acrossb = a.cross_prod(b); - for ( size_t k = j+1; k < num_to_try; k++ ) - { - c = directions[k]; - vol = acrossb.scalar_prod( c ); - if ( vol > min_vol && HasNiggliAngles( a, b, c, 0.01 ) ) - { - Matrix new_tran(3,3,false); - OrientedLattice::GetUB( new_tran, a, b, c ); - UB_list.push_back( new_tran ); - } - } - } - } - } - // if no valid UBs could be formed, return - // false and the original UB - if ( UB_list.empty() ) - { - newUB = UB; - return false; - } - // now sort the UB's in order of increasing - // total side length |a|+|b|+|c| - std::sort( UB_list.begin(), UB_list.end(), CompareABCsum ); - - // keep only those UB's with total side length - // within .1% of the first one. This can't - // be much larger or "bad" UBs are made for - // some tests with 5% noise - double length_tol = 0.001; - double total_length; - - std::vector short_list; - short_list.push_back( UB_list[0] ); - OrientedLattice::GetABC( short_list[0], a, b, c ); - total_length = a.norm() + b.norm() + c.norm(); - - bool got_short_list = false; - size_t i = 1; - while ( i < UB_list.size() && !got_short_list ) - { - OrientedLattice::GetABC( UB_list[i], v1, v2, v3 ); - double next_length = v1.norm() + v2.norm() + v3.norm(); - if ( fabs(next_length - total_length)/total_length < length_tol ) - short_list.push_back( UB_list[i] ); - else - got_short_list = true; - i++; - } - // now sort on the basis of difference of cell - // angles from 90 degrees and return the one - // with angles most different from 90 - std::sort( short_list.begin(), short_list.end(), CompareDiffFrom90 ); - - newUB = short_list[0]; - - return true; -} - diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/NiggliCell.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/NiggliCell.cpp new file mode 100644 index 000000000000..c8177515abe1 --- /dev/null +++ b/Code/Mantid/Framework/Geometry/src/Crystal/NiggliCell.cpp @@ -0,0 +1,360 @@ +#include "MantidGeometry/Crystal/NiggliCell.h" +#include "MantidGeometry/Crystal/OrientedLattice.h" +#include "MantidKernel/Quat.h" +#include +#include "MantidGeometry/Crystal/OrientedLattice.h" +#include +#include +#include + +namespace Mantid +{ +namespace Geometry +{ + using Mantid::Kernel::DblMatrix; + using Mantid::Kernel::V3D; + using Mantid::Kernel::Matrix; + + namespace { + const double TWO_PI = 2.*M_PI; + const double DEG_TO_RAD = M_PI / 180.; + const double RAD_TO_DEG = 180. / M_PI; + } + /** + Comparator function for sorting list of UB matrices based on the sum + of the lengths of the corresponding real space cell edge lengths + |a|+|b|+|C| + */ + static bool CompareABCsum( const DblMatrix & UB_1, const DblMatrix & UB_2 ) + { + V3D a1; + V3D b1; + V3D c1; + V3D a2; + V3D b2; + V3D c2; + OrientedLattice::GetABC( UB_1, a1, b1, c1 ); + OrientedLattice::GetABC( UB_2, a2, b2, c2 ); + + double sum_1 = a1.norm() + b1.norm() + c1.norm(); + double sum_2 = a2.norm() + b2.norm() + c2.norm(); + + return (sum_1 < sum_2); + } + + + /** + Get the cell angles for the unit cell corresponding to matrix UB + and calculate the sum of the differences of the cell angles from 90 + degrees. + @param UB the UB matrix + @return The sum of the difference of the cell angles from 90 degrees. + */ + static double GetDiffFrom90Sum( const DblMatrix & UB ) + { + V3D a; + V3D b; + V3D c; + + if ( !OrientedLattice::GetABC( UB, a, b, c ) ) + return -1; + + double alpha = b.angle( c ) * RAD_TO_DEG; + double beta = c.angle( a ) * RAD_TO_DEG; + double gamma = a.angle( b ) * RAD_TO_DEG; + + double sum = fabs( alpha - 90.0 ) + + fabs( beta - 90.0 ) + + fabs( gamma - 90.0 ); + + return sum; + } + + + /** + Comparator to sort a list of UBs in decreasing order based on + the difference of cell angles from 90 degrees. + */ + static bool CompareDiffFrom90( const DblMatrix & UB_1, const DblMatrix & UB_2 ) + { + double sum_1 = GetDiffFrom90Sum( UB_1 ); + double sum_2 = GetDiffFrom90Sum( UB_2 ); + + return ( sum_2 < sum_1 ); + } + /** Default constructor + @param Umatrix :: orientation matrix U. By default this will be identity matrix + */ + NiggliCell::NiggliCell(const DblMatrix & Umatrix) : UnitCell() + { + if (Umatrix.isRotation()==true) + { + U=Umatrix; + UB=U*getB(); + } + else throw std::invalid_argument("U is not a proper rotation"); + } + + /** Copy constructor + @param other :: The NiggliCell from which to copy information + */ + NiggliCell::NiggliCell(const NiggliCell& other) : UnitCell(other),U(other.U),UB(other.UB) + { + } + + /** Constructor + @param _a :: lattice parameter \f$ a \f$ with \f$\alpha = \beta = \gamma = 90^\circ \f$ + @param _b :: lattice parameter \f$ b \f$ with \f$\alpha = \beta = \gamma = 90^\circ \f$ + @param _c :: lattice parameter \f$ c \f$ with \f$\alpha = \beta = \gamma = 90^\circ \f$ + @param Umatrix :: orientation matrix U + */ + NiggliCell::NiggliCell(const double _a,const double _b,const double _c, + const DblMatrix &Umatrix) : UnitCell(_a,_b,_c) + { + if (Umatrix.isRotation()==true) + { + U=Umatrix; + UB=U*getB(); + } + else throw std::invalid_argument("U is not a proper rotation"); + } + + /** Constructor + @param _a :: lattice parameter \f$ a \f$ + @param _b :: lattice parameter \f$ b \f$ + @param _c :: lattice parameter \f$ c \f$ + @param _alpha :: lattice parameter \f$ \alpha \f$ + @param _beta :: lattice parameter \f$ \beta \f$ + @param _gamma :: lattice parameter \f$ \gamma \f$ + @param angleunit :: units for angle, of type #AngleUnits. Default is degrees. + @param Umatrix :: orientation matrix U + */ + NiggliCell::NiggliCell(const double _a,const double _b,const double _c,const double _alpha, + const double _beta,const double _gamma, const DblMatrix &Umatrix, + const int angleunit) + :UnitCell(_a,_b,_c,_alpha,_beta,_gamma,angleunit) + { + if (Umatrix.isRotation()==true) + { + U=Umatrix; + UB=U*getB(); + } + else throw std::invalid_argument("U is not a proper rotation"); + } + + /** UnitCell constructor + @param uc :: UnitCell + @param Umatrix :: orientation matrix U. By default this will be identity matrix + */ + NiggliCell::NiggliCell(const UnitCell & uc, const DblMatrix & Umatrix) + : UnitCell(uc),U(Umatrix) + { + if (Umatrix.isRotation()==true) + { + U=Umatrix; + UB=U*getB(); + } + else throw std::invalid_argument("U is not a proper rotation"); + } + + NiggliCell::NiggliCell(const UnitCell * uc , const DblMatrix & Umatrix) + : UnitCell(uc),U(Umatrix) + { + if (Umatrix.isRotation()==true) + { + U=Umatrix; + UB=U*getB(); + } + else throw std::invalid_argument("U is not a proper rotation"); + } + + /// Destructor + NiggliCell::~NiggliCell() + { + } + + + + + /** + Check if a,b,c cell has angles satifying Niggli condition within epsilon. + Specifically, check if all angles are strictly less than 90 degrees, + or all angles are greater than or equal to 90 degrees. The inequality + requirements are relaxed by an amount specified by the paramter epsilon + to accommodate some experimental and/or rounding error in the calculated + angles. + + @param a_dir Vector in the direction of the real cell edge vector 'a' + @param b_dir Vector in the direction of the real cell edge vector 'b' + @param c_dir Vector in the direction of the real cell edge vector 'c' + @param epsilon Tolerance (in degrees) around 90 degrees. For example + an angle theta will be considered strictly less than 90 + degrees, if it is less than 90+epsilon. + @return true if all angles are less than 90 degrees, or if all angles + are greater than or equal to 90 degrees. + */ + bool NiggliCell::HasNiggliAngles( const V3D & a_dir, + const V3D & b_dir, + const V3D & c_dir, + double epsilon ) + { + double alpha = b_dir.angle( c_dir ) * RAD_TO_DEG; + double beta = c_dir.angle( a_dir ) * RAD_TO_DEG; + double gamma = a_dir.angle( b_dir ) * RAD_TO_DEG; + + if ( alpha < 90+epsilon && beta < 90+epsilon && gamma < 90+epsilon ) + { + return true; + } + + if ( alpha >= 90-epsilon && beta >= 90-epsilon && gamma >= 90-epsilon ) + { + return true; + } + + return false; + } + + + /** + * Try to find a UB that is equivalent to the original UB, but corresponds + * to a Niggli reduced cell with the smallest sum of edge lengths and + * with angles that are farthest from 90 degrees. + * + * @param UB The original UB + * @param newUB Returns the newUB + * + * @return True if a possibly constructive change was made and newUB has been + * set to a new matrix. It returns false if no constructive change was found + * and newUB is just set to the original UB. + */ + + bool NiggliCell::MakeNiggliUB( const DblMatrix & UB, + DblMatrix & newUB ) + { + V3D a; + V3D b; + V3D c; + + if ( !OrientedLattice::GetABC( UB, a, b, c ) ) + { + return false; + } + + V3D v1; + V3D v2; + V3D v3; + // first make a list of linear combinations + // of vectors a,b,c with coefficients up to 5 + std::vector directions; + int N_coeff = 5; + for ( int i = -N_coeff; i <= N_coeff; i++ ) + { + for ( int j = -N_coeff; j <= N_coeff; j++ ) + { + for ( int k = -N_coeff; k <= N_coeff; k++ ) + { + if ( i != 0 || j != 0 || k != 0 ) + { + v1 = a * i; + v2 = b * j; + v3 = c * k; + V3D sum(v1); + sum += v2; + sum += v3; + directions.push_back( sum ); + } + } + } + } + // next sort the list of linear combinations + // in order of increasing length + std::sort( directions.begin(), directions.end(), V3D::CompareMagnitude ); + + // next form a list of possible UB matrices + // using sides from the list of linear + // combinations, using shorter directions first. + // Keep trying more until 25 UBs are found. + // Only keep UBs corresponding to cells with + // at least a minimum cell volume + std::vector UB_list; + + size_t num_needed = 25; + size_t max_to_try = 5; + while ( UB_list.size() < num_needed && max_to_try < directions.size() ) + { + max_to_try *= 2; + size_t num_to_try = std::min( max_to_try, directions.size() ); + + V3D acrossb; + double vol = 0; + double min_vol = .1f; // what should this be? 0.1 works OK, but...? + for ( size_t i = 0; i < num_to_try-2; i++ ) + { + a = directions[i]; + for ( size_t j = i+1; j < num_to_try-1; j++ ) + { + b = directions[j]; + acrossb = a.cross_prod(b); + for ( size_t k = j+1; k < num_to_try; k++ ) + { + c = directions[k]; + vol = acrossb.scalar_prod( c ); + if ( vol > min_vol && HasNiggliAngles( a, b, c, 0.01 ) ) + { + Matrix new_tran(3,3,false); + OrientedLattice::GetUB( new_tran, a, b, c ); + UB_list.push_back( new_tran ); + } + } + } + } + } + // if no valid UBs could be formed, return + // false and the original UB + if ( UB_list.empty() ) + { + newUB = UB; + return false; + } + // now sort the UB's in order of increasing + // total side length |a|+|b|+|c| + std::sort( UB_list.begin(), UB_list.end(), CompareABCsum ); + + // keep only those UB's with total side length + // within .1% of the first one. This can't + // be much larger or "bad" UBs are made for + // some tests with 5% noise + double length_tol = 0.001; + double total_length; + + std::vector short_list; + short_list.push_back( UB_list[0] ); + OrientedLattice::GetABC( short_list[0], a, b, c ); + total_length = a.norm() + b.norm() + c.norm(); + + bool got_short_list = false; + size_t i = 1; + while ( i < UB_list.size() && !got_short_list ) + { + OrientedLattice::GetABC( UB_list[i], v1, v2, v3 ); + double next_length = v1.norm() + v2.norm() + v3.norm(); + if ( fabs(next_length - total_length)/total_length < length_tol ) + short_list.push_back( UB_list[i] ); + else + got_short_list = true; + i++; + } + // now sort on the basis of difference of cell + // angles from 90 degrees and return the one + // with angles most different from 90 + std::sort( short_list.begin(), short_list.end(), CompareDiffFrom90 ); + + newUB = short_list[0]; + + return true; + } + + +}//Namespace Geometry +}//Namespace Mantid diff --git a/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h b/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h index 7bdbe7484b9a..b92a4a6cf4ac 100644 --- a/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h +++ b/Code/Mantid/Framework/Geometry/test/IndexingUtilsTest.h @@ -19,7 +19,6 @@ class IndexingUtilsTest : public CxxTest::TestSuite { public: -#define PI 3.141592653589793238 static std::vector getNatroliteQs() { @@ -75,19 +74,6 @@ class IndexingUtilsTest : public CxxTest::TestSuite } - static Matrix getSiliconUB() - { - Matrix UB(3,3,false); - V3D row_0( -0.147196, -0.141218, 0.304286 ); - V3D row_1( 0.106642, 0.120341, 0.090518 ); - V3D row_2( -0.261273, 0.258426, -0.006190 ); - UB.setRow( 0, row_0 ); - UB.setRow( 1, row_1 ); - UB.setRow( 2, row_2 ); - return UB; - } - - static void ShowLatticeParameters( Matrix UB ) { Matrix UB_inv(3,3,false); @@ -96,9 +82,9 @@ class IndexingUtilsTest : public CxxTest::TestSuite V3D a_dir( UB_inv[0][0], UB_inv[0][1], UB_inv[0][2] ); V3D b_dir( UB_inv[1][0], UB_inv[1][1], UB_inv[1][2] ); V3D c_dir( UB_inv[2][0], UB_inv[2][1], UB_inv[2][2] ); - double alpha = b_dir.angle( c_dir ) * 180 / PI; - double beta = c_dir.angle( a_dir ) * 180 / PI; - double gamma = a_dir.angle( b_dir ) * 180 / PI; + double alpha = b_dir.angle( c_dir ) * 180 / M_PI; + double beta = c_dir.angle( a_dir ) * 180 / M_PI; + double gamma = a_dir.angle( b_dir ) * 180 / M_PI; std::cout << "-------------------------------------------" << std::endl; std::cout << "a = " << a_dir << " " << a_dir.norm() << std::endl; std::cout << "b = " << b_dir << " " << b_dir.norm() << std::endl; @@ -556,15 +542,15 @@ class IndexingUtilsTest : public CxxTest::TestSuite V3D a_dir( 1, 2, 3 ); V3D b_dir( -3, 2, 1 ); - double gamma = a_dir.angle( b_dir ) * 180.0 / PI; + double gamma = a_dir.angle( b_dir ) * 180.0 / M_PI; double alpha = 123; double beta = 74; double c_length = 10; V3D result = IndexingUtils::Make_c_dir( a_dir, b_dir, c_length, alpha, beta, gamma ); - double alpha_calc = result.angle( b_dir ) * 180 / PI; - double beta_calc = result.angle( a_dir ) * 180 / PI; + double alpha_calc = result.angle( b_dir ) * 180 / M_PI; + double beta_calc = result.angle( a_dir ) * 180 / M_PI; TS_ASSERT_DELTA( result.norm(), c_length, 1e-5 ); TS_ASSERT_DELTA( alpha_calc, alpha, 1e-5 ); @@ -1008,86 +994,6 @@ class IndexingUtilsTest : public CxxTest::TestSuite TS_ASSERT_DELTA( lat_par[i], correct_value[i], 1e-3 ); } - - void test_HasNiggleAngles() - { - V3D a(1,0,0); - V3D b(0,1,0); - V3D c(0,0,1); - - TS_ASSERT_EQUALS( IndexingUtils::HasNiggliAngles(a, b, c, 0.001 ), true); - - V3D b1( 0.1, 1, 0 ); - V3D c1(-0.1, 0, 1 ); - - TS_ASSERT_EQUALS( IndexingUtils::HasNiggliAngles(a, b1, c1, 0.001), false); - - V3D a2( 1, 0.1, 0.1 ); - V3D b2( 0.1, 1, 0.1 ); - V3D c2( 0.1, 0.1, 1 ); - - TS_ASSERT_EQUALS( IndexingUtils::HasNiggliAngles(a2, b2, c2, 0.001), true); - - V3D a3( 1, -0.1, -0.1 ); - V3D b3( -0.1, 1, -0.1 ); - V3D c3( -0.1, -0.1, 1 ); - - TS_ASSERT_EQUALS( IndexingUtils::HasNiggliAngles(a3, b3, c3, 0.001), true); - } - - - void test_MakeNiggliUB() - { - double answer[3][3] = { { -0.147196, -0.141218, 0.304286 }, - { 0.106642, 0.120341, 0.090518 }, - { -0.261273, 0.258426, -0.006190 } }; - - Matrix newUB(3,3,false); - Matrix UB = getSiliconUB(); - UB = UB * 1.0; - - TS_ASSERT( IndexingUtils::MakeNiggliUB( UB, newUB ) ); - - for ( size_t row = 0; row < 3; row++ ) - for ( size_t col = 0; col < 3; col++ ) - TS_ASSERT_DELTA( newUB[row][col], answer[row][col], 1e-5 ); - } - - - void test_MakeNiggliUB2() - { - // Make a fake UB matrix with: - // gamma > 90 deg - // alpha < 90 deg - Matrix UB(3,3, true); - V3D a(10,0,0); - V3D b(-5,5,0); - V3D c(0,5,5); - OrientedLattice::GetUB(UB, a,b,c); - - Matrix newUB(3,3,false); - - TS_ASSERT( IndexingUtils::MakeNiggliUB( UB, newUB ) ); - - // Extract the a,b,c vectors - V3D a_dir; - V3D b_dir; - V3D c_dir; - OrientedLattice::GetABC(newUB, a_dir,b_dir,c_dir); - double alpha = b_dir.angle( c_dir ) * 180.0/PI; - double beta = c_dir.angle( a_dir ) * 180.0/PI; - double gamma = a_dir.angle( b_dir ) * 180.0/PI; - // All vectors have two components of length 5.0 - double norm = sqrt(50.0); - TS_ASSERT_DELTA( a_dir.norm(), norm, 1e-3 ); - TS_ASSERT_DELTA( b_dir.norm(), norm, 1e-3 ); - TS_ASSERT_DELTA( c_dir.norm(), norm, 1e-3 ); - // Angles are 60 degrees - TS_ASSERT_DELTA( alpha, 60, 1e-1 ); - TS_ASSERT_DELTA( beta, 60, 1e-1 ); - TS_ASSERT_DELTA( gamma, 60, 1e-1 ); - - } }; #endif /* MANTID_GEOMETRY_INDEXING_UTILS_TEST_H_ */ diff --git a/Code/Mantid/Framework/Geometry/test/NiggliCellTest.h b/Code/Mantid/Framework/Geometry/test/NiggliCellTest.h new file mode 100644 index 000000000000..060290591e30 --- /dev/null +++ b/Code/Mantid/Framework/Geometry/test/NiggliCellTest.h @@ -0,0 +1,132 @@ +#ifndef MANTID_GEOMETRY_NiggliCellTEST_H_ +#define MANTID_GEOMETRY_NiggliCellTEST_H_ + +#include +#include +#include +#include "MantidKernel/Matrix.h" +#include "MantidGeometry/Crystal/NiggliCell.h" +#include "MantidGeometry/Crystal/OrientedLattice.h" +#include "MantidTestHelpers/NexusTestHelper.h" + +using namespace Mantid::Geometry; +using Mantid::Kernel::V3D; +using Mantid::Kernel::DblMatrix; +using Mantid::Kernel::Matrix; + +class NiggliCellTest : public CxxTest::TestSuite +{ +public: + + + static Matrix getSiliconUB() + { + Matrix UB(3,3,false); + V3D row_0( -0.147196, -0.141218, 0.304286 ); + V3D row_1( 0.106642, 0.120341, 0.090518 ); + V3D row_2( -0.261273, 0.258426, -0.006190 ); + UB.setRow( 0, row_0 ); + UB.setRow( 1, row_1 ); + UB.setRow( 2, row_2 ); + return UB; + } + /// test constructors, access to some of the variables + void test_Simple() + { + + NiggliCell u1,u2(3,4,5),u3(2,3,4,85.,95.,100),u4; + u4=u2; + TS_ASSERT_EQUALS(u1.a1(),1); + TS_ASSERT_EQUALS(u1.alpha(),90); + TS_ASSERT_DELTA(u2.b1(),1./3.,1e-10); + TS_ASSERT_DELTA(u2.alphastar(),90,1e-10); + TS_ASSERT_DELTA(u4.volume(),1./u2.recVolume(),1e-10); + u2.seta(3); + TS_ASSERT_DELTA(u2.a(),3,1e-10); + } + +void test_HasNiggleAngles() +{ + V3D a(1,0,0); + V3D b(0,1,0); + V3D c(0,0,1); + + TS_ASSERT_EQUALS( NiggliCell::HasNiggliAngles(a, b, c, 0.001 ), true); + + V3D b1( 0.1, 1, 0 ); + V3D c1(-0.1, 0, 1 ); + + TS_ASSERT_EQUALS( NiggliCell::HasNiggliAngles(a, b1, c1, 0.001), false); + + V3D a2( 1, 0.1, 0.1 ); + V3D b2( 0.1, 1, 0.1 ); + V3D c2( 0.1, 0.1, 1 ); + + TS_ASSERT_EQUALS( NiggliCell::HasNiggliAngles(a2, b2, c2, 0.001), true); + + V3D a3( 1, -0.1, -0.1 ); + V3D b3( -0.1, 1, -0.1 ); + V3D c3( -0.1, -0.1, 1 ); + + TS_ASSERT_EQUALS( NiggliCell::HasNiggliAngles(a3, b3, c3, 0.001), true); +} + + +void test_MakeNiggliUB() +{ + double answer[3][3] = { { -0.147196, -0.141218, 0.304286 }, + { 0.106642, 0.120341, 0.090518 }, + { -0.261273, 0.258426, -0.006190 } }; + + Matrix newUB(3,3,false); + Matrix UB = getSiliconUB(); + UB = UB * 1.0; + + TS_ASSERT( NiggliCell::MakeNiggliUB( UB, newUB ) ); + + for ( size_t row = 0; row < 3; row++ ) + for ( size_t col = 0; col < 3; col++ ) + TS_ASSERT_DELTA( newUB[row][col], answer[row][col], 1e-5 ); +} + + +void test_MakeNiggliUB2() +{ + // Make a fake UB matrix with: + // gamma > 90 deg + // alpha < 90 deg + Matrix UB(3,3, true); + V3D a(10,0,0); + V3D b(-5,5,0); + V3D c(0,5,5); + OrientedLattice::GetUB(UB, a,b,c); + + Matrix newUB(3,3,false); + + TS_ASSERT( NiggliCell::MakeNiggliUB( UB, newUB ) ); + + // Extract the a,b,c vectors + V3D a_dir; + V3D b_dir; + V3D c_dir; + OrientedLattice::GetABC(newUB, a_dir,b_dir,c_dir); + double alpha = b_dir.angle( c_dir ) * 180.0/M_PI; + double beta = c_dir.angle( a_dir ) * 180.0/M_PI; + double gamma = a_dir.angle( b_dir ) * 180.0/M_PI; + // All vectors have two components of length 5.0 + double norm = sqrt(50.0); + TS_ASSERT_DELTA( a_dir.norm(), norm, 1e-3 ); + TS_ASSERT_DELTA( b_dir.norm(), norm, 1e-3 ); + TS_ASSERT_DELTA( c_dir.norm(), norm, 1e-3 ); + // Angles are 60 degrees + TS_ASSERT_DELTA( alpha, 60, 1e-1 ); + TS_ASSERT_DELTA( beta, 60, 1e-1 ); + TS_ASSERT_DELTA( gamma, 60, 1e-1 ); + +} + +}; + + +#endif /* MANTID_GEOMETRY_NiggliCellTEST_H_ */ + From 1f6465a81119051d3c37901c6489c503b6d04bc2 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Fri, 13 Dec 2013 16:29:53 -0500 Subject: [PATCH 211/403] Refs #8251 for old geometry without numbered pixels --- .../Framework/Crystal/src/SaveIsawPeaks.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp index e25d46fa32f2..3ac03bcb3cae 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveIsawPeaks.cpp @@ -381,16 +381,14 @@ namespace Crystal } else { - std::string bankName0 = bankName; - //Only works for WISH - bankName0.erase(0,4); - std::ostringstream pixelString; - pixelString << inst->getName() << "/" << bankName0 << "/" < component = inst->getComponentByName(pixelString.str()); - boost::shared_ptr pixel = boost::dynamic_pointer_cast(component); - return pixel->getPos(); + std::vector children; + boost::shared_ptr asmb = boost::dynamic_pointer_cast(parent); + asmb->getChildren(children, false); + boost::shared_ptr asmb2 = boost::dynamic_pointer_cast(children[col]); + std::vector grandchildren; + asmb2->getChildren(grandchildren,false); + Geometry::IComponent_const_sptr first = grandchildren[row]; + return first->getPos(); } } void SaveIsawPeaks::sizeBanks(std::string bankName, int& NCOLS, int& NROWS, double& xsize, double& ysize) From b2d92d8607875f4bbe823cbdfc2900b444de6576 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Fri, 13 Dec 2013 16:34:29 -0500 Subject: [PATCH 212/403] Refs #8621 Correct several description bits Make the descriptions of Gamma and Amplitude correct and consitent in the header, source, and wiki files. --- .../CurveFitting/inc/MantidCurveFitting/Lorentzian.h | 7 ++++--- Code/Mantid/Framework/CurveFitting/src/Lorentzian.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h index 115395710c6e..e966eef72b61 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h @@ -12,14 +12,15 @@ namespace Mantid { /** Provide lorentzian peak shape function interface to IPeakFunction. - I.e. the function: \frac{A}{\pi}( \Gamma/((x-PeakCentre)^2+HWHM^2) ). + I.e. the function: \frac{A}{\pi}( \Gamma/2((x-PeakCentre)^2+(\Gamma/2)^2) ). + \Gamma/2 (HWHM) - half-width at half-maximum Lorentzian parameters:
    -
  • Amplitude - Maximum height of peak at x=PeakCentre(default 1.0)
  • +
  • Amplitude - Intensity scaling (default 1.0)
  • PeakCentre - centre of peak (default 0.0)
  • -
  • HWHM - half-width half-maximum (default 0.0)
  • +
  • FWHM - Full-width half-maximum (default 0.0)
Copyright © 2007-8 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory diff --git a/Code/Mantid/Framework/CurveFitting/src/Lorentzian.cpp b/Code/Mantid/Framework/CurveFitting/src/Lorentzian.cpp index d9cc3a0f9be2..039f21e114d0 100644 --- a/Code/Mantid/Framework/CurveFitting/src/Lorentzian.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/Lorentzian.cpp @@ -5,12 +5,12 @@ A Lorentzian function is defined as: where:
    -
  • A (Amplitude) - Maximum peak height at peak centre
  • +
  • A (Amplitude) - Intensity scaling
  • x_0 (PeakCentre) - centre of peak
  • -
  • \Gamma (HWHM) - half-width at half-maximum
  • +
  • \Gamma/2 (HWHM) - half-width at half-maximum
-Note that the FWHM (Full Width Half Maximum) equals two times HWHM, and the integral over the Lorentzian equals 1. +Note that the FWHM (Full Width Half Maximum) equals two times HWHM, and the integral over the Lorentzian equals the intensity scaling A. The figure below illustrate this symmetric peakshape function fitted to a TOF peak: @@ -35,9 +35,9 @@ DECLARE_FUNCTION(Lorentzian); void Lorentzian::init() { - declareParameter("Amplitude", 1.0, "Maximum height of peak when x=x0"); + declareParameter("Amplitude", 1.0, "Intensity scaling"); declareParameter("PeakCentre", 0.0, "Centre of peak"); - declareParameter("FWHM", 0.0, "Falf-width at half-maximum"); + declareParameter("FWHM", 0.0, "Full-width at half-maximum"); } From 89bd573ca496e30f0eaf53d0fbee901b9066c415 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Mon, 16 Dec 2013 11:43:17 +0000 Subject: [PATCH 213/403] Complete the parameterXMLString code re #8398 Still to be tested Signed-off-by: Karl Palmen --- .../Framework/DataHandling/src/LoadFullprofResolution.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index e1a30df8b927..91f017a1ac73 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -11,6 +11,7 @@ Load Fullprof resolution (.irf) file to TableWorkspace(s) and optionally into th #include "MantidGeometry/Instrument.h" #include "MantidAPI/InstrumentDataService.h" #include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" +#include "MantidDataHandling/LoadParameterFile.h" #include #include @@ -808,11 +809,12 @@ namespace DataHandling } // Convert DOM XML document into string - // ? std::ofstream outFile(); - // ? writer.writeNode(outFile, mDoc); // How do I do this? - + std::ostringstream outFile; + writer.writeNode(outFile, mDoc); + std::string parameterXMLString = outFile.str(); // Load the string into the workspace + LoadParameterFile::execManually(true, "", parameterXMLString, ws); } From 58edeb1b05efba046d86db4142348d650cf53884 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Mon, 16 Dec 2013 13:34:35 -0500 Subject: [PATCH 214/403] Refs #8571 modifications for WISH --- .../Crystal/inc/MantidCrystal/LoadIsawPeaks.h | 1 + .../Framework/Crystal/src/LoadIsawPeaks.cpp | 46 +++++++++++++++---- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h index e7100e0ede94..79a4db870cf5 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h @@ -31,6 +31,7 @@ namespace Crystal /// Returns a confidence value that this algorithm can load a file virtual int confidence(Kernel::FileDescriptor & descriptor) const; + int findPixelID(Geometry::Instrument_const_sptr inst, std::string bankName, int col, int row); private: /// Sets documentation strings for this algorithm diff --git a/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp b/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp index f3727656dddd..429a2d492c49 100644 --- a/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp +++ b/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp @@ -238,8 +238,9 @@ namespace Crystal } std::string SbankNum = boost::lexical_cast(bankNum); - - std::string bankName = "bank"+SbankNum; + std::string bankName = "bank"; + if (instr->getName() == "WISH") bankName = "WISHpanel0"; + bankName += SbankNum; boost::shared_ptr bank =instr_old->getComponentByName( bankName ); if( !bank) @@ -262,6 +263,8 @@ namespace Crystal boost::shared_ptr< const Geometry::RectangularDetector>bankR= boost::dynamic_pointer_cast ( bank); + if (!bankR)return startChar; + double DetWScale = 1, DetHtScale = 1; if( bank) { @@ -431,15 +434,11 @@ namespace Crystal // Find the detector ID from row/col Instrument_const_sptr inst = outWS->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace!"); - IComponent_const_sptr bank = inst->getComponentByName(bankName); - if (!bank) throw std::runtime_error("Bank named " + bankName + " not found!"); - RectangularDetector_const_sptr rect = boost::dynamic_pointer_cast(bank); - if (!rect) throw std::runtime_error("Bank named " + bankName + " is not a RectangularDetector!"); - IDetector_sptr det = rect->getAtXY(int(col), int(row)); - if (!det) throw std::runtime_error("Detector not found on " + bankName + "!"); + LoadIsawPeaks u; + int pixelID = u.findPixelID(inst, bankName, static_cast(col), static_cast(row)); //Create the peak object - Peak peak(outWS->getInstrument(), det->getID(), wl); + Peak peak(outWS->getInstrument(), pixelID, wl); // HKL's are flipped by -1 because of the internal Q convention peak.setHKL(-h,-k,-l); peak.setIntensity(Inti); @@ -449,6 +448,31 @@ namespace Crystal return peak; } + int LoadIsawPeaks::findPixelID(Instrument_const_sptr inst, std::string bankName, int col, int row) + { + boost::shared_ptr parent = inst->getComponentByName(bankName); + if (parent->type().compare("RectangularDetector") == 0) + { + boost::shared_ptr RDet = boost::dynamic_pointer_cast< + const RectangularDetector>(parent); + + boost::shared_ptr pixel = RDet->getAtXY(col, row); + return pixel->getID(); + } + else + { + std::vector children; + boost::shared_ptr asmb = boost::dynamic_pointer_cast(parent); + asmb->getChildren(children, false); + int col0 = (col%2==0 ? col/2+75 : (col-1)/2); + boost::shared_ptr asmb2 = boost::dynamic_pointer_cast(children[col0]); + std::vector grandchildren; + asmb2->getChildren(grandchildren,false); + Geometry::IComponent_const_sptr first = grandchildren[row-1]; + Geometry::IDetector_const_sptr det = boost::dynamic_pointer_cast(first); + return det->getID(); + } + } //----------------------------------------------------------------------------------------------- @@ -548,7 +572,9 @@ namespace Crystal std::ostringstream oss; - oss << "bank" << bankNum; + std::string bankString = "bank"; + if (outWS->getInstrument()->getName() == "WISH") bankString = "WISHpanel0"; + oss << bankString << bankNum; std::string bankName = oss.str(); int seqNum = -1; From 5faeaf17f1841839da34d5fda37a93e0af272af8 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Mon, 16 Dec 2013 14:38:47 -0500 Subject: [PATCH 215/403] Refs #8622 calculate uncertainties of new UB --- .../Crystal/src/OptimizeLatticeForCellType.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp index 36a3bcff36e5..0dc06ad6f25f 100644 --- a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp +++ b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp @@ -185,6 +185,22 @@ namespace Mantid std::vectorParams; for ( size_t i = 0; i < s->x->size; i++ )Params.push_back(gsl_vector_get(s->x,i)); optLattice(inname, type, Params); + std::vector sigabc(7); + OrientedLattice latt=ws->mutableSample().getOrientedLattice(); + DblMatrix UBnew = latt.getUB(); + const std::vector &peaks = ws->getPeaks(); + size_t n_peaks = ws->getNumberPeaks(); + std::vector q_vector; + std::vector hkl_vector; + + for ( size_t i = 0; i < n_peaks; i++ ) + { + q_vector.push_back(peaks[i].getQSampleFrame()); + hkl_vector.push_back(peaks[i].getHKL()); + } + IndexingUtils::Optimize_UB(UBnew, hkl_vector,q_vector,sigabc); + ws->mutableSample().getOrientedLattice().setError(sigabc[0],sigabc[1],sigabc[2],sigabc[3],sigabc[4],sigabc[5]); + gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free (s); From 54c3fefe2e922797bafde3254c78816bec2147ef Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Mon, 16 Dec 2013 15:28:58 -0500 Subject: [PATCH 216/403] Refs #8624 improved time domain both tmin and tmax have been extended to make sure we obtain a sufficiently complete frequency spectrum after doing the fourier transform modified: StretchedExpFT.py modified: StretchedExpFTTest.py --- .../plugins/functions/StretchedExpFT.py | 16 +++++++++------- .../plugins/functions/StretchedExpFTTest.py | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py b/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py index 06ecbfd50a6b..43386ff4e946 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py @@ -43,7 +43,7 @@ class StretchedExpFT(IFunction1D): def __init__(self): '''declare some constants''' super(StretchedExpFT, self).__init__() - self._meV2ps = 4.136 + self._h = 4.135665616 #meV*Thz self._parmset = set(['height','tau','beta']) #valid syntaxfor python >= 2.6 self._parm2index = {'height':0,'tau':1,'beta':2} #order in which they were defined @@ -86,8 +86,8 @@ def function1D(self, xvals, **optparms): 1/(M*dt) = xvals[1]-xvals[0] N/(M*dt) = max(abs(xvals)) Thus: - dt = 1/[M*(xvals[1]-xvals[0])] # M=2*N+1 N = max(abs(xvals)) / (xvals[1]-xvals[0]) + dt = 1/[M*(xvals[1]-xvals[0])] # M=2*N+1 Its Fourier transform is real by definition, thus we return the real part of the Fast Fourier Transform (FFT). The FFT step is meant to produce @@ -107,11 +107,13 @@ def function1D(self, xvals, **optparms): if optparms: if self._parmset.issubset( set(optparms.keys()) ): for name in self._parmset: p[name] = optparms[name] - de = xvals[1]-xvals[0] # meV (or ueV) , energy step - # make sure M > len(xvals) so that we can use interp1d later - N = 1+ int( max(np.abs(xvals)) / de ) - M = 2*N+1 - dt = self._meV2ps / (M*de) # ps ( or ns), time step + + de = (xvals[1]-xvals[0]) / 2 # increase the long-time range, increase the low-frequency resolution + emax = 32 * max(abs(xvals)) # increase short-times resolution, increase the resolution of the structure factor tail + tmax = self._h / de + tmin = self._h / emax + N = int( tmax / tmin ) + dt = N * tmin / ( 2 *N + 1 ) # extent to negative times and t==0 sampled_times = dt * np.arange(-N, N+1) exponent = -(np.abs(sampled_times)/p['tau'])**p['beta'] freqs = de * np.arange(-N, N+1) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py index 7f76e8d1121b..351c34c1329f 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py @@ -63,7 +63,7 @@ def PyExec(self): wspace.dataE(0)[:] = error self.setProperty('OutputWorkspace', wspace) # Stores the workspace as the given name - + class StretchedExpFTTest(unittest.TestCase): def skipTest(self): From 61f5b1413131cd1e126196034dbe79c10a07d17f Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Mon, 16 Dec 2013 16:09:55 -0500 Subject: [PATCH 217/403] Ensure all monitor types are monitors. refs #8625 Also removed redundant IDF. --- Code/Mantid/instrument/VISION_Definition.xml | 4477 ----------------- .../VISION_Definition_20131021-.xml | 2 +- 2 files changed, 1 insertion(+), 4478 deletions(-) delete mode 100644 Code/Mantid/instrument/VISION_Definition.xml diff --git a/Code/Mantid/instrument/VISION_Definition.xml b/Code/Mantid/instrument/VISION_Definition.xml deleted file mode 100644 index 2305ea4e9664..000000000000 --- a/Code/Mantid/instrument/VISION_Definition.xml +++ /dev/null @@ -1,4477 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Code/Mantid/instrument/VISION_Definition_20131021-.xml b/Code/Mantid/instrument/VISION_Definition_20131021-.xml index 84b40c2281ae..21fb59cdf00b 100644 --- a/Code/Mantid/instrument/VISION_Definition_20131021-.xml +++ b/Code/Mantid/instrument/VISION_Definition_20131021-.xml @@ -4390,7 +4390,7 @@
- + From 19c22bbe3674d884973b9ed9856deae7770816ac Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Mon, 16 Dec 2013 16:39:17 -0500 Subject: [PATCH 218/403] Refs #8622 new function to calculate errors without changing UB --- .../src/OptimizeLatticeForCellType.cpp | 18 ++-- .../MantidGeometry/Crystal/IndexingUtils.h | 5 + .../Geometry/src/Crystal/IndexingUtils.cpp | 97 +++++++++++++++++++ 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp index 0dc06ad6f25f..a9b927a8f4f3 100644 --- a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp +++ b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp @@ -181,7 +181,7 @@ namespace Mantid " Method used = " << " Simplex" << " Iteration = " << iter << " Status = " << report << - " Chisq = " << s->fval ; + " Chisq = " << s->fval <<"\n"; std::vectorParams; for ( size_t i = 0; i < s->x->size; i++ )Params.push_back(gsl_vector_get(s->x,i)); optLattice(inname, type, Params); @@ -190,24 +190,26 @@ namespace Mantid DblMatrix UBnew = latt.getUB(); const std::vector &peaks = ws->getPeaks(); size_t n_peaks = ws->getNumberPeaks(); - std::vector q_vector; std::vector hkl_vector; for ( size_t i = 0; i < n_peaks; i++ ) { - q_vector.push_back(peaks[i].getQSampleFrame()); hkl_vector.push_back(peaks[i].getHKL()); } - IndexingUtils::Optimize_UB(UBnew, hkl_vector,q_vector,sigabc); - ws->mutableSample().getOrientedLattice().setError(sigabc[0],sigabc[1],sigabc[2],sigabc[3],sigabc[4],sigabc[5]); + IndexingUtils::Calculate_Errors(UBnew, hkl_vector, sigabc, s->fval); + OrientedLattice o_lattice; + o_lattice.setUB( UBnew ); + o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],sigabc[3],sigabc[4],sigabc[5]); + + // Show the modified lattice parameters + g_log.notice() << o_lattice << "\n"; + ws->mutableSample().setOrientedLattice( new OrientedLattice(o_lattice) ); gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free (s); setProperty("OutputChi2", s->fval); - // Show the modified lattice parameters - OrientedLattice o_lattice = ws->mutableSample().getOrientedLattice(); - g_log.notice() << o_lattice << "\n"; + if ( apply ) { // Reindex peaks with new UB diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h index 36f8b20cec97..dd5e7c963823 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/IndexingUtils.h @@ -93,6 +93,11 @@ class MANTID_GEOMETRY_DLL IndexingUtils const std::vector & q_vectors , std::vector & sigabc); + /// Find the UB matrix that most nearly maps hkl to qxyz for 3 or more peaks + static double Calculate_Errors( Kernel::DblMatrix & UB, + const std::vector & hkl_vectors, + std::vector & sigabc, double chisq); + /// Find the UB matrix that most nearly maps hkl to qxyz for 3 or more peaks static double Optimize_UB( Kernel::DblMatrix & UB, const std::vector & hkl_vectors, diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp index 16f6fcb52184..663fdbe046a1 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/IndexingUtils.cpp @@ -779,6 +779,103 @@ double IndexingUtils::Optimize_UB( DblMatrix & UB, + return result; +} +/** + STATIC method Optimize_UB: Calculates the matrix that most nearly maps + the specified hkl_vectors to the specified q_vectors. The calculated + UB minimizes the sum squared differences between UB*(h,k,l) and the + corresponding (qx,qy,qz) for all of the specified hkl and Q vectors. + The sum of the squares of the residual errors is returned. This method is + used to optimize the UB matrix once an initial indexing has been found. + + @param UB 3x3 matrix that will be set to the UB matrix + @param hkl_vectors std::vector of V3D objects that contains the + list of hkl values + @param q_vectors std::vector of V3D objects that contains the list of + q_vectors that are indexed by the corresponding hkl + vectors. + @param sigabc error in the crystal lattice parameter values if length + is at least 6. NOTE: Calculation of these errors is based on + SCD FORTRAN code base at IPNS. Contributors to the least + squares application(1979) are J.Marc Overhage, G.Anderson, + P. C. W. Leung, R. G. Teller, and A. J. Schultz + NOTE: The number of hkl_vectors and q_vectors must be the same, and must + be at least 3. + + @return This will return the sum of the squares of the residual differences + between the Q vectors provided and the UB*hkl values, in + reciprocal space. + + @throws std::invalid_argument exception if there are not at least 3 + hkl and q vectors, or if the numbers of + hkl and q vectors are not the same, or if + the UB matrix is not a 3x3 matrix. + + @throws std::runtime_error exception if the QR factorization fails or + the UB matrix can't be calculated or if + UB is a singular matrix. +*/ +double IndexingUtils::Calculate_Errors( DblMatrix & UB, + const std::vector & hkl_vectors, + std::vector & sigabc, double chisq) +{ + double result = chisq; + if( sigabc.size() <6) + { + sigabc.clear(); + return result; + }else + for( int i=0;i<6;i++) + sigabc[i]=0.0; + + size_t nDOF= 3*(hkl_vectors.size()-3); + DblMatrix HKLTHKL(3,3); + for( int r=0; r < 3; r++) + for( int c=0; c<3;c++) + for( size_t i =0; i< hkl_vectors.size();i++) + { + HKLTHKL[r][c] += hkl_vectors[i][r]*hkl_vectors[i][c];//rounded??? to nearest integer + } + + HKLTHKL.Invert(); + + + double SMALL =1.525878906E-5; + Matrix derivs( 3,7); + std::vector latOrig, latNew; + GetLatticeParameters( UB, latOrig); + + + for( int r=0; r<3;r++) + { + for( int c=0; c<3;c++) + { + + UB[r][c] += SMALL; + + GetLatticeParameters( UB, latNew); + UB[r][c] -= SMALL; + + for( int l=0; l<7; l++ ) + derivs[c][l] = (latNew[l]-latOrig[l])/SMALL; + + + } + + for( size_t l=0;l((size_t)7,sigabc.size());l++) + for( int m=0; m<3;m++) + for( int n=0; n<3;n++) + sigabc[l] += (derivs[m][l] * HKLTHKL[m][n] * derivs[n][l]); + } + + double delta = result /(double)nDOF; + + for( size_t i = 0; i < std::min(7,sigabc.size()); i++ ) + sigabc[i] = sqrt( delta * sigabc[i] ); + + + return result; } /** From 99e177db672b9f0c2dc5ac4bd9a221268805338e Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Mon, 16 Dec 2013 16:46:06 -0500 Subject: [PATCH 219/403] Refs #8571 wrong changes in merge --- .../scripts/Reflectometry/isis_reflectometry/quick.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 7eda40dbb286..a5ac5b02a80a 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -143,11 +143,9 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi _monInt = Integration(InputWorkspace=_I0P,RangeLower=int_min,RangeUpper=int_max) IvsLam = Divide(LHSWorkspace=_detector_ws,RHSWorkspace=_monInt) names = mtd.getObjectNames() - - IvsLam = transCorr(trans, IvsLam) + IvsLam = transCorr(trans, IvsLam, lambda_min, lambda_max, background_min, background_max, + int_min, int_max, detector_index_ranges, i0_monitor_index) RenameWorkspace(InputWorkspace=IvsLam, OutputWorkspace="IvsLam") # TODO: Hardcoded names are bad - - # Convert to I vs Q # check if detector in direct beam if (theta == 0 or theta == ''): From 85e6e9a7617f6e77b6613e684c132548e5848ed2 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Mon, 16 Dec 2013 16:58:09 -0500 Subject: [PATCH 220/403] Re #8627. Catch the exception if encountering an unknown monitor. ADARA files have been seen to occasionally contain 'phantom' monitors that aren't in the IDF. This was causing the algorithm to fail, but this change defends against that by catching the exception and then ignoring those spectra. --- .../Algorithms/src/SumEventsByLogValue.cpp | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/SumEventsByLogValue.cpp b/Code/Mantid/Framework/Algorithms/src/SumEventsByLogValue.cpp index a11ad9e05818..0d8e20fa7a74 100644 --- a/Code/Mantid/Framework/Algorithms/src/SumEventsByLogValue.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SumEventsByLogValue.cpp @@ -331,17 +331,22 @@ namespace Algorithms // Loop over the spectra - there will be one per monitor for ( std::size_t spec = 0; spec < monitorWorkspace->getNumberHistograms(); ++spec ) { - // Create a column for this monitor - const std::string monitorName = monitorWorkspace->getDetector(spec)->getName(); - auto monitorCounts = outputWorkspace->addColumn("int",monitorName); - const IEventList & eventList = monitorWorkspace->getEventList(spec); - // Accumulate things in a local vector before transferring to the table workspace - std::vector Y(xLength); - filterEventList(eventList, minVal, maxVal, log, Y); - // Transfer the results to the table - for ( int i = 0; i < xLength; ++i ) - { - monitorCounts->cell(i) = Y[i]; + try { + // Create a column for this monitor + const std::string monitorName = monitorWorkspace->getDetector(spec)->getName(); + auto monitorCounts = outputWorkspace->addColumn("int",monitorName); + const IEventList & eventList = monitorWorkspace->getEventList(spec); + // Accumulate things in a local vector before transferring to the table workspace + std::vector Y(xLength); + filterEventList(eventList, minVal, maxVal, log, Y); + // Transfer the results to the table + for ( int i = 0; i < xLength; ++i ) + { + monitorCounts->cell(i) = Y[i]; + } + } catch (Exception::NotFoundError&) { + // ADARA-generated nexus files have sometimes been seen to contain 'phantom' monitors that aren't in the IDF. + // This handles that by ignoring those spectra. } } } From 7be194d98f1877296c84f17945947134e786f27a Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Mon, 16 Dec 2013 18:06:17 -0500 Subject: [PATCH 221/403] Refs #8624 Impose limit on time domain size Extension of the time domain may create a too large one, thus lengthening the fitting in excess modified: StretchedExpFT.py modified: StretchedExpFTTest.py --- .../plugins/functions/StretchedExpFT.py | 13 +- .../plugins/functions/StretchedExpFTTest.py | 238 +++++++++--------- 2 files changed, 128 insertions(+), 123 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py b/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py index 43386ff4e946..d8a9d7cda272 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/functions/StretchedExpFT.py @@ -109,12 +109,13 @@ def function1D(self, xvals, **optparms): for name in self._parmset: p[name] = optparms[name] de = (xvals[1]-xvals[0]) / 2 # increase the long-time range, increase the low-frequency resolution - emax = 32 * max(abs(xvals)) # increase short-times resolution, increase the resolution of the structure factor tail - tmax = self._h / de - tmin = self._h / emax - N = int( tmax / tmin ) - dt = N * tmin / ( 2 *N + 1 ) # extent to negative times and t==0 - sampled_times = dt * np.arange(-N, N+1) + emax = max( abs(xvals) ) + Nmax = 16000 # increase short-times resolution, increase the resolution of the structure factor tail + while ( emax / de ) < Nmax: + emax = 2 * emax + N = int( emax / de ) + dt = ( float(N) / ( 2 * N + 1 ) ) * (self._h / emax) # extent to negative times and t==0 + sampled_times = dt * np.arange(-N, N+1) # len( sampled_times ) < 64000 exponent = -(np.abs(sampled_times)/p['tau'])**p['beta'] freqs = de * np.arange(-N, N+1) fourier = p['height']*np.abs( scipy.fftpack.fft( np.exp(exponent) ).real ) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py index 351c34c1329f..66de05c7fd61 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/functions/StretchedExpFTTest.py @@ -4,122 +4,126 @@ from mantid.simpleapi import Fit import testhelpers -from pdb import set_trace as tr - -class _InternalMakeSEFTData(PythonAlgorithm): - - def PyInit(self): - self.declareProperty('height', 1.0, validator=FloatBoundedValidator(lower=0)) - self.declareProperty('tau', 1.0, validator=FloatBoundedValidator(lower=0)) - self.declareProperty('beta', 1.0, validator=FloatBoundedValidator(lower=0)) - self.declareProperty('nhalfbins', 100) - self.declareProperty('de', 0.0004) # energy step in meV - self.declareProperty(MatrixWorkspaceProperty('OutputWorkspace', '', direction = Direction.Output)) - - def PyExec(self): - '''Create the data workspace containing one spectrum resulting from the - Fourier transform of an stretched exponential, plus some noise''' - import numpy as np - from scipy.fftpack import fft - from scipy.interpolate import interp1d - - meV2ps = 4.136 # from meV (or ueV) to ps (or ns) - - nhalfbins = self.getProperty('nhalfbins').value - de = self.getProperty('de').value #bin width, in meV or ueV - nbins = 2*nhalfbins - xvals = de*np.arange(-nhalfbins, nhalfbins) + de/2 # energy values - - #Find the time domain - N = 1+nhalfbins - M = 2*N+1 - dt = meV2ps / (M*de) # ps ( or ns), time step - sampled_times = dt * np.arange(-N, N+1) - - height = self.getProperty('height').value - tau = self.getProperty('tau').value - beta = self.getProperty('beta').value - - #Define the stretched exponential on the time domain, then do its Fourier transform - exponent = -(np.abs(sampled_times)/tau)**beta - freqs = de * np.arange(-N, N+1) - fourier = height*np.abs( fft( np.exp(exponent) ).real ) - fourier = np.concatenate( (fourier[N+1:],fourier[0:N+1]) ) - interpolator = interp1d(freqs, fourier) - ynominal = interpolator(xvals) - - wspace = WorkspaceFactory.create('Workspace2D', NVectors=1, XLength=nbins, YLength=nbins) - # white noise in the [0.2, 1) range, average is 0.6 - noise = 0.2 + 0.8*np.random.random(nbins) - sign = np.random.random(nbins) - sign = np.where(sign>0.5, 1, -1) # random sign - # average noise is 6% of the signal local intensity - - yvals = (1+0.1*noise*sign) * ynominal - error = 0.2*noise*ynominal - wspace.dataX(0)[:] = xvals - wspace.dataY(0)[:] = yvals - # average error is 12% of the signal local intensity - wspace.dataE(0)[:] = error - - self.setProperty('OutputWorkspace', wspace) # Stores the workspace as the given name - -class StretchedExpFTTest(unittest.TestCase): - - def skipTest(self): - try: - import scipy.fftpack # Scipy not available in windows debug - return False - except ImportError: - return True - - def test_registered(self): - try: - FunctionFactory.createFunction('StretchedExpFT') - except RuntimeError, exc: - self.fail('Could not create StretchedExpFT function: %s' % str(exc)) - - 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 = 4000 - de = 0.0004 - AlgorithmFactory.subscribe(_InternalMakeSEFTData) - alg = testhelpers.run_algorithm('_InternalMakeSEFTData', nhalfbins=Nh, de=de, - OutputWorkspace='_test_seft_data', **parms) - input_ws = alg.getProperty('OutputWorkspace').value - - 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') +#from pdb import set_trace as tr + +class _InternalMakeSEFTData( PythonAlgorithm ): + + def PyInit( self ): + self.declareProperty( 'height', 1.0, validator = FloatBoundedValidator( lower = 0 ) ) + self.declareProperty( 'tau', 1.0, validator = FloatBoundedValidator( lower = 0 ) ) + self.declareProperty( 'beta', 1.0, validator = FloatBoundedValidator( lower = 0 ) ) + self.declareProperty( 'nhalfbins', 100 ) + self.declareProperty( 'de', 0.0004 ) # energy step in meV + self.declareProperty( MatrixWorkspaceProperty( 'OutputWorkspace', '', direction = Direction.Output ) ) + + def PyExec( self ): + '''Create the data workspace containing one spectrum resulting from the + Fourier transform of an stretched exponential, plus some noise''' + import numpy as np + from scipy.fftpack import fft + from scipy.interpolate import interp1d + + plank_constant = 4.135665616 # in units of meV*THz + + nhalfbins = self.getProperty( 'nhalfbins' ).value + de = self.getProperty( 'de' ).value #bin width, in meV or ueV + nbins = 2 * nhalfbins + xvals = de * np.arange( -nhalfbins, nhalfbins + 1) + de/2 # + + #Find the time domain + M = 2 * nhalfbins + 1 + dt = plank_constant / ( M * de ) # ps ( or ns), time step + sampled_times = dt * np.arange( -nhalfbins, nhalfbins + 1 ) + + height = self.getProperty( 'height' ).value + tau = self.getProperty( 'tau' ).value + beta = self.getProperty( 'beta' ).value + + #Define the stretched exponential on the time domain, then do its Fourier transform + exponent = -( np.abs( sampled_times ) / tau )**beta + freqs = de * np.arange( -nhalfbins, nhalfbins + 1 ) + fourier = height * np.abs( fft( np.exp( exponent ) ).real ) + fourier = np.concatenate( ( fourier[ nhalfbins + 1 : ],fourier[ 0 : nhalfbins + 1 ] ) ) + interpolator = interp1d( freqs, fourier ) + N = nhalfbins / 2 + ynominal = interpolator( xvals[ N : -N-1 ] ) # high energies are not well represented, avoid them + + wspace = WorkspaceFactory.create( 'Workspace2D' , NVectors = 1, XLength = 2 * N, YLength = 2 * N ) + # white noise in the [0.2, 1) range, average is 0.6 + noise = 0.2 + 0.8 * np.random.random( 2 * N ) + sign = np.random.random( 2 * N ) + sign = np.where( sign > 0.5, 1, -1 ) # random sign + # average noise is 6% of the signal local intensity + + yvals = ( 1 + 0.05 * noise * sign ) * ynominal + error = 0.1 * noise * ynominal + wspace.dataX(0)[:] = xvals[ N : -N-1 ] + wspace.dataY(0)[:] = yvals + # average error is 12% of the signal local intensity + wspace.dataE(0)[:] = error + + """ # Only for debugging purposes + buffer = '#h = {0}, tau = {1}, beta = {2}\n'.format( height, tau, beta ) + for iy in range( len(yvals) ): + buffer += '{0} {1} {2}\n'.format( xvals[N+iy], yvals[iy], error[iy] ) + open( '/tmp/junk.dat', 'w' ).write( buffer ) + """ + + self.setProperty( 'OutputWorkspace', wspace ) # Stores the workspace as the given name + +class StretchedExpFTTest( unittest.TestCase ): + + def skipTest( self ): + try: + import scipy.fftpack # Scipy not available in windows debug + return False + except ImportError: + return True + + def test_registered( self ): + try: + FunctionFactory.createFunction( 'StretchedExpFT' ) + except RuntimeError, exc: + self.fail( 'Could not create StretchedExpFT function: %s' % str( exc ) ) + + 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 ) + input_ws = alg.getProperty( 'OutputWorkspace' ).value + + 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' ) if __name__ == '__main__': - unittest.main() + unittest.main() From 83a1c91ed5be66def7849a86b095fb5b65cf87ad Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Tue, 17 Dec 2013 08:59:13 +0000 Subject: [PATCH 222/403] refs #8628. wrong arguments passed fixed. --- Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 7eda40dbb286..8e7042ab9331 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -144,7 +144,8 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi IvsLam = Divide(LHSWorkspace=_detector_ws,RHSWorkspace=_monInt) names = mtd.getObjectNames() - IvsLam = transCorr(trans, IvsLam) + IvsLam = transCorr(trans, IvsLam, lambda_min, lambda_max, background_min, background_max, + int_min, int_max, detector_index_ranges, i0_monitor_index) RenameWorkspace(InputWorkspace=IvsLam, OutputWorkspace="IvsLam") # TODO: Hardcoded names are bad From 7677fe7f9ac4fbee02b7d73ca7e94ae5dcb5382d Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 17 Dec 2013 09:23:23 -0500 Subject: [PATCH 223/403] Re #8630. It is actually just an 'else' --- Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py index 98d0610fdea7..04c40a2dc6ec 100644 --- a/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py +++ b/Code/Mantid/scripts/SCD_Reduction/ReduceSCD_OneRun.py @@ -338,7 +338,7 @@ # If requested, also switch to the specified conventional cell and save the # corresponding matrix and integrate file # -if not use_ellipse_integration: +else: if (not cell_type is None) and (not centering is None) : run_conventional_matrix_file = output_directory + "/" + run + "_" + \ cell_type + "_" + centering + ".mat" From 8171401959f461614239e0b20c160a16d4c65eaf Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Tue, 17 Dec 2013 16:15:47 +0000 Subject: [PATCH 224/403] Begin unit test of new property re #8398 Unit test present just tests that it executes without error. Also some fixes to ensure it executes without error. Signed-off-by: Karl Palmen --- .../src/LoadFullprofResolution.cpp | 11 ++-- .../test/LoadFullprofResolutionTest.h | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index 91f017a1ac73..8560279270a6 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -81,7 +81,7 @@ namespace DataHandling "Path to an Fullprof .irf file to load."); // Output table workspace - auto wsprop = new WorkspaceProperty("OutputTableWorkspace", "", Direction::Output); + auto wsprop = new WorkspaceProperty("OutputTableWorkspace", "", Direction::Output, PropertyMode::Optional); declareProperty(wsprop, "Name of the output TableWorkspace containing profile parameters or bank information. "); // Bank to import @@ -187,12 +187,13 @@ namespace DataHandling // Generate output table workspace API::ITableWorkspace_sptr outTabWs = genTableWorkspace(bankparammap); - // 6. Output table workspace - setProperty("OutputTableWorkspace", outTabWs); - - // 7. If workspace, put parameters there + // If workspace, put parameters there if(workspace){ putParametersIntoWorkspace( outTabWs, workspace ); + } + else + { // else, output the output table workspace + setProperty("OutputTableWorkspace", outTabWs); } return; diff --git a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h index 42ce8caf3c6e..3be2ede3cd29 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h @@ -6,12 +6,15 @@ #include "MantidDataHandling/LoadFullprofResolution.h" #include "MantidDataObjects/TableWorkspace.h" #include "MantidAPI/TableRow.h" +#include "MantidDataHandling/LoadInstrument.h" +#include "MantidDataObjects/Workspace2D.h" #include #include using Mantid::DataHandling::LoadFullprofResolution; using namespace Mantid; +using namespace Mantid::DataHandling; using namespace Mantid::DataObjects; using namespace Mantid::Kernel; using namespace Mantid::API; @@ -267,6 +270,38 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite return; } + //---------------------------------------------------------------------------------------------- + /** Test that when the workspace property is used + ** that parameters are correctly loaded into this workspace + * The GEM instrument is used + */ + void test_workspace() + { + // Generate file + string filename("TestWorskpace.irf"); + generate1BankIrfFile(filename); + + // Load workspace wsName + load_GEM(); + + // Set up algorithm to load into the workspace + LoadFullprofResolution alg; + alg.initialize(); + + alg.setProperty("Filename", filename); + alg.setPropertyValue("Banks", "1"); + alg.setProperty("Workspace", wsName); + + // Execute + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(alg.isExecuted()); + + // Check parameters in workspace + + // Clean + Poco::File("TestWorskpace.irf").remove(); + } + //---------------------------------------------------------------------------------------------- /** Test that the number from the NPROF is read correctly ** and has correct name in table. @@ -380,6 +415,33 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite return; } + + //---------------------------------------------------------------------------------------------- + /** Generate a GEM workspace + */ + void load_GEM() + { + LoadInstrument loaderGEM; + + TS_ASSERT_THROWS_NOTHING(loaderGEM.initialize()); + + //create a workspace with some sample data + wsName = "LoadFullprofResolutionWorkspace"; + Workspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D",1,1,1); + Workspace2D_sptr ws2D = boost::dynamic_pointer_cast(ws); + + //put this workspace in the data service + TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add(wsName, ws2D)); + + // Path to test input file + loaderGEM.setPropertyValue("Filename", "GEM_Definition.xml"); + //inputFile = loaderIDF2.getPropertyValue("Filename"); + loaderGEM.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderGEM.execute()); + TS_ASSERT( loaderGEM.isExecuted() ); + + } + //---------------------------------------------------------------------------------------------- /** Generate a 1 bank .irf file */ @@ -573,6 +635,9 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite return 29; // Change this value if you add or remove any rows from the OutputTableWorkspace } + private: + std::string wsName; // For Workspace property + }; From 7359eb29084af2dd1be8da1a020556489225a7c9 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Tue, 17 Dec 2013 11:32:02 -0500 Subject: [PATCH 225/403] Refs #8631 Improved the value of Plank constant Substituted 4.136 for 4.135665616 Also renamed the associated variable to m_h modified: DiffRotDiscreteCircle.h modified: DiffRotDiscreteCircle.cpp modified: DiffRotDiscreteCircleTest.h --- .../inc/MantidCurveFitting/DiffRotDiscreteCircle.h | 7 ++++++- .../CurveFitting/src/DiffRotDiscreteCircle.cpp | 12 ++++-------- .../CurveFitting/test/DiffRotDiscreteCircleTest.h | 3 ++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h index 0e711510bc02..ad86aae27180 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -53,6 +53,9 @@ class DLLExport ElasticDiffRotDiscreteCircle : public DeltaFunction /// overwrite IFunction base class methods virtual std::string name()const{ return "ElasticDiffRotDiscreteCircle"; } + /// overwrite IFunction base class method, which declare function parameters + // virtual void init(); + /// A rescaling of the peak intensity double HeightPrefactor() const; @@ -74,13 +77,15 @@ class DLLExport InelasticDiffRotDiscreteCircle : public API::ParamFunction, publ virtual std::string name() const { return "InelasticDiffRotDiscreteCircle"; } + // virtual void init(); + protected: virtual void function1D( double * out, const double* xValues, const size_t nData ) const; private: - const double m_t2e; // converstion from picosec to mili-eV, or from nanosec to micro-eV + const double m_h; // Plank constant, in meV*THz (or ueV*PHz) }; diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 2de63a6fc38b..068a4a71340f 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -81,6 +81,8 @@ DECLARE_FUNCTION(DiffRotDiscreteCircle); ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ //declareParameter("Height", 1.0); //parameter "Height" already declared in constructor of base class DeltaFunction declareParameter( "Radius", 1.0, "Circle radius [Angstroms] " ); + declareAttribute( "Q", API::IFunction::Attribute(0.5) ); + declareAttribute( "N", API::IFunction::Attribute(3) ); // Ensure positive values for Height and Radius BoundaryConstraint* HeightConstraint = new BoundaryConstraint( this, "Height", std::numeric_limits::epsilon(), true ); @@ -88,10 +90,6 @@ ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ BoundaryConstraint* RadiusConstraint = new BoundaryConstraint( this, "Radius", std::numeric_limits::epsilon(), true ); addConstraint( RadiusConstraint ); - - declareAttribute( "Q", API::IFunction::Attribute(0.5) ); - declareAttribute( "N", API::IFunction::Attribute(3) ); - } double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ @@ -108,7 +106,7 @@ double ElasticDiffRotDiscreteCircle::HeightPrefactor() const{ return aN / N; } -InelasticDiffRotDiscreteCircle::InelasticDiffRotDiscreteCircle() : m_t2e(4.136) +InelasticDiffRotDiscreteCircle::InelasticDiffRotDiscreteCircle() : m_h(4.135665616) { declareParameter( "Intensity",1.0, "scaling factor [arbitrary units]" ); declareParameter( "Radius", 1.0, "Circle radius [Angstroms]" ); @@ -126,15 +124,13 @@ InelasticDiffRotDiscreteCircle::InelasticDiffRotDiscreteCircle() : m_t2e(4.136) BoundaryConstraint* DecayConstraint = new BoundaryConstraint( this, "Decay", std::numeric_limits< double >::epsilon(), true ); addConstraint( DecayConstraint ); - } - void InelasticDiffRotDiscreteCircle::function1D( double *out, const double* xValues, const size_t nData ) const { const double I = getParameter( "Intensity" ); const double R = getParameter( "Radius" ); - const double rate = m_t2e / getParameter( "Decay" ); // micro-eV or mili-eV + const double rate = m_h / getParameter( "Decay" ); // micro-eV or mili-eV const double Q = getAttribute( "Q" ).asDouble(); const int N = getAttribute( "N" ).asInt(); diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h index b39bdfefccd3..05d608817fc3 100644 --- a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -338,7 +338,8 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite */ Mantid::DataObjects::Workspace2D_sptr generateN3Workspace( const double & I, const double & R, const double & tao, const double & Q ) { - const double rate = 4.136 / tao; // conversion from picosec to mili-eV, or from nanosec to micro-eV + const double h = 4.135665616; // plank constant in meV*THz (or ueV*PHz) + const double rate = h / tao; // conversion from picosec to mili-eV, or from nanosec to micro-eV // calculate prefix A1. Better be verbose for clarity const double x = Q * R * sqrt( 3.0 ); From 4a0c9e6c7d68904e638eeb105088597c00bd63cc Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Tue, 17 Dec 2013 11:58:25 -0500 Subject: [PATCH 226/403] Refs #8631 elastic part: moved constraint initialization modified: DiffRotDiscreteCircle.h modified: DiffRotDiscreteCircle.cpp --- .../inc/MantidCurveFitting/DiffRotDiscreteCircle.h | 2 +- .../Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h index ad86aae27180..75d1f985f20b 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -54,7 +54,7 @@ class DLLExport ElasticDiffRotDiscreteCircle : public DeltaFunction virtual std::string name()const{ return "ElasticDiffRotDiscreteCircle"; } /// overwrite IFunction base class method, which declare function parameters - // virtual void init(); + virtual void init(); /// A rescaling of the peak intensity double HeightPrefactor() const; diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 068a4a71340f..6a4285d53102 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -83,7 +83,10 @@ ElasticDiffRotDiscreteCircle::ElasticDiffRotDiscreteCircle(){ declareParameter( "Radius", 1.0, "Circle radius [Angstroms] " ); declareAttribute( "Q", API::IFunction::Attribute(0.5) ); declareAttribute( "N", API::IFunction::Attribute(3) ); +} +void ElasticDiffRotDiscreteCircle::init() +{ // Ensure positive values for Height and Radius BoundaryConstraint* HeightConstraint = new BoundaryConstraint( this, "Height", std::numeric_limits::epsilon(), true ); addConstraint( HeightConstraint ); From fb44afc8d429bb153341c8a7562cae13e5e6e977 Mon Sep 17 00:00:00 2001 From: Keith Brown Date: Tue, 17 Dec 2013 16:59:11 +0000 Subject: [PATCH 227/403] Refs #8633. Save dialog inplace Max's save dialog is now in placecas is. Converting it to a porper UI and making some improvements will be done in another ticket To Tester Make sure this save works for all formats --- .../Interface/ui/reflectometer/refl_gui.py | 12 +- .../Interface/ui/reflectometer/refl_save.py | 394 ++++++++++++++++++ 2 files changed, 400 insertions(+), 6 deletions(-) create mode 100644 Code/Mantid/scripts/Interface/ui/reflectometer/refl_save.py diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py index 64fd79639e0f..ab89fd6339c6 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py @@ -2,6 +2,7 @@ #so this file provides any extra GUI tweaks not easily doable in the designer #for the time being this also includes non-GUI behaviour import refl_window +import refl_save import csv from PyQt4 import QtCore, QtGui from mantid.simpleapi import * @@ -460,12 +461,11 @@ def reloadTable(self): self.loading = False self.windowRefl.modFlag = False def saveWorkspaces(self): - #Dialog = QtGui.QDialog() - #u = Ui_SaveWindow() - #u.setupUi(Dialog) - #Dialog.exec_() - #print "Disabled until decision about old dialog has been reached" - print "Disabled - Run desired save algorithm from main MantidPlot window instead" + Dialog = QtGui.QDialog() + u = refl_save.Ui_SaveWindow() + u.setupUi(Dialog) + Dialog.exec_() + #print "Disabled - Run desired save algorithm from main MantidPlot window instead" def showHelp(self): import webbrowser webbrowser.open('http://www.mantidproject.org/ISIS_Reflectometry_GUI') diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_save.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_save.py new file mode 100644 index 000000000000..a215037129ec --- /dev/null +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_save.py @@ -0,0 +1,394 @@ +from PyQt4 import QtCore, QtGui +from mantid.simpleapi import * + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_SaveWindow(object): + + def setupUi(self, SaveWindow): + SaveWindow.setObjectName(_fromUtf8("SaveWindow")) + SaveWindow.resize(700, 450) + SaveWindow.setAcceptDrops(True) + + self.centralWidget = QtGui.QWidget(SaveWindow) + self.centralWidget.setObjectName(_fromUtf8("centralWidget")) + self.gridLayout_2 = QtGui.QGridLayout(self.centralWidget) + self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) + self.gridLayout = QtGui.QGridLayout() + self.gridLayout.setSizeConstraint(QtGui.QLayout.SetNoConstraint) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + +# Path label and edit field + self.PathLabel = QtGui.QLabel("Save path: ",self.centralWidget) + self.gridLayout.addWidget(self.PathLabel,0,2,1,1) + self.lineEdit = QtGui.QLineEdit(self.centralWidget) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(False) + self.lineEdit.setFont(font) + self.lineEdit.setObjectName(_fromUtf8("lineEdit")) + self.gridLayout.addWidget(self.lineEdit, 0, 3, 1, 3) + #print QtGui.QMainWindow.findChild(QtGui.QMainWindow.QLabel,'RBEdit') + +# Prefix label and edit field + self.PrefixLabel = QtGui.QLabel("Prefix: ",self.centralWidget) + self.gridLayout.addWidget(self.PrefixLabel,0,6,1,1) + self.lineEdit2 = QtGui.QLineEdit(self.centralWidget) + self.lineEdit2.setFont(font) + self.lineEdit2.setObjectName(_fromUtf8("lineEdit2")) + self.gridLayout.addWidget(self.lineEdit2, 0, 7, 1, 2) + + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth()) + self.lineEdit.setSizePolicy(sizePolicy) + self.lineEdit2.setSizePolicy(sizePolicy) + + self.ListLabel = QtGui.QLabel("List of workspaces: ",self.centralWidget) + self.gridLayout.addWidget(self.ListLabel,1,2,1,3) + + self.LogsLabel = QtGui.QLabel("List of logged parameters: ",self.centralWidget) + self.gridLayout.addWidget(self.LogsLabel,1,6,1,3) + +# List of workspaces + self.listWidget = QtGui.QListWidget(self.centralWidget) + self.listWidget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth()) + self.gridLayout.addWidget(self.listWidget, 2, 2, 1, 3) + +# List of Logged Parameters + self.listWidget2 = QtGui.QListWidget(self.centralWidget) + self.listWidget2.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth()) + self.gridLayout.addWidget(self.listWidget2, 2, 6, 1, 3) + + spacerItem = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem, 2, 5, 1, 1) + spacerItem1 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + self.gridLayout.addItem(spacerItem1, 4, 2, 1, 1) + spacerItem2 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem2, 2, 0, 1, 1) + self.pushButton = QtGui.QPushButton(self.centralWidget) + +# Save Title + self.titleCheckBox = QtGui.QCheckBox("Title", self.centralWidget) + #self.gridLayout.addWidget(self.titleCheckBox, 3, 6, 1, 1) + + + +# Tab check box + #self.tabCheckBox = QtGui.QCheckBox("tab", self.centralWidget) + #self.gridLayout.addWidget(self.titleCheckBox, 3, 6, 1, 1) + +# Comma check box + #self.commaCheckBox = QtGui.QCheckBox("comma", self.centralWidget) + #self.gridLayout.addWidget(self.commaCheckBox, 3, 6, 1, 1) + + +# Space check box + #self.spaceCheckBox = QtGui.QCheckBox("space", self.centralWidget) + #self.gridLayout.addWidget(self.commaCheckBox, 3, 6, 1, 1) + +# Save XError + self.xErrorCheckBox = QtGui.QCheckBox("Q resolution", self.centralWidget) + #self.gridLayout.addWidget(self.xErrorCheckBox, 3, 7, 1, 1) + +# separator + #self.separatorLabel = QtGui.QLabel("Separator: ", self.centralWidget) + #self.gridLayout.addWidget(self.separatorLabel,4,6,1,1) + #self.separatorEdit = QtGui.QLineEdit(self.centralWidget) + #self.separatorEdit.setObjectName(_fromUtf8("separatorEdit")) + #self.gridLayout.addWidget(self.separatorEdit, 4, 7, 1, 1) + + self.groupBox = QtGui.QGroupBox("Custom format options") + + self.vbox = QtGui.QVBoxLayout() + self.hbox = QtGui.QHBoxLayout() + self.vbox.addWidget(self.titleCheckBox) + self.vbox.addWidget(self.xErrorCheckBox) + + self.groupBox2 = QtGui.QGroupBox("Separator") + #self.buttonGroup=QtGui.QButtonGroup("Separator:", self.groupBox) + self.radio1=QtGui.QRadioButton("Comma", self.centralWidget) + self.radio2=QtGui.QRadioButton("Space", self.centralWidget) + self.radio3=QtGui.QRadioButton("Tab", self.centralWidget) + + + self.radio1.setChecked(1) + self.hbox.addWidget(self.radio1) + self.hbox.addWidget(self.radio2) + self.hbox.addWidget(self.radio3) + self.groupBox2.setLayout(self.hbox) + # self.hbox.addWidget(self.separatorLabel) + # self.hbox.addWidget(self.commaCheckBox) + # self.hbox.addWidget(self.spaceCheckBox) + # self.hbox.addWidget(self.tabCheckBox) + + self.vbox.addWidget(self.groupBox2) + self.vbox.addStretch(1) + #self.groupBox.setCheckable(1) + self.groupBox.setLayout(self.vbox) + self.gridLayout.addWidget(self.groupBox, 3, 6, 3, 3) + + +# spectralist + self.spectraLabel = QtGui.QLabel("Spectra list: ", self.centralWidget) + self.gridLayout.addWidget(self.spectraLabel,3,2,1,1) + self.spectraEdit = QtGui.QLineEdit(self.centralWidget) + self.spectraEdit.setObjectName(_fromUtf8("spectraEdit")) + self.gridLayout.addWidget(self.spectraEdit, 3, 3, 1, 1) + + + +# file format selector + self.fileFormatLabel = QtGui.QLabel("File format: ", self.centralWidget) + self.gridLayout.addWidget(self.fileFormatLabel,5,2,1,1) + self.comboBox = QtGui.QComboBox(self.centralWidget) + self.comboBox.setToolTip("Please select the file format") + self.comboBox.setStatusTip("Please select the file format") + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) + self.comboBox.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.comboBox.setFont(font) + self.comboBox.setObjectName(_fromUtf8("comboBox")) + self.comboBox.addItem(_fromUtf8("Custom format (*.dat)")) + self.comboBox.addItem(_fromUtf8("3 column (*.dat)")) + self.comboBox.addItem(_fromUtf8("ANSTO, MotoFit, 4 column (*.txt)")) + self.comboBox.addItem(_fromUtf8("ILL Cosmos (*.mft)")) + self.gridLayout.addWidget(self.comboBox, 5, 3, 1, 1) + + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth()) + self.pushButton.setSizePolicy(sizePolicy) + self.pushButton.setObjectName(_fromUtf8("pushButton")) + self.gridLayout.addWidget(self.pushButton, 8, 2, 1, 1) + spacerItem3 = QtGui.QSpacerItem(20, 28, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + self.gridLayout.addItem(spacerItem3, 8, 3, 1, 1) + self.pushButton_2 = QtGui.QPushButton(self.centralWidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.pushButton_2.sizePolicy().hasHeightForWidth()) + self.pushButton_2.setSizePolicy(sizePolicy) + self.pushButton_2.setObjectName(_fromUtf8("pushButton_2")) + self.gridLayout.addWidget(self.pushButton_2, 8, 4, 1, 1) + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + + + self.retranslateUi(SaveWindow) + self.populateList() + #self.workspaceSelected() + QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.buttonClickHandler1) + QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8("clicked()")), self.populateList) + QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL(_fromUtf8("textChanged()")), self.setPath) + QtCore.QObject.connect(self.comboBox, QtCore.SIGNAL(_fromUtf8("activated(QString)")), self.on_comboBox_Activated) + QtCore.QObject.connect(self.listWidget, QtCore.SIGNAL(_fromUtf8("itemActivated(QListWidgetItem*)")), self.workspaceSelected) + # QtCore.QObject.connect(self.actionSave_table, QtCore.SIGNAL(_fromUtf8("triggered()")), self.saveDialog) + # QtCore.QObject.connect(self.actionLoad_table, QtCore.SIGNAL(_fromUtf8("triggered()")), self.loadDialog) + QtCore.QMetaObject.connectSlotsByName(SaveWindow) + + def retranslateUi(self, SaveWindow): + SaveWindow.setWindowTitle(QtGui.QApplication.translate("SaveWindow", "SaveWindow", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton.setText(QtGui.QApplication.translate("SaveWindow", "SAVE", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton_2.setText(QtGui.QApplication.translate("SaveWindow", "Refresh", None, QtGui.QApplication.UnicodeUTF8)) + + def setPath(): + Ui_MainWindow.SavePath=self.lineEdit.text() + + def workspaceSelected(self): + self.listWidget2.clear() + #self.listWidget.setCurrentRow(0) + print str(self.listWidget.currentItem().text()) + logs = mantid[str(self.listWidget.currentItem().text())].getSampleDetails().getLogData() + for i in range(0,len(logs)): + self.listWidget2.addItem(logs[i].name) + + def on_comboBox_Activated(self): + print "" + + def populateList(self): + self.listWidget.clear() + names = mtd.getObjectNames() + if len(names): + RB_Number=groupGet(names[0],'samp','rb_proposal') + for ws in names: + self.listWidget.addItem(ws) + + self.listWidget.setCurrentItem(self.listWidget.item(0)) + # try to get correct user directory + currentInstrument=config['default.instrument'] + if (Ui_MainWindow.SavePath!=''): + self.lineEdit.setText(Ui_MainWindow.SavePath) + else: + tree1=xml.parse(r'\\isis\inst$\NDX'+currentInstrument+'\Instrument\logs\journal\journal_main.xml') + root1=tree1.getroot() + currentJournal=root1[len(root1)-1].attrib.get('name') + tree=xml.parse(r'\\isis\inst$\NDX'+currentInstrument+'\Instrument\logs\journal\\'+currentJournal) + root=tree.getroot() + + i=0 + try: + while root[i][4].text!=str(RB_Number): + i+=1 + if root[i][1].text.find(',')>0: + user=root[i][1].text[0:root[i][1].text.find(',')] + else: + user=root[i][1].text[0:root[i][1].text.find(' ')] + SavePath='U:/'+user+'/' + self.lineEdit.setText(SavePath) + except LookupError: + print "Not found!" + +#--------- If "Save" button pressed, selcted workspaces are saved ------------- + def buttonClickHandler1(self): + names = mtd.getObjectNames() + dataToSave=[] + prefix = str(self.lineEdit2.text()) + if (self.lineEdit.text()[len(self.lineEdit.text())-1] != '/'): + path = self.lineEdit.text()+'/' + else: + path = self.lineEdit.text() + + for idx in self.listWidget.selectedItems(): + runlist=parseRunList(str(self.spectraEdit.text())) + print runlist + fname=str(path+prefix+idx.text()) + if (self.comboBox.currentIndex() == 0): + fname+='.dat' + print "FILENAME: ", fname + a1=mantid.getMatrixWorkspace(str(idx.text())) + titl='#'+a1.getTitle()+'\n' + x1=a1.readX(0) + X1=n.zeros((len(x1)-1)) + for i in range(0,len(x1)-1): + X1[i]=(x1[i]+x1[i+1])/2.0 + y1=a1.readY(0) + e1=a1.readE(0) + if (self.radio1.isChecked()): + sep=',' + elif (self.radio2.isChecked()): + sep=' ' + elif (self.radio3.isChecked()): + sep='\t' + + f=open(fname,'w') + if self.titleCheckBox.isChecked(): + f.write(titl) + samp = a1.getSampleDetails() + for log in self.listWidget2.selectedItems(): + + prop = samp.getLogData(str(log.text())) + headerLine='#'+log.text() + ': ' + str(prop.value) + '\n' + print headerLine + f.write(headerLine) + qres=(X1[1]-X1[0])/X1[1] + print "Constant dq/q from file: ",qres + for i in range(len(X1)): + if self.xErrorCheckBox.isChecked(): + dq=X1[i]*qres + s="%e" % X1[i] +sep+"%e" % y1[i] +sep + "%e" % e1[i] + sep + "%e" % dq +"\n" + else: + s="%e" % X1[i] +sep+"%e" % y1[i] +sep + "%e" % e1[i]+ "\n" + f.write(s) + f.close() + elif (self.comboBox.currentIndex() == 1): + print "Not yet implemented!" + elif (self.comboBox.currentIndex() == 2): + print "ANSTO format" + self.saveANSTO(idx,fname) + elif (self.comboBox.currentIndex() == 3): + print "ILL MFT format" + self.saveMFT(idx,fname) + + + # for idx in self.listWidget.selectedItems(): + # fname=str(path+prefix+idx.text()+'.dat') + # print "FILENAME: ", fname + # wksp=str(idx.text()) + # SaveAscii(InputWorkspace=wksp,Filename=fname) + + Ui_MainWindow.SavePath=self.lineEdit.text() + + def saveANSTO(self,idx,fname): + fname+='.txt' + print "FILENAME: ", fname + a1=mantid.getMatrixWorkspace(str(idx.text())) + titl='#'+a1.getTitle()+'\n' + x1=a1.readX(0) + X1=n.zeros((len(x1)-1)) + for i in range(0,len(x1)-1): + X1[i]=(x1[i]+x1[i+1])/2.0 + y1=a1.readY(0) + e1=a1.readE(0) + sep='\t' + f=open(fname,'w') + qres=(X1[1]-X1[0])/X1[1] + print "Constant dq/q from file: ",qres + for i in range(len(X1)): + dq=X1[i]*qres + s="%e" % X1[i] +sep+"%e" % y1[i] +sep + "%e" % e1[i] + sep + "%e" % dq +"\n" + f.write(s) + f.close() + + def saveMFT(self,idx,fname): + fname+='.mft' + print "FILENAME: ", fname + a1=mantid.getMatrixWorkspace(str(idx.text())) + titl=a1.getTitle()+'\n' + x1=a1.readX(0) + X1=n.zeros((len(x1)-1)) + for i in range(0,len(x1)-1): + X1[i]=(x1[i]+x1[i+1])/2.0 + y1=a1.readY(0) + e1=a1.readE(0) + sep='\t' + f=open(fname,'w') + f.write('MFT\n') + f.write('Instrument: '+a1.getInstrument().getName()+'\n') + f.write('User-local contact: \n') + f.write('Title: \n') + samp = a1.getSampleDetails() + s = 'Subtitle: '+samp.getLogData('run_title').value+'\n' + f.write(s) + s = 'Start date + time: '+samp.getLogData('run_start').value+'\n' + f.write(s) + s = 'End date + time: '+samp.getLogData('run_end').value+'\n' + f.write(s) + + for log in self.listWidget2.selectedItems(): + + prop = samp.getLogData(str(log.text())) + headerLine=log.text() + ': ' + str(prop.value) + '\n' + print headerLine + f.write(headerLine) + f.write('Number of file format: 2\n') + s = 'Number of data points:\t' + str(len(X1))+'\n' + f.write(s) + f.write('\n') + f.write('\tq\trefl\trefl_err\tq_res\n') + qres=(X1[1]-X1[0])/X1[1] + print "Constant dq/q from file: ",qres + for i in range(len(X1)): + dq=X1[i]*qres + s="\t%e" % X1[i] +sep+"%e" % y1[i] +sep + "%e" % e1[i] + sep + "%e" % dq +"\n" + f.write(s) + f.close() From a6ddad0f29ac4d86fbcb2395eae827be8567e351 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Tue, 17 Dec 2013 12:07:46 -0500 Subject: [PATCH 228/403] Refs #8631 Inelastic part: moved constraints to init modified: DiffRotDiscreteCircle.h modified: DiffRotDiscreteCircle.cpp --- .../inc/MantidCurveFitting/DiffRotDiscreteCircle.h | 2 +- .../Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h index 75d1f985f20b..dc33aea921d2 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -77,7 +77,7 @@ class DLLExport InelasticDiffRotDiscreteCircle : public API::ParamFunction, publ virtual std::string name() const { return "InelasticDiffRotDiscreteCircle"; } - // virtual void init(); + virtual void init(); protected: diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 6a4285d53102..008ef635089c 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -117,7 +117,10 @@ InelasticDiffRotDiscreteCircle::InelasticDiffRotDiscreteCircle() : m_h(4.1356656 declareAttribute( "Q", API::IFunction::Attribute( 0.5 ) ); declareAttribute( "N", API::IFunction::Attribute( 3 ) ); +} +void InelasticDiffRotDiscreteCircle::init() +{ // Ensure positive values for Intensity, Radius, and decay BoundaryConstraint* IntensityConstraint = new BoundaryConstraint( this, "Intensity", std::numeric_limits< double >::epsilon(), true ); addConstraint(IntensityConstraint); From 6ee6bb1989285b91391278b7693a605ae2f04253 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Tue, 17 Dec 2013 12:09:43 -0500 Subject: [PATCH 229/403] Refs #8611 store in nxs file --- Code/Mantid/Framework/API/src/Run.cpp | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Code/Mantid/Framework/API/src/Run.cpp b/Code/Mantid/Framework/API/src/Run.cpp index a1eb556b79f7..bb98b5b83f11 100644 --- a/Code/Mantid/Framework/API/src/Run.cpp +++ b/Code/Mantid/Framework/API/src/Run.cpp @@ -32,6 +32,9 @@ namespace const char * GONIOMETER_LOG_NAME = "goniometer"; /// Name of the stored histogram bins log when saved to NeXus const char * HISTO_BINS_LOG_NAME = "processed_histogram_bins"; + const char * PEAK_RADIUS_GROUP = "peak_radius"; + const char * INNER_BKG_RADIUS_GROUP = "inner_bkg_radius"; + const char * OUTER_BKG_RADIUS_GROUP = "outer_bkg_radius"; } // Get a reference to the logger Kernel::Logger& Run::g_log = Kernel::Logger::get("Run"); @@ -358,7 +361,31 @@ Kernel::Logger& Run::g_log = Kernel::Logger::get("Run"); file->writeData("value", m_histoBins); file->closeGroup(); } + if( this->hasProperty("PeakRadius") ) + { + const std::vector & values = + this->getPropertyValueAsType >("PeakRadius"); + file->makeGroup(PEAK_RADIUS_GROUP, "NXdata", 1); + file->writeData("value", values); + file->closeGroup(); + } + if( this->hasProperty("BackgroundInnerRadius") ) + { + file->makeGroup(INNER_BKG_RADIUS_GROUP, "NXdata", 1); + const std::vector & values = + this->getPropertyValueAsType >("BackgroundInnerRadius"); + file->writeData("value", values); + file->closeGroup(); + } + if( this->hasProperty("BackgroundOuterRadius") ) + { + file->makeGroup(OUTER_BKG_RADIUS_GROUP, "NXdata", 1); + const std::vector & values = + this->getPropertyValueAsType >("BackgroundOuterRadius"); + file->writeData("value", values); + file->closeGroup(); + } if(!keepOpen)file->closeGroup(); } @@ -392,6 +419,30 @@ Kernel::Logger& Run::g_log = Kernel::Logger::get("Run"); file->readData("value",m_histoBins); file->closeGroup(); } + else if(name_class.first == PEAK_RADIUS_GROUP) + { + file->openGroup(name_class.first, "NXdata"); + std::vector values; + file->readData("value",values); + file->closeGroup(); + this->addProperty("PeakRadius",values, true); + } + else if(name_class.first == INNER_BKG_RADIUS_GROUP) + { + file->openGroup(name_class.first, "NXdata"); + std::vector values; + file->readData("value",values); + file->closeGroup(); + this->addProperty("BackgroundInnerRadius",values, true); + } + else if(name_class.first == OUTER_BKG_RADIUS_GROUP) + { + file->openGroup(name_class.first, "NXdata"); + std::vector values; + file->readData("value",values); + file->closeGroup(); + this->addProperty("BackgroundOuterRadius",values, true); + } else if (name_class.first == "proton_charge" && !this->hasProperty("proton_charge")) { // Old files may have a proton_charge field, single value (not even NXlog) From 717d92ecb6e7b1ff8891d3a4c3c0ef61df3e6dde Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Tue, 17 Dec 2013 13:20:04 -0500 Subject: [PATCH 230/403] Refs #8631 moved steps to init modified: DiffRotDiscreteCircle.h modified: DiffRotDiscreteCircle.cpp modified: DiffRotDiscreteCircleTest.h --- .../DiffRotDiscreteCircle.h | 5 ++--- .../src/DiffRotDiscreteCircle.cpp | 19 ++++++++++--------- .../test/DiffRotDiscreteCircleTest.h | 2 ++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h index dc33aea921d2..9ae2af98d07c 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/DiffRotDiscreteCircle.h @@ -98,9 +98,6 @@ class DLLExport DiffRotDiscreteCircle : public API::ImmutableCompositeFunction { public: - /// Constructor - DiffRotDiscreteCircle(); - /// Destructor ~DiffRotDiscreteCircle() {}; @@ -110,6 +107,8 @@ class DLLExport DiffRotDiscreteCircle : public API::ImmutableCompositeFunction virtual int version() const { return 1; } + virtual void init(); + /// Propagate an attribute to member functions virtual void trickleDownAttribute( const std::string &name ); diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index 008ef635089c..fc873ccf2bb1 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -208,26 +208,27 @@ void DiffRotDiscreteCircle::setAttribute( const std::string& name, const Attribu trickleDownAttribute( name ); } -DiffRotDiscreteCircle::DiffRotDiscreteCircle() +//DiffRotDiscreteCircle::DiffRotDiscreteCircle() +void DiffRotDiscreteCircle::init() { m_elastic = boost::dynamic_pointer_cast( API::FunctionFactory::Instance().createFunction( "ElasticDiffRotDiscreteCircle" ) ); addFunction( m_elastic ); m_inelastic = boost::dynamic_pointer_cast( API::FunctionFactory::Instance().createFunction( "InelasticDiffRotDiscreteCircle" ) ); addFunction( m_inelastic ); - this->setAttributeValue( "NumDeriv", true ); + setAttributeValue( "NumDeriv", true ); - this->declareAttribute( "Q", API::IFunction::Attribute( 0.5 ) ); - this->declareAttribute( "N", API::IFunction::Attribute( 3 ) ); + declareAttribute( "Q", API::IFunction::Attribute( 0.5 ) ); + declareAttribute( "N", API::IFunction::Attribute( 3 ) ); //Set the aliases - this->setAlias( "f1.Intensity", "Intensity" ); - this->setAlias( "f1.Radius", "Radius" ); - this->setAlias( "f1.Decay", "Decay" ); + setAlias( "f1.Intensity", "Intensity" ); + setAlias( "f1.Radius", "Radius" ); + setAlias( "f1.Decay", "Decay" ); //Set the ties between Elastic and Inelastic parameters - this->addDefaultTies( "f0.Height=f1.Intensity,f0.Radius=f1.Radius" ); - this->applyTies(); + addDefaultTies( "f0.Height=f1.Intensity,f0.Radius=f1.Radius" ); + applyTies(); } diff --git a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h index 05d608817fc3..66414510910a 100644 --- a/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/DiffRotDiscreteCircleTest.h @@ -189,6 +189,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite const double Q = 0.7; const int N = 4; Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.init(); func.setParameter( "f1.Intensity", I ); func.setParameter( "f1.Radius" , R ); func.setParameter( "f1.Decay", tao ); @@ -221,6 +222,7 @@ class DiffRotDiscreteCircleTest : public CxxTest::TestSuite // This should set parameters of the inelastic part Mantid::CurveFitting::DiffRotDiscreteCircle func; + func.init(); func.setParameter( "Intensity", I ); func.setParameter( "Radius", R ); func.setParameter( "Decay", tao ); From ca0d69aaa831c9dd797b635fe06785a4f06ada2e Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Tue, 17 Dec 2013 14:01:00 -0500 Subject: [PATCH 231/403] Refs #8280 warning for overlap --- .../MantidMDAlgorithms/IntegratePeaksMD2.h | 4 +++ .../MDAlgorithms/src/IntegratePeaksMD2.cpp | 33 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/IntegratePeaksMD2.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/IntegratePeaksMD2.h index f78b1555a8f2..74a78a88ac97 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/IntegratePeaksMD2.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/IntegratePeaksMD2.h @@ -51,6 +51,10 @@ namespace MDAlgorithms /// Instrument reference Geometry::Instrument_const_sptr inst; + /// Check if peaks overlap + void checkOverlap(int i, + Mantid::DataObjects::PeaksWorkspace_sptr peakWS, int CoordinatesToUse, double radius); + }; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp index 6d2968fba409..3541f44b1f5e 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp @@ -593,6 +593,8 @@ namespace MDAlgorithms } } } + checkOverlap (i, peakWS, CoordinatesToUse, + std::max(PeakRadiusVector[i],BackgroundOuterRadiusVector[i])); // Save it back in the peak object. if (signal != 0. || replaceIntensity) { @@ -676,7 +678,36 @@ namespace MDAlgorithms } return in; } - + void IntegratePeaksMD2::checkOverlap(int i, + Mantid::DataObjects::PeaksWorkspace_sptr peakWS, int CoordinatesToUse, double radius) + { + // Get a direct ref to that peak. + IPeak & p1 = peakWS->getPeak(i); + V3D pos1; + if (CoordinatesToUse == 1) //"Q (lab frame)" + pos1 = p1.getQLabFrame(); + else if (CoordinatesToUse == 2) //"Q (sample frame)" + pos1 = p1.getQSampleFrame(); + else if (CoordinatesToUse == 3) //"HKL" + pos1 = p1.getHKL(); + for (int j=i+1; j < peakWS->getNumberPeaks(); ++j) + { + // Get a direct ref to rest of peaks peak. + IPeak & p2 = peakWS->getPeak(j); + V3D pos2; + if (CoordinatesToUse == 1) //"Q (lab frame)" + pos2 = p2.getQLabFrame(); + else if (CoordinatesToUse == 2) //"Q (sample frame)" + pos2 = p2.getQSampleFrame(); + else if (CoordinatesToUse == 3) //"HKL" + pos2 = p2.getHKL(); + if (pos1.distance(pos2) < radius) + { + g_log.warning() << " Warning: Peak integration spheres for peaks " + << i << " and " << j <<" overlap. Distance between peaks is "<< pos1.distance(pos2)< Date: Tue, 17 Dec 2013 14:52:56 -0500 Subject: [PATCH 232/403] Refs #8631 Modified WIKI header modified: DiffRotDiscreteCircle.cpp --- .../CurveFitting/src/DiffRotDiscreteCircle.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp index fc873ccf2bb1..c7d323e8a900 100644 --- a/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/DiffRotDiscreteCircle.cpp @@ -17,7 +17,7 @@ The Decay fitting parameter \tau is the inverse of the transition r
\tau_l^{-1} = 4 \tau^{-1} sin^2(\frac{\pi l}{N})
-If the unit of \omega is energy, and the energy unit is \mueV, then \tau is expressed in nano-seconds. If E-unit is meV then \tau is expressed in pico-seconds. The conversion equation used between the jump transition rate k, expressed in energy units, and \tau is: k\cdot \tau=4.136\, meV\cdot ps=4.136\, \mu eV\cdot ns +The transition rate, expressed in units of energy is h\tau^{-1}, with h = 4.135665616 meV THz. == Example: Methyl Rotations == Methyl Rotations can be modelled setting N=3. In this case, the inelastic part reduces to a single Lorentzian: @@ -26,10 +26,10 @@ Methyl Rotations can be modelled setting N=3. In this case, the inelastic part r If, alternatively, one models these dynamics using the [[Lorentzian]] function provided in Mantid: -
S(Q,E) = A \delta (\omega) + \frac{B}{\pi} \left( \frac{\frac{\Gamma}{2}}{(\frac{\Gamma}{2})^2 + \omega^2}\right)
-Then the following equalities hold: -
B = 2\,A_1
-
\Gamma = 6\cdot 4.126/\tau
+
S(Q,E) = A \delta (\omega) + \frac{B}{\pi} \left( \frac{\frac{\Gamma}{2}}{(\frac{\Gamma}{2})^2 + (\hbar\omega)^2}\right)
+Then: +
B = \frac{1}{\pi}h A_1
+
\Gamma = \frac{3}{\pi} h\tau^{-1} = 3.949269754 meV\cdot THz \cdot \tau^{-1}
== Properties == @@ -55,7 +55,6 @@ Then the following equalities hold: |inverse of the transition rate (ps if energy in meV; ns if energy in \mueV) |} - [[Category:Fit_functions]] *WIKI*/ From be74ef8ee7a048f5eeb62a4bf9823db07fd37741 Mon Sep 17 00:00:00 2001 From: Andrei Savici Date: Tue, 17 Dec 2013 16:33:57 -0500 Subject: [PATCH 233/403] MaskAngle algorithm. Refs #8626 --- .../plugins/algorithms/MaskAngle.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py new file mode 100644 index 000000000000..b04af5211b41 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py @@ -0,0 +1,58 @@ +""" +Algorithm to mask detectors with scattering angles in a given interval (in degrees) +By default MinAngle=0, MaxAngle=180, so if no keywords are set, all detectors are going to be masked +Returns a list of detectors that were masked +""" + +import mantid.simpleapi +import mantid.kernel +import mantid.api +import numpy + +class MaskAngle(mantid.api.PythonAlgorithm): + """ Class to generate grouping file + """ + + def category(self): + """ Mantid required + """ + return "PythonAlgorithms;Transforms\\Masking" + + def name(self): + """ Mantid require + """ + return "MaskAngle" + + def PyInit(self): + self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "", direction=mantid.kernel.Direction.Input), "Input workspace") + angleValidator=mantid.kernel.FloatBoundedValidator() + angleValidator.setBounds(0.,180.) + self.declareProperty(name="MinAngle", defaultValue=0.0, validator=angleValidator, direction=mantid.kernel.Direction.Input, doc="Angles above StartAngle are going to be masked") + self.declareProperty(name="MaxAngle", defaultValue=0.0, validator=angleValidator, direction=mantid.kernel.Direction.Input, doc="Angles above StartAngle are going to be masked") + self.declareProperty(mantid.kernel.IntArrayProperty(name="MaskedDetectors", direction=mantid.kernel.Direction.Output), doc="List of detector masked, with scatterin angles between MinAngle and MaxAngle") + + def PyExec(self): + ws = self.getProperty("Workspace").value + ttmin = self.getProperty("MinAngle").value + ttmax = self.getProperty("MaxAngle").value + if ttmin > ttmax : + raise ValueError("MinAngle > MaxAngle, please check angle range for masking") + + detlist=[] + + + numspec = ws.getNumberHistograms() + for i in range(numspec): + det=ws.getDetector(i) + if not det.isMonitor(): + tt=numpy.degrees(det.getTwoTheta(mantid.kernel.V3D(0,0,0),mantid.kernel.V3D(0,0,1))) + if tt>= ttmin and tt<= ttmax: + detlist.append(det.getID()) + + if len(detlist)> 0: + mantid.simpleapi.MaskDetectors(Workspace=ws,DetectorList=detlist) + else: + self.log().information("no detectors within this range") + self.setProperty("MaskedDetectors", numpy.array(detlist)) + +mantid.api.AlgorithmFactory.subscribe(MaskAngle) From 467eb0977e080a2cbb9cfc111fe71cf019b47a78 Mon Sep 17 00:00:00 2001 From: Andrei Savici Date: Tue, 17 Dec 2013 19:28:05 -0500 Subject: [PATCH 234/403] Unit test for MaskAngle. Refs #8626 InstrumentValidator not working for some reason --- .../plugins/algorithms/MaskAngle.py | 7 ++++-- .../python/plugins/algorithms/CMakeLists.txt | 1 + .../plugins/algorithms/MaskAngleTest.py | 23 +++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py index b04af5211b41..88b649a97a8b 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py @@ -24,7 +24,8 @@ def name(self): return "MaskAngle" def PyInit(self): - self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "", direction=mantid.kernel.Direction.Input), "Input workspace") + instvalid= + self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "",direction=mantid.kernel.Direction.Input,validator=mantid.api.InstrumentValidator()), "Input workspace") angleValidator=mantid.kernel.FloatBoundedValidator() angleValidator.setBounds(0.,180.) self.declareProperty(name="MinAngle", defaultValue=0.0, validator=angleValidator, direction=mantid.kernel.Direction.Input, doc="Angles above StartAngle are going to be masked") @@ -42,10 +43,12 @@ def PyExec(self): numspec = ws.getNumberHistograms() + source=ws.getInstrument().getSource().getPos() + sample=ws.getInstrument().getSample().getPos() for i in range(numspec): det=ws.getDetector(i) if not det.isMonitor(): - tt=numpy.degrees(det.getTwoTheta(mantid.kernel.V3D(0,0,0),mantid.kernel.V3D(0,0,1))) + tt=numpy.degrees(det.getTwoTheta(sample,sample-source)) if tt>= ttmin and tt<= ttmax: detlist.append(det.getID()) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index 7bad2236ccb5..786892b0038d 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -15,6 +15,7 @@ set ( TEST_PY_FILES LoadLiveDataTest.py LoadLogPropertyTableTest.py LoadMultipleGSSTest.py + MaskAngleTest.py MaskWorkspaceToCalFileTest.py MeanTest.py MergeCalFilesTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py new file mode 100644 index 000000000000..5d34e73dcbdc --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py @@ -0,0 +1,23 @@ +import unittest +from mantid.simpleapi import * +from mantid.api import * +from testhelpers import * +from numpy import * + +class MaskAngleTest(unittest.TestCase): + + def testMaskAngle(self): + w=WorkspaceCreationHelper.create2DWorkspaceWithFullInstrument(30,5,False,False) + AnalysisDataService.add('w',w) + masklist = MaskAngle(w,10,20) + for i in arange(w.getNumberHistograms())+1: + if (i<10) or (i>19): + self.assertTrue(not w.getInstrument().getDetector(i).isMasked()) + else: + self.assertTrue(w.getInstrument().getDetector(i).isMasked()) + DeleteWorkspace(w) + self.assertTrue(array_equal(masklist,arange(10)+10)) + + +if __name__ == '__main__': + unittest.main() From c7abd61dfc3a40d6f5fd1dec24daff2592d2a8d5 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Mon, 16 Dec 2013 11:23:06 +0000 Subject: [PATCH 235/403] refs #8616. Adding properties to dec. --- .../CreateTransmissionWorkspaceAuto.py | 63 +++++++++++++++++++ .../python/plugins/algorithms/CMakeLists.txt | 1 + .../CreateTransmissionWorkspaceAutoTest.py | 15 +++++ 3 files changed, 79 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py new file mode 100644 index 000000000000..f20d406052b1 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py @@ -0,0 +1,63 @@ +import mantid.simpleapi +from mantid.api import * +from mantid.kernel import * + +class CreateTransmissionWorkspaceAuto(PythonAlgorithm): + + def category(self): + return "Reflectometry\\ISIS" + + def name(self): + return "CreateTransmissionWorkspaceAuto" + + def PyInit(self): + + ''' + + declareProperty( + new ArrayProperty("Params", boost::make_shared(true)), + "A comma separated list of first bin boundary, width, last bin boundary. " + "These parameters are used for stitching together transmission runs. " + "Values are in wavelength (angstroms). This input is only needed if a SecondTransmission run is provided."); + + declareProperty( + new PropertyWithValue("StartOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "Start wavelength for stitching transmission runs together"); + + declareProperty( + new PropertyWithValue("EndOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "End wavelength (angstroms) for stitching transmission runs together"); + + + this->initStitchingInputs(); + this->initIndexInputs(); + this->initWavelengthInputs(); + + declareProperty(new WorkspaceProperty("OutputWorkspace", "", Direction::Output), + "Output Workspace IvsQ."); + + ''' + + + input_validator = WorkspaceUnitValidator("TOF") + self.declareProperty(MatrixWorkspaceProperty("FirstTransmissionRun", "", Direction.Input, validator=input_validator), "Input workspace") + self.declareProperty(MatrixWorkspaceProperty("SecondTransmissionRun", "", optional=PropertyMode.Optional, validator=input_validator, direction=Direction.Input), "Second transmission run workspace in TOF") + self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output transmission workspace in wavelength") + self.declareProperty(FloatArrayProperty(name="Params", values=[0.1]), doc="Rebinning Parameters. See Rebin for format.") + + self.declareProperty(name="StartOverlap", defaultValue=-1.0, doc="Overlap in Q.") + self.declareProperty(name="EndOverlap", defaultValue=-1.0, doc="End overlap in Q.") + + + + + def PyExec(self): + firstws = self.getProperty("FirstTransmissionRun").value + secondws = self.getProperty("SecondTransmissionRun").value + start_overlap = self.getProperty("StartOverlap").value + end_overlap = self.getProperty("EndOverlap").value + params = self.getProperty("Params").value + + self.setProperty("OutputWorkspace", firstws) + +AlgorithmFactory.subscribe(CreateTransmissionWorkspaceAuto) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index 7bad2236ccb5..a817bd35f27f 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -8,6 +8,7 @@ set ( TEST_PY_FILES CreateLeBailFitInputTest.py CreateWorkspaceTest.py CreateTransmissionWorkspaceTest.py + CreateTransmissionWorkspaceAutoTest.py DakotaChiSquaredTest.py FilterLogByTimeTest.py FindReflectometryLinesTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py new file mode 100644 index 000000000000..4596e89d6f0c --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py @@ -0,0 +1,15 @@ +import unittest +import mantid.api +from mantid.simpleapi import * + +class CreateTransmissionWorkspaceAutoTest(unittest.TestCase): + + + def test_input_workspace_not_tof_throws(self): + inws = CreateWorkspace(DataY=[1,1,1], DataX=[0,1,2,3], UnitX="TOF") + out = CreateTransmissionWorkspaceAuto(FirstTransmissionRun=inws) + + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 4eb962c5788ba83f21536d37ab34115025faac40 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Mon, 16 Dec 2013 11:49:52 +0000 Subject: [PATCH 236/403] refs #8616. Add remaining properties. --- .../CreateTransmissionWorkspaceAuto.py | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py index f20d406052b1..5064ba17fb3a 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py @@ -1,3 +1,4 @@ +import sys import mantid.simpleapi from mantid.api import * from mantid.kernel import * @@ -12,43 +13,26 @@ def name(self): def PyInit(self): - ''' - - declareProperty( - new ArrayProperty("Params", boost::make_shared(true)), - "A comma separated list of first bin boundary, width, last bin boundary. " - "These parameters are used for stitching together transmission runs. " - "Values are in wavelength (angstroms). This input is only needed if a SecondTransmission run is provided."); - - declareProperty( - new PropertyWithValue("StartOverlap", Mantid::EMPTY_DBL(), Direction::Input), - "Start wavelength for stitching transmission runs together"); - - declareProperty( - new PropertyWithValue("EndOverlap", Mantid::EMPTY_DBL(), Direction::Input), - "End wavelength (angstroms) for stitching transmission runs together"); - - - this->initStitchingInputs(); - this->initIndexInputs(); - this->initWavelengthInputs(); - - declareProperty(new WorkspaceProperty("OutputWorkspace", "", Direction::Output), - "Output Workspace IvsQ."); - - ''' - input_validator = WorkspaceUnitValidator("TOF") self.declareProperty(MatrixWorkspaceProperty("FirstTransmissionRun", "", Direction.Input, validator=input_validator), "Input workspace") self.declareProperty(MatrixWorkspaceProperty("SecondTransmissionRun", "", optional=PropertyMode.Optional, validator=input_validator, direction=Direction.Input), "Second transmission run workspace in TOF") self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output transmission workspace in wavelength") - self.declareProperty(FloatArrayProperty(name="Params", values=[0.1]), doc="Rebinning Parameters. See Rebin for format.") - - self.declareProperty(name="StartOverlap", defaultValue=-1.0, doc="Overlap in Q.") - self.declareProperty(name="EndOverlap", defaultValue=-1.0, doc="End overlap in Q.") - - + + self.declareProperty(FloatArrayProperty(name="Params", values=[sys.maxint]), doc="Rebinning Parameters. See Rebin for format.") + self.declareProperty(name="StartOverlap", defaultValue=sys.maxint, doc="Overlap in Q.") + self.declareProperty(name="EndOverlap", defaultValue=sys.maxint, doc="End overlap in Q.") + index_bounds = IntBoundedValidator() + index_bounds.setLower(0) + self.declareProperty(name="I0MonitorIndex", defaultValue=sys.maxint, validator=index_bounds, doc="I0 monitor index" ) + self.declareProperty(IntArrayProperty(name="WorkspaceIndexList", values=[sys.maxint]), doc="Workspace index list") + self.declareProperty(name="WavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength Min in angstroms") + self.declareProperty(name="WavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength Max in angstroms") + self.declareProperty(name="WavelengthStep", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength step in angstroms") + self.declareProperty(name="MonitorBackgroundWavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor wavelength background min in angstroms") + self.declareProperty(name="MonitorBackgroundWavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor wavelength background max in angstroms") + self.declareProperty(name="MonitorIntegrationWavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral min in angstroms") + self.declareProperty(name="MonitorIntegrationWavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral max in angstroms") def PyExec(self): From b5cb1a53f177a24979c659cfd493384af181228c Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Mon, 16 Dec 2013 17:36:12 +0000 Subject: [PATCH 237/403] refs #8616. Implemented now extending tests. Have subclassed the existing test methods as these all should still work. --- .../CreateTransmissionWorkspaceAuto.py | 102 ++++++++++++++++-- .../CreateTransmissionWorkspaceAutoTest.py | 37 ++++++- .../CreateTransmissionWorkspaceTest.py | 43 ++++---- 3 files changed, 148 insertions(+), 34 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py index 5064ba17fb3a..33515f77ab89 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py @@ -1,5 +1,15 @@ +"""*WIKI* + +Facade over [[CreateTransmissionWorkspace]]. Pull numeric parameters out of the instrument parameters where possible. You can override any of these automatically +applied defaults by providing your own value for the input. + +See [[CreateTransmissionWorkspace]] for more information on the wrapped algorithm. + +*WIKI*""" + + import sys -import mantid.simpleapi +from mantid.simpleapi import CreateTransmissionWorkspace from mantid.api import * from mantid.kernel import * @@ -13,6 +23,10 @@ def name(self): def PyInit(self): + analysis_modes = ["PointDetectorAnalysis", "MultiDetectorAnalysis"] + analysis_mode_validator = StringListValidator(analysis_modes) + + self.declareProperty(name="AnalysisMode", defaultValue=analysis_modes[0], validator=analysis_mode_validator, direction = Direction.Input, doc="Analysis Mode to Choose") input_validator = WorkspaceUnitValidator("TOF") self.declareProperty(MatrixWorkspaceProperty("FirstTransmissionRun", "", Direction.Input, validator=input_validator), "Input workspace") @@ -20,8 +34,8 @@ def PyInit(self): self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output transmission workspace in wavelength") self.declareProperty(FloatArrayProperty(name="Params", values=[sys.maxint]), doc="Rebinning Parameters. See Rebin for format.") - self.declareProperty(name="StartOverlap", defaultValue=sys.maxint, doc="Overlap in Q.") - self.declareProperty(name="EndOverlap", defaultValue=sys.maxint, doc="End overlap in Q.") + self.declareProperty(name="StartOverlap", defaultValue=sys.float_info.max, doc="Overlap in Q.") + self.declareProperty(name="EndOverlap", defaultValue=sys.float_info.max, doc="End overlap in Q.") index_bounds = IntBoundedValidator() index_bounds.setLower(0) self.declareProperty(name="I0MonitorIndex", defaultValue=sys.maxint, validator=index_bounds, doc="I0 monitor index" ) @@ -34,14 +48,82 @@ def PyInit(self): self.declareProperty(name="MonitorIntegrationWavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral min in angstroms") self.declareProperty(name="MonitorIntegrationWavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral max in angstroms") - + + def value_or_none(self, prop_name, instrument): + property = self.getProperty(prop_name) + if property.isDefault: + return None # TODO: check this + else: + return property.value + + + def value_to_apply(self, prop_name, instrument, idf_name=""): + property = self.getProperty(prop_name) + if property.isDefault: + return instrument.getNumberParameter(idf_name)[0] + else: + return property.value + def PyExec(self): - firstws = self.getProperty("FirstTransmissionRun").value - secondws = self.getProperty("SecondTransmissionRun").value - start_overlap = self.getProperty("StartOverlap").value - end_overlap = self.getProperty("EndOverlap").value - params = self.getProperty("Params").value + first_ws = self.getProperty("FirstTransmissionRun").value + instrument = first_ws.getInstrument() + + ''' + Get all the inputs. + ''' + outputWorkspaceName = self.getPropertyValue("OutputWorkspace") + + analysis_mode = self.getPropertyValue("AnalysisMode") + + second_ws_property = self.getProperty("SecondTransmissionRun") + second_ws = None + if not second_ws_property.isDefault: + second_ws = second_ws_property.value + + start_overlap = self.value_or_none("StartOverlap", instrument) + + end_overlap = self.value_or_none("EndOverlap", instrument) + + params = self.value_or_none("Params", instrument) + + i0_monitor_index = int(self.value_to_apply("I0MonitorIndex", instrument, "I0MonitorIndex")) + + workspace_index_list = list() + if self.getProperty("WorkspaceIndexList").isDefault: + if analysis_mode == "PointDetectorAnalysis": + workspace_index_list.append( int(instrument.getNumberParameter("PointDetectorStart")[0]) ) + workspace_index_list.append( int(instrument.getNumberParameter("PointDetectorStop")[0]) ) + else: + workspace_index_list.append( int(instrument.getNumberParameter("MultiDetectorStart")[0]) ) + workspace_index_list.append( first_ws.getNumberHistograms() - 1) + else: + workspace_index_list = self.getProperty("WorkspaceIndexList").value + + wavelength_min = self.value_to_apply("WavelengthMin", instrument, "LambdaMin") + + wavelength_max = self.value_to_apply("WavelengthMax", instrument, "LambdaMax") + print wavelength_min, wavelength_max + + wavelength_step = self.value_or_none("WavelengthStep", instrument) + + wavelength_back_min = self.value_to_apply("MonitorBackgroundWavelengthMin", instrument, "MonitorBackgroundMin") + + wavelength_back_max = self.value_to_apply("MonitorBackgroundWavelengthMax", instrument, "MonitorBackgroundMax") + + wavelength_integration_min = self.value_to_apply("MonitorIntegrationWavelengthMin", instrument, "MonitorIntegralMin") + + wavelength_integration_max = self.value_to_apply("MonitorIntegrationWavelengthMax", instrument, "MonitorIntegralMax") + + ''' + Pass the arguments and execute the main algorithm. + ''' + output_ws = CreateTransmissionWorkspace(FirstTransmissionRun=first_ws, SecondTransmissionRun=second_ws, OutputWorkspace=outputWorkspaceName, + StartOverlap=start_overlap, EndOverlap=end_overlap, Params=params, I0MonitorIndex=i0_monitor_index, + WorkspaceIndexList=workspace_index_list, WavelengthMin=wavelength_min, WavelengthStep=wavelength_step, WavelengthMax=wavelength_max, + MonitorBackgroundWavelengthMin=wavelength_back_min, MonitorBackgroundWavelengthMax=wavelength_back_max, + MonitorIntegrationWavelengthMin=wavelength_integration_min, MonitorIntegrationWavelengthMax=wavelength_integration_max) + - self.setProperty("OutputWorkspace", firstws) + self.setProperty("OutputWorkspace", output_ws) AlgorithmFactory.subscribe(CreateTransmissionWorkspaceAuto) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py index 4596e89d6f0c..a1890be1ebb5 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py @@ -1,15 +1,42 @@ import unittest +from testhelpers.algorithm_decorator import make_decorator import mantid.api +from CreateTransmissionWorkspaceTest import CreateTransmissionWorkspaceTest from mantid.simpleapi import * -class CreateTransmissionWorkspaceAutoTest(unittest.TestCase): +class CreateTransmissionWorkspaceAutoTest(CreateTransmissionWorkspaceTest): + def __init__(self, *args, **kwargs): + super(CreateTransmissionWorkspaceAutoTest, self).__init__(*args, **kwargs) + trans1 = Load('INTER00013463.nxs', OutputWorkspace="trans1") + trans2 = Load('INTER00013464.nxs', OutputWorkspace="trans2") + self.__trans1 = trans1 + self.__trans2 = trans2 + + def setUp(self): + super(CreateTransmissionWorkspaceAutoTest, self).setUp() + standard_alg = make_decorator(self.algorithm_type()) + self.__standard_alg = standard_alg + + def __del__(self): + pass + #DeleteWorkspace(self.__trans1) + #DeleteWorkspace(self.__trans2) + + + def algorithm_type(self): + return CreateTransmissionWorkspaceAuto - def test_input_workspace_not_tof_throws(self): - inws = CreateWorkspace(DataY=[1,1,1], DataX=[0,1,2,3], UnitX="TOF") - out = CreateTransmissionWorkspaceAuto(FirstTransmissionRun=inws) + def test_use_point_detector_start(self): + alg = self.__standard_alg + print self.__trans1 + alg.set_FirstTransmissionRun(self.__trans1) + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.execute() - + + + if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index 7ceca8566a6e..ecbb1226f485 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -1,5 +1,6 @@ import unittest import mantid.api +from abc import abstractmethod from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace, Load from testhelpers.algorithm_decorator import make_decorator @@ -8,6 +9,10 @@ class CreateTransmissionWorkspaceTest(unittest.TestCase): + @abstractmethod + def algorithm_type(self): + return CreateTransmissionWorkspace + def setUp(self): tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) @@ -19,7 +24,7 @@ def tearDown(self): DeleteWorkspace(self.__not_tof) def construct_standard_algorithm(self): - alg = make_decorator(CreateTransmissionWorkspace) + alg = make_decorator(self.algorithm_type()) alg.set_FirstTransmissionRun(self.__tof) alg.set_WavelengthMin(0.0) alg.set_WavelengthMax(1.0) @@ -34,31 +39,31 @@ def construct_standard_algorithm(self): def test_input_workspace_not_tof_throws(self): alg = self.construct_standard_algorithm() alg.set_FirstTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_second_transmission_workspace_not_tof_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_provide_second_transmission_run_without_params_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_provide_second_transmission_run_without_start_overlap_q_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_provide_end_transmission_run_without_end_overlap_q_throws(self): alg = self.construct_standard_algorithm() alg.set_SecondTransmissionRun(self.__tof) alg.set_Params([0, 0.1, 1]) alg.set_StartOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): alg = self.construct_standard_algorithm() @@ -66,49 +71,49 @@ def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): alg.set_Params([0, 0.1, 1]) alg.set_StartOverlap( 0.6 ) alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, CreateTransmissionWorkspace, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, CreateTransmissionWorkspace, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) def test_wavelength_min_greater_wavelength_max_throws(self): alg = self.construct_standard_algorithm() alg.set_WavelengthMin(1.0) alg.set_WavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): alg = self.construct_standard_algorithm() alg.set_MonitorBackgroundWavelengthMin(1.0) alg.set_MonitorBackgroundWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): alg = self.construct_standard_algorithm() alg.set_MonitorIntegrationWavelengthMin(1.0) alg.set_MonitorIntegrationWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_monitor_index_positive(self): alg = self.construct_standard_algorithm() alg.set_I0MonitorIndex(-1) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_workspace_index_list_throw_if_not_pairs(self): alg = self.construct_standard_algorithm() alg.set_WorkspaceIndexList([0]) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_workspace_index_list_values_not_positive_throws(self): alg = self.construct_standard_algorithm() alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): alg = self.construct_standard_algorithm() alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) def test_spectrum_map_mismatch_throws(self): alg = self.construct_standard_algorithm() @@ -121,12 +126,12 @@ def test_spectrum_map_mismatch_throws(self): alg.set_Params([0, 0.1, 1]) alg.set_StartOverlap(1) alg.set_EndOverlap(2) - self.assertRaises(ValueError, alg.execute) + self.assertRaises(Exception, alg.execute) DeleteWorkspace(trans_run1) def test_execute_one_tranmission(self): - alg = make_decorator(CreateTransmissionWorkspace) + alg = make_decorator(self.algorithm_type()) trans_run1 = Load('INTER00013463.nxs') @@ -156,7 +161,7 @@ def test_execute_one_tranmission(self): DeleteWorkspace(transmission_ws) def test_execute_two_tranmissions(self): - alg = make_decorator(CreateTransmissionWorkspace) + alg = make_decorator(self.algorithm_type()) trans_run1 = Load('INTER00013463.nxs') trans_run2 = Load('INTER00013464.nxs') From 6c8c0ae19e3a01500f7119f04df40d69301f48a8 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Tue, 17 Dec 2013 17:23:16 +0000 Subject: [PATCH 238/403] refs #8616. Extend and fix tests. Check via the history that the algorithm values supplied were from the IDF. --- .../CreateTransmissionWorkspaceAuto.py | 1 - .../CreateTransmissionWorkspaceAutoTest.py | 49 ++++++++----------- .../CreateTransmissionWorkspaceTest.py | 1 - 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py index 33515f77ab89..8027a456d226 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py @@ -102,7 +102,6 @@ def PyExec(self): wavelength_min = self.value_to_apply("WavelengthMin", instrument, "LambdaMin") wavelength_max = self.value_to_apply("WavelengthMax", instrument, "LambdaMax") - print wavelength_min, wavelength_max wavelength_step = self.value_or_none("WavelengthStep", instrument) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py index a1890be1ebb5..a37c00e783b2 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py @@ -1,40 +1,33 @@ import unittest -from testhelpers.algorithm_decorator import make_decorator import mantid.api -from CreateTransmissionWorkspaceTest import CreateTransmissionWorkspaceTest +#from CreateTransmissionWorkspaceTest import CreateTransmissionWorkspaceTest from mantid.simpleapi import * -class CreateTransmissionWorkspaceAutoTest(CreateTransmissionWorkspaceTest): +class CreateTransmissionWorkspaceAutoTest(unittest.TestCase): - def __init__(self, *args, **kwargs): - super(CreateTransmissionWorkspaceAutoTest, self).__init__(*args, **kwargs) + + def test_minimal(self): + trans1 = Load('INTER00013463.nxs', OutputWorkspace="trans1") - trans2 = Load('INTER00013464.nxs', OutputWorkspace="trans2") - self.__trans1 = trans1 - self.__trans2 = trans2 - def setUp(self): - super(CreateTransmissionWorkspaceAutoTest, self).setUp() - standard_alg = make_decorator(self.algorithm_type()) - self.__standard_alg = standard_alg + inst = trans1.getInstrument() - def __del__(self): - pass - #DeleteWorkspace(self.__trans1) - #DeleteWorkspace(self.__trans2) - - - def algorithm_type(self): - return CreateTransmissionWorkspaceAuto - - def test_use_point_detector_start(self): - alg = self.__standard_alg - print self.__trans1 - alg.set_FirstTransmissionRun(self.__trans1) - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.execute() + out_ws = CreateTransmissionWorkspaceAuto(FirstTransmissionRun=trans1, AnalysisMode="PointDetectorAnalysis") + history = out_ws.getHistory() + alg = history.lastAlgorithm() - + ''' + Here we are checking that the applied values (passed to CreateTransmissionWorkspace come from the instrument parameters. + ''' + self.assertEqual(inst.getNumberParameter("LambdaMin")[0], alg.getProperty("WavelengthMin").value) + self.assertEqual(inst.getNumberParameter("LambdaMax")[0], alg.getProperty("WavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMin")[0], alg.getProperty("MonitorBackgroundWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMax")[0], alg.getProperty("MonitorBackgroundWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMin")[0], alg.getProperty("MonitorIntegrationWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMax")[0], alg.getProperty("MonitorIntegrationWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("I0MonitorIndex")[0], alg.getProperty("I0MonitorIndex").value) + self.assertEqual(inst.getNumberParameter("PointDetectorStart")[0], alg.getProperty("WorkspaceIndexList").value[0]) + self.assertEqual(inst.getNumberParameter("PointDetectorStop")[0], alg.getProperty("WorkspaceIndexList").value[1]) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index ecbb1226f485..dd3117ad92b3 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -9,7 +9,6 @@ class CreateTransmissionWorkspaceTest(unittest.TestCase): - @abstractmethod def algorithm_type(self): return CreateTransmissionWorkspace From 39b62a0bc9ed7573e75aeb8783f09e6086b10ffb Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 18 Dec 2013 09:57:15 +0000 Subject: [PATCH 239/403] refs #8616. Base python test class. --- .../CreateTransmissionWorkspaceBaseTest.py | 201 ++++++++++++++++++ .../CreateTransmissionWorkspaceTest.py | 199 +---------------- 2 files changed, 210 insertions(+), 190 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceBaseTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceBaseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceBaseTest.py new file mode 100644 index 000000000000..7224498b5cb6 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceBaseTest.py @@ -0,0 +1,201 @@ +import unittest +import mantid.api +import abc +from mantid.simpleapi import CreateWorkspace, DeleteWorkspace, Load +from testhelpers.algorithm_decorator import make_decorator + +import inspect +import re + +class CreateTransmissionWorkspaceBaseTest(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def algorithm_type(self): + raise RuntimeError("Not implemented") + + def setUp(self): + tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + self.__tof = tof + self.__not_tof = not_tof + + def tearDown(self): + DeleteWorkspace(self.__tof) + DeleteWorkspace(self.__not_tof) + + def construct_standard_algorithm(self): + alg = make_decorator(self.algorithm_type()) + alg.set_FirstTransmissionRun(self.__tof) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(1.0) + alg.set_I0MonitorIndex(0) + alg.set_WorkspaceIndexList([0, 1]) + alg.set_MonitorBackgroundWavelengthMin(0.0) + alg.set_MonitorBackgroundWavelengthMax(1.0) + alg.set_MonitorIntegrationWavelengthMin(0.0) + alg.set_MonitorIntegrationWavelengthMax(1.0) + return alg + + def test_input_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_second_transmission_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_params_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_start_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_provide_end_transmission_run_without_end_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_must_provide_wavelengths(self): + self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + + def test_wavelength_min_greater_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WavelengthMin(1.0) + alg.set_WavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorBackgroundWavelengthMin(1.0) + alg.set_MonitorBackgroundWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorIntegrationWavelengthMin(1.0) + alg.set_MonitorIntegrationWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_index_positive(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_throw_if_not_pairs(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([0]) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_values_not_positive_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 + self.assertRaises(Exception, alg.execute) + + def test_spectrum_map_mismatch_throws(self): + alg = self.construct_standard_algorithm() + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap(1) + alg.set_EndOverlap(2) + self.assertRaises(Exception, alg.execute) + + DeleteWorkspace(trans_run1) + + def test_execute_one_tranmission(self): + alg = make_decorator(self.algorithm_type()) + + trans_run1 = Load('INTER00013463.nxs') + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_I0MonitorIndex(0) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(17.9) + alg.set_WavelengthStep(0.5) + alg.set_MonitorBackgroundWavelengthMin(15.0) + alg.set_MonitorBackgroundWavelengthMax(17.0) + alg.set_MonitorIntegrationWavelengthMin(4.0) + alg.set_MonitorIntegrationWavelengthMax(10.0) + + transmission_ws = alg.execute() + + self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) + + # Because we have one transmission workspaces, binning should come from the WavelengthStep. + x = transmission_ws.readX(0) + actual_binning = x[1] - x[0] + step = alg.get_WavelengthStep() + self.assertAlmostEqual( actual_binning, step, 6) + + DeleteWorkspace(trans_run1) + DeleteWorkspace(transmission_ws) + + def test_execute_two_tranmissions(self): + alg = make_decorator(self.algorithm_type()) + + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = Load('INTER00013464.nxs') + + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + alg.set_I0MonitorIndex(0) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(17.9) + alg.set_WavelengthStep(0.5) + alg.set_MonitorBackgroundWavelengthMin(15.0) + alg.set_MonitorBackgroundWavelengthMax(17.0) + alg.set_MonitorIntegrationWavelengthMin(4.0) + alg.set_MonitorIntegrationWavelengthMax(10.0) + alg.set_Params([1.5, 0.02, 17]) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) + + transmission_ws = alg.execute() + + self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) + + # Because we have two transmission workspaces, binning should come from the Params for stitching. + x = transmission_ws.readX(0) + actual_binning = x[1] - x[0] + params = alg.get_Params() + self.assertAlmostEqual( actual_binning, params[1], 6) + self.assertAlmostEqual( 1.5, params[0], 6) + self.assertAlmostEqual( 17, params[2], 6) + + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + DeleteWorkspace(transmission_ws) + \ No newline at end of file diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py index dd3117ad92b3..1369a7bf630d 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceTest.py @@ -1,202 +1,21 @@ import unittest -import mantid.api -from abc import abstractmethod -from mantid.simpleapi import CreateTransmissionWorkspace, CreateWorkspace, DeleteWorkspace, Load -from testhelpers.algorithm_decorator import make_decorator +from mantid.simpleapi import CreateTransmissionWorkspace +from CreateTransmissionWorkspaceBaseTest import CreateTransmissionWorkspaceBaseTest -import inspect -import re - -class CreateTransmissionWorkspaceTest(unittest.TestCase): - - def algorithm_type(self): - return CreateTransmissionWorkspace +class CreateTransmissionWorkspaceTest(unittest.TestCase, CreateTransmissionWorkspaceBaseTest): def setUp(self): - tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - self.__tof = tof - self.__not_tof = not_tof + CreateTransmissionWorkspaceBaseTest.setUp(self) def tearDown(self): - DeleteWorkspace(self.__tof) - DeleteWorkspace(self.__not_tof) + CreateTransmissionWorkspaceBaseTest.setUp(self) - def construct_standard_algorithm(self): - alg = make_decorator(self.algorithm_type()) - alg.set_FirstTransmissionRun(self.__tof) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(1.0) - alg.set_I0MonitorIndex(0) - alg.set_WorkspaceIndexList([0, 1]) - alg.set_MonitorBackgroundWavelengthMin(0.0) - alg.set_MonitorBackgroundWavelengthMax(1.0) - alg.set_MonitorIntegrationWavelengthMin(0.0) - alg.set_MonitorIntegrationWavelengthMax(1.0) - return alg + def __init__(self, *args, **kwargs): + super(CreateTransmissionWorkspaceTest,self).__init__(*args, **kwargs) - def test_input_workspace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__not_tof) - self.assertRaises(Exception, alg.execute) - - def test_second_transmission_workspace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__not_tof) - self.assertRaises(Exception, alg.execute) - - def test_provide_second_transmission_run_without_params_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(Exception, alg.execute) - - def test_provide_second_transmission_run_without_start_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_provide_end_transmission_run_without_end_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.6 ) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, self.algorithm_type(), FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) - - def test_wavelength_min_greater_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WavelengthMin(1.0) - alg.set_WavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorBackgroundWavelengthMin(1.0) - alg.set_MonitorBackgroundWavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorIntegrationWavelengthMin(1.0) - alg.set_MonitorIntegrationWavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_index_positive(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(Exception, alg.execute) - - def test_workspace_index_list_throw_if_not_pairs(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([0]) - self.assertRaises(Exception, alg.execute) - - def test_workspace_index_list_values_not_positive_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. - self.assertRaises(Exception, alg.execute) + def algorithm_type(self): + return CreateTransmissionWorkspace - def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 - self.assertRaises(Exception, alg.execute) - - def test_spectrum_map_mismatch_throws(self): - alg = self.construct_standard_algorithm() - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = self.__tof - - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap(1) - alg.set_EndOverlap(2) - self.assertRaises(Exception, alg.execute) - - DeleteWorkspace(trans_run1) - - def test_execute_one_tranmission(self): - alg = make_decorator(self.algorithm_type()) - - trans_run1 = Load('INTER00013463.nxs') - - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_I0MonitorIndex(0) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(17.9) - alg.set_WavelengthStep(0.5) - alg.set_MonitorBackgroundWavelengthMin(15.0) - alg.set_MonitorBackgroundWavelengthMax(17.0) - alg.set_MonitorIntegrationWavelengthMin(4.0) - alg.set_MonitorIntegrationWavelengthMax(10.0) - - transmission_ws = alg.execute() - - self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) - - # Because we have one transmission workspaces, binning should come from the WavelengthStep. - x = transmission_ws.readX(0) - actual_binning = x[1] - x[0] - step = alg.get_WavelengthStep() - self.assertAlmostEqual( actual_binning, step, 6) - - DeleteWorkspace(trans_run1) - DeleteWorkspace(transmission_ws) - - def test_execute_two_tranmissions(self): - alg = make_decorator(self.algorithm_type()) - - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = Load('INTER00013464.nxs') - - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - alg.set_I0MonitorIndex(0) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(17.9) - alg.set_WavelengthStep(0.5) - alg.set_MonitorBackgroundWavelengthMin(15.0) - alg.set_MonitorBackgroundWavelengthMax(17.0) - alg.set_MonitorIntegrationWavelengthMin(4.0) - alg.set_MonitorIntegrationWavelengthMax(10.0) - alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlap( 10.0 ) - alg.set_EndOverlap( 12.0 ) - - transmission_ws = alg.execute() - - self.assertTrue(isinstance(transmission_ws, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", transmission_ws.getAxis(0).getUnit().unitID()) - - # Because we have two transmission workspaces, binning should come from the Params for stitching. - x = transmission_ws.readX(0) - actual_binning = x[1] - x[0] - params = alg.get_Params() - self.assertAlmostEqual( actual_binning, params[1], 6) - self.assertAlmostEqual( 1.5, params[0], 6) - self.assertAlmostEqual( 17, params[2], 6) - - DeleteWorkspace(trans_run1) - DeleteWorkspace(trans_run2) - DeleteWorkspace(transmission_ws) - if __name__ == '__main__': unittest.main() \ No newline at end of file From ac79606e83232e53f7b8f50b278df163e8c11753 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 18 Dec 2013 10:04:55 +0000 Subject: [PATCH 240/403] refs #8616. Use test base class in auto algorithm. This firstly ensures that the layout of the CreateTransmissionWorkspaceAuto algorithm is the same as CreateTransmissionWorkspace algorithm, and also that it's behaviour is the same if all parameters are passed in. --- .../CreateTransmissionWorkspaceAutoTest.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py index a37c00e783b2..71b0de1e2b57 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CreateTransmissionWorkspaceAutoTest.py @@ -1,10 +1,22 @@ import unittest -import mantid.api -#from CreateTransmissionWorkspaceTest import CreateTransmissionWorkspaceTest +from CreateTransmissionWorkspaceTest import CreateTransmissionWorkspaceTest from mantid.simpleapi import * -class CreateTransmissionWorkspaceAutoTest(unittest.TestCase): +from CreateTransmissionWorkspaceBaseTest import CreateTransmissionWorkspaceBaseTest + +class CreateTransmissionWorkspaceAutoTest(unittest.TestCase, CreateTransmissionWorkspaceBaseTest): + + def algorithm_type(self): + return CreateTransmissionWorkspaceAuto + + def setUp(self): + CreateTransmissionWorkspaceBaseTest.setUp(self) + + def tearDown(self): + CreateTransmissionWorkspaceBaseTest.setUp(self) + def __init__(self, *args, **kwargs): + super(CreateTransmissionWorkspaceAutoTest,self).__init__(*args, **kwargs) def test_minimal(self): From 01c5a185776c448ce71f92f9e35d9d44c153512a Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 18 Dec 2013 13:54:40 +0000 Subject: [PATCH 241/403] refs #8617. New ReflectometryReductionOneAuto algorithm. --- .../ReflectometryReductionOneAuto.py | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py new file mode 100644 index 000000000000..87727cc413aa --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py @@ -0,0 +1,165 @@ +"""*WIKI* + +Facade over [[ReflectometryReductionOne]]. Pulls numeric parameters out of the instrument parameters where possible. You can override any of these automatically +applied defaults by providing your own value for the input. + +See [[ReflectometryReductionOne]] for more information on the wrapped algorithm. + +*WIKI*""" + + +import sys +from mantid.simpleapi import ReflectometryReductionOne +from mantid.api import * +from mantid.kernel import * + +class ReflectometryReductionOneAuto(PythonAlgorithm): + + def category(self): + return "Reflectometry\\ISIS" + + def name(self): + return "ReflectometryReductionOneAuto" + + def PyInit(self): + + input_validator = WorkspaceUnitValidator("TOF") + self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, optional=PropertyMode.Optional), "Input run in TOF") + + analysis_modes = ["PointDetectorAnalysis", "MultiDetectorAnalysis"] + analysis_mode_validator = StringListValidator(analysis_modes) + + self.declareProperty(IntArrayProperty(name="RegionOfInterest", direction=Direction.Input), doc="Indices of the spectra a pair (lower, upper) that mark the ranges that correspond to the region of interest (reflected beam) in multi-detector mode.") + self.declareProperty(IntArrayProperty(name="RegionOfDirectBeam", direction=Direction.Input), doc="Indices of the spectra a pair (lower, upper) that mark the ranges that correspond to the direct beam in multi-detector mode.") + + self.declareProperty(name="AnalysisMode", defaultValue=analysis_modes[0], validator=analysis_mode_validator, direction = Direction.Input, doc="Analysis Mode to Choose") + + self.declareProperty(MatrixWorkspaceProperty("FirstTransmissionRun", "", Direction.Input, optional=PropertyMode.Optional), "First transmission run workspace in TOF or Wavelength") + self.declareProperty(MatrixWorkspaceProperty("SecondTransmissionRun", "", optional=PropertyMode.Optional, validator=input_validator, direction=Direction.Input), "Second transmission run workspace in TOF") + self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output workspace in wavelength q") + self.declareProperty(MatrixWorkspaceProperty("OutputWorkspaceWavelength", "", Direction.Output), "Output workspace in wavelength") + + self.declareProperty(FloatArrayProperty(name="Params", values=[sys.maxint]), doc="Rebinning Parameters. See Rebin for format.") + self.declareProperty(name="StartOverlap", defaultValue=sys.float_info.max, doc="Overlap in Q.") + self.declareProperty(name="EndOverlap", defaultValue=sys.float_info.max, doc="End overlap in Q.") + index_bounds = IntBoundedValidator() + index_bounds.setLower(0) + + self.declareProperty(name="I0MonitorIndex", defaultValue=sys.maxint, validator=index_bounds, doc="I0 monitor index" ) + self.declareProperty(IntArrayProperty(name="WorkspaceIndexList", values=[sys.maxint]), doc="Workspace index list") + self.declareProperty(name="WavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength Min in angstroms") + self.declareProperty(name="WavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength Max in angstroms") + self.declareProperty(name="WavelengthStep", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Wavelength step in angstroms") + self.declareProperty(name="MonitorBackgroundWavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor wavelength background min in angstroms") + self.declareProperty(name="MonitorBackgroundWavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor wavelength background max in angstroms") + self.declareProperty(name="MonitorIntegrationWavelengthMin", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral min in angstroms") + self.declareProperty(name="MonitorIntegrationWavelengthMax", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Monitor integral max in angstroms") + + self.declareProperty(name="DetectorComponentName", direction=Direction.Input, defaultValue="", doc="Name of the detector component i.e. point-detector. If these are not specified, the algorithm will attempt lookup using a standard naming convention.") + self.declareProperty(name="SampleComponentName", direction=Direction.Input, defaultValue="", doc="Name of the sample component i.e. some-surface-holder. If these are not specified, the algorithm will attempt lookup using a standard naming convention." ) + + self.declareProperty(name="ThetaIn", direction=Direction.Input, defaultValue=sys.float_info.max, doc="Final theta in degrees") + self.declareProperty(name="ThetaOut", direction=Direction.Output, defaultValue=sys.float_info.max, doc="Calculated final theta in degrees.") + + self.declareProperty(name="CorrectDetectorPositions", defaultValue=True, direction=Direction.Input, doc="Correct detector positions using ThetaIn (if given)") + + + def value_or_none(self, prop_name): + property = self.getProperty(prop_name) + if property.isDefault: + return None # TODO: check this + else: + return property.value + + + def value_to_apply(self, prop_name, instrument, idf_name=""): + property = self.getProperty(prop_name) + if property.isDefault: + return instrument.getNumberParameter(idf_name)[0] + else: + return property.value + + def PyExec(self): + + in_ws = self.getProperty("InputWorkspace").value + + first_ws = self.getProperty("FirstTransmissionRun").value + instrument = first_ws.getInstrument() + + ''' + Get all the inputs. + ''' + output_workspace_name = self.getPropertyValue("OutputWorkspace") + + output_workspace_lam_name = self.getPropertyValue("OutputWorkspaceWavelength") + + analysis_mode = self.getPropertyValue("AnalysisMode") + + first_ws = self.value_or_none("FirstTransmissionRun") + + second_ws = self.value_or_none("SecondTransmissionRun") + + start_overlap = self.value_or_none("StartOverlap") + + end_overlap = self.value_or_none("EndOverlap") + + params = self.value_or_none("Params") + + i0_monitor_index = int(self.value_to_apply("I0MonitorIndex", instrument, "I0MonitorIndex")) + + workspace_index_list = list() + if self.getProperty("WorkspaceIndexList").isDefault: + if analysis_mode == "PointDetectorAnalysis": + workspace_index_list.append( int(instrument.getNumberParameter("PointDetectorStart")[0]) ) + workspace_index_list.append( int(instrument.getNumberParameter("PointDetectorStop")[0]) ) + else: + workspace_index_list.append( int(instrument.getNumberParameter("MultiDetectorStart")[0]) ) + workspace_index_list.append( first_ws.getNumberHistograms() - 1) + else: + workspace_index_list = self.getProperty("WorkspaceIndexList").value + + wavelength_min = self.value_to_apply("WavelengthMin", instrument, "LambdaMin") + + wavelength_max = self.value_to_apply("WavelengthMax", instrument, "LambdaMax") + + wavelength_step = self.value_or_none("WavelengthStep") + + wavelength_back_min = self.value_to_apply("MonitorBackgroundWavelengthMin", instrument, "MonitorBackgroundMin") + + wavelength_back_max = self.value_to_apply("MonitorBackgroundWavelengthMax", instrument, "MonitorBackgroundMax") + + wavelength_integration_min = self.value_to_apply("MonitorIntegrationWavelengthMin", instrument, "MonitorIntegralMin") + + wavelength_integration_max = self.value_to_apply("MonitorIntegrationWavelengthMax", instrument, "MonitorIntegralMax") + + detector_component_name = self.value_or_none("DetectorComponentName") + + sample_component_name = self.value_or_none("SampleComponentName") + + theta_in = self.value_or_none("ThetaIn") + + correct_positions = self.value_or_none("CorrectDetectorPositions") + + region_of_interest = self.value_or_none("RegionOfInterest") + + region_of_direct_beam = self.value_or_none("RegionOfDirectBeam") + + ''' + Pass the arguments and execute the main algorithm. + ''' + new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne(InputWorkspace=in_ws, FirstTransmissionRun=first_ws, SecondTransmissionRun=second_ws, + OutputWorkspace=output_workspace_name, OutputWorkspaceWavelength=output_workspace_lam_name, + StartOverlap=start_overlap, EndOverlap=end_overlap, Params=params, I0MonitorIndex=i0_monitor_index, + WorkspaceIndexList=workspace_index_list, WavelengthMin=wavelength_min, WavelengthStep=wavelength_step, WavelengthMax=wavelength_max, + MonitorBackgroundWavelengthMin=wavelength_back_min, MonitorBackgroundWavelengthMax=wavelength_back_max, + MonitorIntegrationWavelengthMin=wavelength_integration_min, MonitorIntegrationWavelengthMax=wavelength_integration_max, + RegionOfInterest=region_of_interest, RegionOfDirectBeam=region_of_direct_beam, DetectorComponentName=detector_component_name, + SampleComponentName=sample_component_name) + + self.setProperty("OutputWorkspace", new_IvsQ1) + self.setProperty("OutputWorkspaceWavelength", new_IvsLam1) + self.setProperty("ThetaOut", thetaOut1) + + + +AlgorithmFactory.subscribe(ReflectometryReductionOneAuto) \ No newline at end of file From 1f37f939068cee8240735fa76a356193dbf810e3 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 18 Dec 2013 14:42:28 +0000 Subject: [PATCH 242/403] refs #8617. ReflectometryReductionOneAuto refined and tested. New tests using a base class to avoid duplication. Base class ensures that signature and behaviour of facade algorithm is exactly the same as the base one. In addition, additional tests check that the values supplied to the wrapped algorithm upon execution are what we would expect from the IDF. --- .../ReflectometryReductionOneAuto.py | 35 ++- .../python/plugins/algorithms/CMakeLists.txt | 1 + .../ReflectometryReductionOneAutoTest.py | 45 +++ .../ReflectometryReductionOneBaseTest.py | 290 ++++++++++++++++++ .../ReflectometryReductionOneTest.py | 286 +---------------- 5 files changed, 371 insertions(+), 286 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py index 87727cc413aa..d664009fabd1 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py @@ -82,9 +82,9 @@ def value_to_apply(self, prop_name, instrument, idf_name=""): def PyExec(self): in_ws = self.getProperty("InputWorkspace").value + instrument = in_ws.getInstrument() first_ws = self.getProperty("FirstTransmissionRun").value - instrument = first_ws.getInstrument() ''' Get all the inputs. @@ -147,14 +147,31 @@ def PyExec(self): ''' Pass the arguments and execute the main algorithm. ''' - new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne(InputWorkspace=in_ws, FirstTransmissionRun=first_ws, SecondTransmissionRun=second_ws, - OutputWorkspace=output_workspace_name, OutputWorkspaceWavelength=output_workspace_lam_name, - StartOverlap=start_overlap, EndOverlap=end_overlap, Params=params, I0MonitorIndex=i0_monitor_index, - WorkspaceIndexList=workspace_index_list, WavelengthMin=wavelength_min, WavelengthStep=wavelength_step, WavelengthMax=wavelength_max, - MonitorBackgroundWavelengthMin=wavelength_back_min, MonitorBackgroundWavelengthMax=wavelength_back_max, - MonitorIntegrationWavelengthMin=wavelength_integration_min, MonitorIntegrationWavelengthMax=wavelength_integration_max, - RegionOfInterest=region_of_interest, RegionOfDirectBeam=region_of_direct_beam, DetectorComponentName=detector_component_name, - SampleComponentName=sample_component_name) + new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne( + InputWorkspace=in_ws, + AnalysisMode = analysis_mode, + FirstTransmissionRun=first_ws, + SecondTransmissionRun=second_ws, + OutputWorkspace=output_workspace_name, + OutputWorkspaceWavelength=output_workspace_lam_name, + StartOverlap=start_overlap, + EndOverlap=end_overlap, + Params=params, + I0MonitorIndex=i0_monitor_index, + WorkspaceIndexList=workspace_index_list, + WavelengthMin=wavelength_min, + WavelengthStep=wavelength_step, + WavelengthMax=wavelength_max, + MonitorBackgroundWavelengthMin=wavelength_back_min, + MonitorBackgroundWavelengthMax=wavelength_back_max, + MonitorIntegrationWavelengthMin=wavelength_integration_min, + MonitorIntegrationWavelengthMax=wavelength_integration_max, + RegionOfInterest=region_of_interest, + RegionOfDirectBeam=region_of_direct_beam, + DetectorComponentName=detector_component_name, + SampleComponentName=sample_component_name, + ThetaIn=theta_in, + CorrectPositions=correct_positions) self.setProperty("OutputWorkspace", new_IvsQ1) self.setProperty("OutputWorkspaceWavelength", new_IvsLam1) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index 7bad2236ccb5..b7deb4b641e2 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -19,6 +19,7 @@ set ( TEST_PY_FILES MeanTest.py MergeCalFilesTest.py ReflectometryReductionOneTest.py + ReflectometryReductionOneAutoTest.py RetrieveRunInfoTest.py SANSWideAngleCorrectionTest.py SortXAxisTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py new file mode 100644 index 000000000000..481a99c8acd6 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py @@ -0,0 +1,45 @@ +import unittest +from mantid.simpleapi import ReflectometryReductionOneAuto, Load, DeleteWorkspace +from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest + +class ReflectometryReductionOneAutoTest(unittest.TestCase, ReflectometryReductionOneBaseTest): + + def setUp(self): + ReflectometryReductionOneBaseTest.setUp(self) + + def tearDown(self): + ReflectometryReductionOneBaseTest.setUp(self) + + def algorithm_type(self): + return ReflectometryReductionOneAuto + + def test_minimal_inputs(self): + + in_ws = Load('INTER00013460.nxs', OutputWorkspace="13460") + trans1 = Load('INTER00013463.nxs', OutputWorkspace="trans1") + + inst = trans1.getInstrument() + + out_ws, out_wsl_lam, thetafinal = ReflectometryReductionOneAuto(InputWorkspace=in_ws, AnalysisMode="PointDetectorAnalysis" + ,OutputWorkspace="InQ", OutputWorkspaceWavelength="InLam") + history = out_ws.getHistory() + alg = history.lastAlgorithm() + + ''' + Here we are checking that the applied values (passed to CreateTransmissionWorkspace come from the instrument parameters. + ''' + self.assertEqual(inst.getNumberParameter("LambdaMin")[0], alg.getProperty("WavelengthMin").value) + self.assertEqual(inst.getNumberParameter("LambdaMax")[0], alg.getProperty("WavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMin")[0], alg.getProperty("MonitorBackgroundWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMax")[0], alg.getProperty("MonitorBackgroundWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMin")[0], alg.getProperty("MonitorIntegrationWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMax")[0], alg.getProperty("MonitorIntegrationWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("I0MonitorIndex")[0], alg.getProperty("I0MonitorIndex").value) + self.assertEqual(inst.getNumberParameter("PointDetectorStart")[0], alg.getProperty("WorkspaceIndexList").value[0]) + self.assertEqual(inst.getNumberParameter("PointDetectorStop")[0], alg.getProperty("WorkspaceIndexList").value[1]) + + DeleteWorkspace(in_ws) + DeleteWorkspace(trans1) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py new file mode 100644 index 000000000000..569a28f01483 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py @@ -0,0 +1,290 @@ +import unittest +from mantid.simpleapi import * +from testhelpers.algorithm_decorator import make_decorator +import mantid.api +import math +import abc + +class ReflectometryReductionOneBaseTest(object): + + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def algorithm_type(self): + raise RuntimeError("Not implemented") + + def construct_standard_algorithm(self): + alg = make_decorator(self.algorithm_type()) + alg.set_InputWorkspace(self.__tof) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(1.0) + alg.set_I0MonitorIndex(0) + alg.set_WorkspaceIndexList([0, 1]) + alg.set_MonitorBackgroundWavelengthMin(0.0) + alg.set_MonitorBackgroundWavelengthMax(1.0) + alg.set_MonitorIntegrationWavelengthMin(0.0) + alg.set_MonitorIntegrationWavelengthMax(1.0) + alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) + return alg + + def setUp(self): + tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + self.__tof = tof + self.__not_tof = not_tof + + def tearDown(self): + DeleteWorkspace(self.__tof) + DeleteWorkspace(self.__not_tof) + + + def test_check_input_workpace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_InputWorkspace(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_check_second_transmission_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_proivde_second_transmission_run_without_first_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_params_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_start_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_provide_end_transmission_run_without_end_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_must_provide_wavelengths(self): + self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + + def test_wavelength_min_greater_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WavelengthMin(1.0) + alg.set_WavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorBackgroundWavelengthMin(1.0) + alg.set_MonitorBackgroundWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorIntegrationWavelengthMin(1.0) + alg.set_MonitorIntegrationWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_index_positive(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_throw_if_not_pairs(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([0]) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_values_not_positive_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 + self.assertRaises(Exception, alg.execute) + + def test_region_of_interest_throws_if_i0monitor_index_negative(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(Exception, alg.execute) + + def test_cannot_set_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfInterest([1, 2]) + self.assertRaises(Exception, alg.execute) + + def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([0, -1]); + self.assertRaises(Exception, alg.execute) + + def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([1, 0]); + self.assertRaises(Exception, alg.execute) + + def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 2]) + self.assertRaises(Exception, alg.execute) + + def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0, -1]); + self.assertRaises(Exception, alg.execute) + + def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 0]); + self.assertRaises(Exception, alg.execute) + + def test_bad_detector_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_DetectorComponentName("made-up") + self.assertRaises(Exception, alg.execute) + + def test_bad_sample_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SampleComponentName("made-up") + self.assertRaises(Exception, alg.execute) + + def test_point_detector_run_with_single_transmission_workspace(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertEqual(0.2, theta, "Theta in and out should be the same") + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + + self.assertEqual(2, out_ws_lam.getNumberHistograms()) + DeleteWorkspace(real_run) + + def test_point_detector_run_with_two_transmission_workspaces(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = Load('INTER00013464.nxs') + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + alg.set_Params([1.5, 0.02, 17]) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + + def test_spectrum_map_mismatch_throws(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + self.assertRaises(Exception, alg.execute) + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + + def test_calculate_theta(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) + + DeleteWorkspace(real_run) + + def test_throw_if_no_roi_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0,1]) + alg.set_DetectorComponentName('lineardetector') + self.assertRaises(Exception, alg.execute) + + def test_throw_if_no_db_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([0,1]) + self.assertRaises(Exception, alg.execute) + + def test_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([3, 10]) # Fictional values + alg.set_RegionOfDirectBeam([20, 30]) # Fictional values + alg.set_ThetaIn(0.1) # Fictional values + + out_ws_q, out_ws_lam, theta = alg.execute() + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index 104c18accbf9..da722ac868b3 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -1,286 +1,18 @@ import unittest -from mantid.simpleapi import * -from testhelpers.algorithm_decorator import make_decorator -import mantid.api -import math +from mantid.simpleapi import ReflectometryReductionOne +from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest -class ReflectometryReductionOneTest(unittest.TestCase): - - def construct_standard_algorithm(self): - alg = make_decorator(ReflectometryReductionOne) - alg.set_InputWorkspace(self.__tof) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(1.0) - alg.set_I0MonitorIndex(0) - alg.set_WorkspaceIndexList([0, 1]) - alg.set_MonitorBackgroundWavelengthMin(0.0) - alg.set_MonitorBackgroundWavelengthMax(1.0) - alg.set_MonitorIntegrationWavelengthMin(0.0) - alg.set_MonitorIntegrationWavelengthMax(1.0) - alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) - return alg +class ReflectometryReductionOneTest(unittest.TestCase, ReflectometryReductionOneBaseTest): def setUp(self): - tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - self.__tof = tof - self.__not_tof = not_tof + ReflectometryReductionOneBaseTest.setUp(self) def tearDown(self): - DeleteWorkspace(self.__tof) - DeleteWorkspace(self.__not_tof) - - - def test_check_input_workpace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_InputWorkspace(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_check_second_transmission_workspace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_proivde_second_transmission_run_without_first_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(ValueError, alg.execute) - - def test_provide_second_transmission_run_without_params_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(ValueError, alg.execute) - - def test_provide_second_transmission_run_without_start_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_provide_end_transmission_run_without_end_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.6 ) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) - - def test_wavelength_min_greater_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WavelengthMin(1.0) - alg.set_WavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorBackgroundWavelengthMin(1.0) - alg.set_MonitorBackgroundWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorIntegrationWavelengthMin(1.0) - alg.set_MonitorIntegrationWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_index_positive(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_throw_if_not_pairs(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([0]) - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_values_not_positive_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 - self.assertRaises(ValueError, alg.execute) - - def test_region_of_interest_throws_if_i0monitor_index_negative(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(ValueError, alg.execute) - - def test_cannot_set_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfInterest([1, 2]) - self.assertRaises(ValueError, alg.execute) - - def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([0, -1]); - self.assertRaises(ValueError, alg.execute) - - def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([1, 0]); - self.assertRaises(ValueError, alg.execute) - - def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 2]) - self.assertRaises(ValueError, alg.execute) - - def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0, -1]); - self.assertRaises(ValueError, alg.execute) - - def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 0]); - self.assertRaises(ValueError, alg.execute) - - def test_bad_detector_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_DetectorComponentName("made-up") - self.assertRaises(ValueError, alg.execute) + ReflectometryReductionOneBaseTest.setUp(self) - def test_bad_sample_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SampleComponentName("made-up") - self.assertRaises(ValueError, alg.execute) - - def test_point_detector_run_with_single_transmission_workspace(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertEqual(0.2, theta, "Theta in and out should be the same") - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - - self.assertEqual(2, out_ws_lam.getNumberHistograms()) - DeleteWorkspace(real_run) + def algorithm_type(self): + return ReflectometryReductionOne - def test_point_detector_run_with_two_transmission_workspaces(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = Load('INTER00013464.nxs') - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlap( 10.0 ) - alg.set_EndOverlap( 12.0 ) - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - DeleteWorkspace(trans_run2) - - def test_spectrum_map_mismatch_throws(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = self.__tof - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - self.assertRaises(ValueError, alg.execute) - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - - def test_calculate_theta(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) - - DeleteWorkspace(real_run) - - def test_throw_if_no_roi_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0,1]) - alg.set_DetectorComponentName('lineardetector') - self.assertRaises(ValueError, alg.execute) - - def test_throw_if_no_db_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([0,1]) - self.assertRaises(ValueError, alg.execute) - - def test_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([3, 10]) # Fictional values - alg.set_RegionOfDirectBeam([20, 30]) # Fictional values - alg.set_ThetaIn(0.1) # Fictional values - - out_ws_q, out_ws_lam, theta = alg.execute() - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - - + if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file From 92a4205528842ed57a7e03af37c86edd58d451c3 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Wed, 18 Dec 2013 14:58:43 +0000 Subject: [PATCH 243/403] Revert "refs #8617. ReflectometryReductionOneAuto refined and tested." This reverts commit 1f37f939068cee8240735fa76a356193dbf810e3. --- .../ReflectometryReductionOneAuto.py | 35 +-- .../python/plugins/algorithms/CMakeLists.txt | 1 - .../ReflectometryReductionOneAutoTest.py | 45 --- .../ReflectometryReductionOneBaseTest.py | 290 ------------------ .../ReflectometryReductionOneTest.py | 286 ++++++++++++++++- 5 files changed, 286 insertions(+), 371 deletions(-) delete mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py delete mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py index d664009fabd1..87727cc413aa 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py @@ -82,9 +82,9 @@ def value_to_apply(self, prop_name, instrument, idf_name=""): def PyExec(self): in_ws = self.getProperty("InputWorkspace").value - instrument = in_ws.getInstrument() first_ws = self.getProperty("FirstTransmissionRun").value + instrument = first_ws.getInstrument() ''' Get all the inputs. @@ -147,31 +147,14 @@ def PyExec(self): ''' Pass the arguments and execute the main algorithm. ''' - new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne( - InputWorkspace=in_ws, - AnalysisMode = analysis_mode, - FirstTransmissionRun=first_ws, - SecondTransmissionRun=second_ws, - OutputWorkspace=output_workspace_name, - OutputWorkspaceWavelength=output_workspace_lam_name, - StartOverlap=start_overlap, - EndOverlap=end_overlap, - Params=params, - I0MonitorIndex=i0_monitor_index, - WorkspaceIndexList=workspace_index_list, - WavelengthMin=wavelength_min, - WavelengthStep=wavelength_step, - WavelengthMax=wavelength_max, - MonitorBackgroundWavelengthMin=wavelength_back_min, - MonitorBackgroundWavelengthMax=wavelength_back_max, - MonitorIntegrationWavelengthMin=wavelength_integration_min, - MonitorIntegrationWavelengthMax=wavelength_integration_max, - RegionOfInterest=region_of_interest, - RegionOfDirectBeam=region_of_direct_beam, - DetectorComponentName=detector_component_name, - SampleComponentName=sample_component_name, - ThetaIn=theta_in, - CorrectPositions=correct_positions) + new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne(InputWorkspace=in_ws, FirstTransmissionRun=first_ws, SecondTransmissionRun=second_ws, + OutputWorkspace=output_workspace_name, OutputWorkspaceWavelength=output_workspace_lam_name, + StartOverlap=start_overlap, EndOverlap=end_overlap, Params=params, I0MonitorIndex=i0_monitor_index, + WorkspaceIndexList=workspace_index_list, WavelengthMin=wavelength_min, WavelengthStep=wavelength_step, WavelengthMax=wavelength_max, + MonitorBackgroundWavelengthMin=wavelength_back_min, MonitorBackgroundWavelengthMax=wavelength_back_max, + MonitorIntegrationWavelengthMin=wavelength_integration_min, MonitorIntegrationWavelengthMax=wavelength_integration_max, + RegionOfInterest=region_of_interest, RegionOfDirectBeam=region_of_direct_beam, DetectorComponentName=detector_component_name, + SampleComponentName=sample_component_name) self.setProperty("OutputWorkspace", new_IvsQ1) self.setProperty("OutputWorkspaceWavelength", new_IvsLam1) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index b7deb4b641e2..7bad2236ccb5 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -19,7 +19,6 @@ set ( TEST_PY_FILES MeanTest.py MergeCalFilesTest.py ReflectometryReductionOneTest.py - ReflectometryReductionOneAutoTest.py RetrieveRunInfoTest.py SANSWideAngleCorrectionTest.py SortXAxisTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py deleted file mode 100644 index 481a99c8acd6..000000000000 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py +++ /dev/null @@ -1,45 +0,0 @@ -import unittest -from mantid.simpleapi import ReflectometryReductionOneAuto, Load, DeleteWorkspace -from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest - -class ReflectometryReductionOneAutoTest(unittest.TestCase, ReflectometryReductionOneBaseTest): - - def setUp(self): - ReflectometryReductionOneBaseTest.setUp(self) - - def tearDown(self): - ReflectometryReductionOneBaseTest.setUp(self) - - def algorithm_type(self): - return ReflectometryReductionOneAuto - - def test_minimal_inputs(self): - - in_ws = Load('INTER00013460.nxs', OutputWorkspace="13460") - trans1 = Load('INTER00013463.nxs', OutputWorkspace="trans1") - - inst = trans1.getInstrument() - - out_ws, out_wsl_lam, thetafinal = ReflectometryReductionOneAuto(InputWorkspace=in_ws, AnalysisMode="PointDetectorAnalysis" - ,OutputWorkspace="InQ", OutputWorkspaceWavelength="InLam") - history = out_ws.getHistory() - alg = history.lastAlgorithm() - - ''' - Here we are checking that the applied values (passed to CreateTransmissionWorkspace come from the instrument parameters. - ''' - self.assertEqual(inst.getNumberParameter("LambdaMin")[0], alg.getProperty("WavelengthMin").value) - self.assertEqual(inst.getNumberParameter("LambdaMax")[0], alg.getProperty("WavelengthMax").value) - self.assertEqual(inst.getNumberParameter("MonitorBackgroundMin")[0], alg.getProperty("MonitorBackgroundWavelengthMin").value) - self.assertEqual(inst.getNumberParameter("MonitorBackgroundMax")[0], alg.getProperty("MonitorBackgroundWavelengthMax").value) - self.assertEqual(inst.getNumberParameter("MonitorIntegralMin")[0], alg.getProperty("MonitorIntegrationWavelengthMin").value) - self.assertEqual(inst.getNumberParameter("MonitorIntegralMax")[0], alg.getProperty("MonitorIntegrationWavelengthMax").value) - self.assertEqual(inst.getNumberParameter("I0MonitorIndex")[0], alg.getProperty("I0MonitorIndex").value) - self.assertEqual(inst.getNumberParameter("PointDetectorStart")[0], alg.getProperty("WorkspaceIndexList").value[0]) - self.assertEqual(inst.getNumberParameter("PointDetectorStop")[0], alg.getProperty("WorkspaceIndexList").value[1]) - - DeleteWorkspace(in_ws) - DeleteWorkspace(trans1) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py deleted file mode 100644 index 569a28f01483..000000000000 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py +++ /dev/null @@ -1,290 +0,0 @@ -import unittest -from mantid.simpleapi import * -from testhelpers.algorithm_decorator import make_decorator -import mantid.api -import math -import abc - -class ReflectometryReductionOneBaseTest(object): - - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def algorithm_type(self): - raise RuntimeError("Not implemented") - - def construct_standard_algorithm(self): - alg = make_decorator(self.algorithm_type()) - alg.set_InputWorkspace(self.__tof) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(1.0) - alg.set_I0MonitorIndex(0) - alg.set_WorkspaceIndexList([0, 1]) - alg.set_MonitorBackgroundWavelengthMin(0.0) - alg.set_MonitorBackgroundWavelengthMax(1.0) - alg.set_MonitorIntegrationWavelengthMin(0.0) - alg.set_MonitorIntegrationWavelengthMax(1.0) - alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) - return alg - - def setUp(self): - tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - self.__tof = tof - self.__not_tof = not_tof - - def tearDown(self): - DeleteWorkspace(self.__tof) - DeleteWorkspace(self.__not_tof) - - - def test_check_input_workpace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_InputWorkspace(self.__not_tof) - self.assertRaises(Exception, alg.execute) - - def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__not_tof) - self.assertRaises(Exception, alg.execute) - - def test_check_second_transmission_workspace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__not_tof) - self.assertRaises(Exception, alg.execute) - - def test_proivde_second_transmission_run_without_first_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(Exception, alg.execute) - - def test_provide_second_transmission_run_without_params_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(Exception, alg.execute) - - def test_provide_second_transmission_run_without_start_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_provide_end_transmission_run_without_end_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.6 ) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(Exception, alg.execute) - - def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) - - def test_wavelength_min_greater_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WavelengthMin(1.0) - alg.set_WavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorBackgroundWavelengthMin(1.0) - alg.set_MonitorBackgroundWavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorIntegrationWavelengthMin(1.0) - alg.set_MonitorIntegrationWavelengthMax(0.0) - self.assertRaises(Exception, alg.execute) - - def test_monitor_index_positive(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(Exception, alg.execute) - - def test_workspace_index_list_throw_if_not_pairs(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([0]) - self.assertRaises(Exception, alg.execute) - - def test_workspace_index_list_values_not_positive_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. - self.assertRaises(Exception, alg.execute) - - def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 - self.assertRaises(Exception, alg.execute) - - def test_region_of_interest_throws_if_i0monitor_index_negative(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(Exception, alg.execute) - - def test_cannot_set_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfInterest([1, 2]) - self.assertRaises(Exception, alg.execute) - - def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([0, -1]); - self.assertRaises(Exception, alg.execute) - - def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([1, 0]); - self.assertRaises(Exception, alg.execute) - - def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 2]) - self.assertRaises(Exception, alg.execute) - - def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0, -1]); - self.assertRaises(Exception, alg.execute) - - def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 0]); - self.assertRaises(Exception, alg.execute) - - def test_bad_detector_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_DetectorComponentName("made-up") - self.assertRaises(Exception, alg.execute) - - def test_bad_sample_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SampleComponentName("made-up") - self.assertRaises(Exception, alg.execute) - - def test_point_detector_run_with_single_transmission_workspace(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertEqual(0.2, theta, "Theta in and out should be the same") - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - - self.assertEqual(2, out_ws_lam.getNumberHistograms()) - DeleteWorkspace(real_run) - - def test_point_detector_run_with_two_transmission_workspaces(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = Load('INTER00013464.nxs') - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlap( 10.0 ) - alg.set_EndOverlap( 12.0 ) - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - DeleteWorkspace(trans_run2) - - def test_spectrum_map_mismatch_throws(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = self.__tof - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - self.assertRaises(Exception, alg.execute) - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - - def test_calculate_theta(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) - - DeleteWorkspace(real_run) - - def test_throw_if_no_roi_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0,1]) - alg.set_DetectorComponentName('lineardetector') - self.assertRaises(Exception, alg.execute) - - def test_throw_if_no_db_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([0,1]) - self.assertRaises(Exception, alg.execute) - - def test_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([3, 10]) # Fictional values - alg.set_RegionOfDirectBeam([20, 30]) # Fictional values - alg.set_ThetaIn(0.1) # Fictional values - - out_ws_q, out_ws_lam, theta = alg.execute() - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index da722ac868b3..104c18accbf9 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -1,18 +1,286 @@ import unittest -from mantid.simpleapi import ReflectometryReductionOne -from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest +from mantid.simpleapi import * +from testhelpers.algorithm_decorator import make_decorator +import mantid.api +import math -class ReflectometryReductionOneTest(unittest.TestCase, ReflectometryReductionOneBaseTest): +class ReflectometryReductionOneTest(unittest.TestCase): + + def construct_standard_algorithm(self): + alg = make_decorator(ReflectometryReductionOne) + alg.set_InputWorkspace(self.__tof) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(1.0) + alg.set_I0MonitorIndex(0) + alg.set_WorkspaceIndexList([0, 1]) + alg.set_MonitorBackgroundWavelengthMin(0.0) + alg.set_MonitorBackgroundWavelengthMax(1.0) + alg.set_MonitorIntegrationWavelengthMin(0.0) + alg.set_MonitorIntegrationWavelengthMax(1.0) + alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) + return alg def setUp(self): - ReflectometryReductionOneBaseTest.setUp(self) + tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + self.__tof = tof + self.__not_tof = not_tof def tearDown(self): - ReflectometryReductionOneBaseTest.setUp(self) + DeleteWorkspace(self.__tof) + DeleteWorkspace(self.__not_tof) + + + def test_check_input_workpace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_InputWorkspace(self.__not_tof) + self.assertRaises(ValueError, alg.execute) + + def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__not_tof) + self.assertRaises(ValueError, alg.execute) + + def test_check_second_transmission_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__not_tof) + self.assertRaises(ValueError, alg.execute) + + def test_proivde_second_transmission_run_without_first_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(ValueError, alg.execute) + + def test_provide_second_transmission_run_without_params_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(ValueError, alg.execute) + + def test_provide_second_transmission_run_without_start_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_provide_end_transmission_run_without_end_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(ValueError, alg.execute) + + def test_must_provide_wavelengths(self): + self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + + def test_wavelength_min_greater_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WavelengthMin(1.0) + alg.set_WavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorBackgroundWavelengthMin(1.0) + alg.set_MonitorBackgroundWavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorIntegrationWavelengthMin(1.0) + alg.set_MonitorIntegrationWavelengthMax(0.0) + self.assertRaises(ValueError, alg.execute) + + def test_monitor_index_positive(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_throw_if_not_pairs(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([0]) + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_values_not_positive_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. + self.assertRaises(ValueError, alg.execute) + + def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 + self.assertRaises(ValueError, alg.execute) + + def test_region_of_interest_throws_if_i0monitor_index_negative(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(ValueError, alg.execute) + + def test_cannot_set_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfInterest([1, 2]) + self.assertRaises(ValueError, alg.execute) + + def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([0, -1]); + self.assertRaises(ValueError, alg.execute) + + def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([1, 0]); + self.assertRaises(ValueError, alg.execute) + + def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 2]) + self.assertRaises(ValueError, alg.execute) + + def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0, -1]); + self.assertRaises(ValueError, alg.execute) + + def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 0]); + self.assertRaises(ValueError, alg.execute) + + def test_bad_detector_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_DetectorComponentName("made-up") + self.assertRaises(ValueError, alg.execute) - def algorithm_type(self): - return ReflectometryReductionOne + def test_bad_sample_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SampleComponentName("made-up") + self.assertRaises(ValueError, alg.execute) + + def test_point_detector_run_with_single_transmission_workspace(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertEqual(0.2, theta, "Theta in and out should be the same") + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + + self.assertEqual(2, out_ws_lam.getNumberHistograms()) + DeleteWorkspace(real_run) - + def test_point_detector_run_with_two_transmission_workspaces(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = Load('INTER00013464.nxs') + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + alg.set_Params([1.5, 0.02, 17]) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + + def test_spectrum_map_mismatch_throws(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + self.assertRaises(ValueError, alg.execute) + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + + def test_calculate_theta(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) + + DeleteWorkspace(real_run) + + def test_throw_if_no_roi_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0,1]) + alg.set_DetectorComponentName('lineardetector') + self.assertRaises(ValueError, alg.execute) + + def test_throw_if_no_db_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([0,1]) + self.assertRaises(ValueError, alg.execute) + + def test_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([3, 10]) # Fictional values + alg.set_RegionOfDirectBeam([20, 30]) # Fictional values + alg.set_ThetaIn(0.1) # Fictional values + + out_ws_q, out_ws_lam, theta = alg.execute() + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + + if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() From f0961043d96dbce7116e250919c4d64af5301584 Mon Sep 17 00:00:00 2001 From: Vickie Lynch Date: Wed, 18 Dec 2013 10:23:57 -0500 Subject: [PATCH 244/403] Refs #8280 Need factor of 2 for radius of both peaks --- Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp index 3541f44b1f5e..586bb7287ffd 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD2.cpp @@ -594,7 +594,7 @@ namespace MDAlgorithms } } checkOverlap (i, peakWS, CoordinatesToUse, - std::max(PeakRadiusVector[i],BackgroundOuterRadiusVector[i])); + 2.0 * std::max(PeakRadiusVector[i],BackgroundOuterRadiusVector[i])); // Save it back in the peak object. if (signal != 0. || replaceIntensity) { From fb32f27d62a0bc8729b48b726ee3d0ac04cab73f Mon Sep 17 00:00:00 2001 From: Peter Parker Date: Wed, 18 Dec 2013 15:44:31 +0000 Subject: [PATCH 245/403] Refs #8469 - Sort items in Interfaces menu. Sorry about the helper-function clutter. This would have been a two-line change with lambdas. --- Code/Mantid/MantidPlot/src/ApplicationWindow.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 43d64450abcd..506b3b8be9e6 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -9297,6 +9297,17 @@ void ApplicationWindow::windowsMenuAboutToShow() reloadCustomActions(); } +namespace // anonymous +{ + /** + * Helper function used with Qt's qSort to make sure interfaces are in alphabetical order. + */ + bool interfaceNameComparator(const QPair & lhs, const QPair & rhs) + { + return lhs.first.toLower() < rhs.first.toLower(); + } +} // anonymous namespace + void ApplicationWindow::interfaceMenuAboutToShow() { interfaceMenu->clear(); @@ -9321,6 +9332,10 @@ void ApplicationWindow::interfaceMenuAboutToShow() categoryMenus[category] = categoryMenu; } + // Show the interfaces in alphabetical order in their respective submenus. + qSort(m_interfaceNameDataPairs.begin(), m_interfaceNameDataPairs.end(), + interfaceNameComparator); + // Turn the name/data pairs into QActions with which we populate the menus. foreach(const auto interfaceNameDataPair, m_interfaceNameDataPairs) { From 4c089bf0fa8e5995b6d590485d5c29488791d35e Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 10:56:47 -0500 Subject: [PATCH 246/403] Re #8634. Add caching of names in FunctionFactory::getFunctionNames. This method was fairly expensive because it had to create an instance of every registered function every time to find out if it's the requested type. This method is called to create validators in various algorithm init methods, which can be called a lot it - for example - the algorithm is used as a sub-algorithm in a loop within another algorithm. It's now cached in a map that's a member of FunctionFactoryImpl. The caching had to be made thread-safe with a mutex. On the plus side this allows the resulting vector to be returned by reference-to-const. --- .../API/inc/MantidAPI/FunctionFactory.h | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h b/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h index c7122ea6c266..09e27a04c20b 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h @@ -8,9 +8,11 @@ #include "MantidAPI/DllConfig.h" #include "MantidKernel/DynamicFactory.h" #include "MantidKernel/SingletonHolder.h" +#include "MantidKernel/MultiThreaded.h" #include + namespace Mantid { @@ -76,7 +78,7 @@ namespace API /// Query available functions based on the template type template - std::vector getFunctionNames() const; + const std::vector& getFunctionNames() const; private: friend struct Mantid::Kernel::CreateUsingNew; @@ -116,9 +118,11 @@ namespace API /// Add a tie to the created function void addTie(boost::shared_ptr fun,const Expression& expr)const; - ///static reference to the logger class + /// Reference to the logger class Kernel::Logger& g_log; + mutable std::map> m_cachedFunctionNames; + mutable Kernel::Mutex m_mutex; }; /** @@ -127,13 +131,20 @@ namespace API * @returns A vector of the names of the functions matching the template type */ template - std::vector FunctionFactoryImpl::getFunctionNames() const + const std::vector& FunctionFactoryImpl::getFunctionNames() const { + Kernel::Mutex::ScopedLock _lock(m_mutex); + + const std::string soughtType(typeid(FunctionType).name()); + if ( m_cachedFunctionNames.find( soughtType ) != m_cachedFunctionNames.end() ) + { + return m_cachedFunctionNames[soughtType]; + } + + // Create the entry in the cache and work with it directly + std::vector& typeNames = m_cachedFunctionNames[soughtType]; const std::vector names = this->getKeys(); - std::vector typeNames; - typeNames.reserve(names.size()); - for( std::vector::const_iterator it = names.begin(); - it != names.end(); ++it ) + for( auto it = names.begin(); it != names.end(); ++it ) { boost::shared_ptr func = this->createFunction(*it); if ( func && dynamic_cast(func.get()) ) @@ -143,12 +154,13 @@ namespace API } return typeNames; } - ///Forward declaration of a specialisation of SingletonHolder for AlgorithmFactoryImpl (needed for dllexport/dllimport) and a typedef for it. + + ///Forward declaration of a specialisation of SingletonHolder for AlgorithmFactoryImpl (needed for dllexport/dllimport) and a typedef for it. #ifdef _WIN32 // this breaks new namespace declaraion rules; need to find a better fix - template class MANTID_API_DLL Mantid::Kernel::SingletonHolder; + template class MANTID_API_DLL Mantid::Kernel::SingletonHolder; #endif /* _WIN32 */ - typedef MANTID_API_DLL Mantid::Kernel::SingletonHolder FunctionFactory; + typedef MANTID_API_DLL Mantid::Kernel::SingletonHolder FunctionFactory; /// Convenient typedef for an UpdateNotification typedef FunctionFactoryImpl::UpdateNotification FunctionFactoryUpdateNotification; From 08194357a74b28c0ed12c424b7d649f47bbdd87d Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 10:57:10 -0500 Subject: [PATCH 247/403] Re #8634. Add some kind of testing for getFunctionNames. --- Code/Mantid/Framework/API/test/FunctionFactoryTest.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Code/Mantid/Framework/API/test/FunctionFactoryTest.h b/Code/Mantid/Framework/API/test/FunctionFactoryTest.h index 9de1d0be112c..0654f99aca5c 100644 --- a/Code/Mantid/Framework/API/test/FunctionFactoryTest.h +++ b/Code/Mantid/Framework/API/test/FunctionFactoryTest.h @@ -378,6 +378,15 @@ class FunctionFactoryTest : public CxxTest::TestSuite // TODO: add more asserts } + void test_getFunctionNames() + { + const auto& names = FunctionFactory::Instance().getFunctionNames(); + TS_ASSERT( !names.empty() ); + TS_ASSERT( std::find(names.begin(), names.end(), "FunctionFactoryTest_FunctA") != names.end() ); + // Call it again to indirectly test caching + TS_ASSERT_EQUALS( names, FunctionFactory::Instance().getFunctionNames()); + } + }; #endif /*FUNCTIONFACTORYTEST_H_*/ From bfc883e8f81708f4bd7b30ed6aabcb8590a8921e Mon Sep 17 00:00:00 2001 From: Andrei Savici Date: Wed, 18 Dec 2013 11:11:47 -0500 Subject: [PATCH 248/403] MaskAngle tests. Refs #8626 --- .../plugins/algorithms/MaskAngle.py | 1 - .../plugins/algorithms/MaskAngleTest.py | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py index 88b649a97a8b..20e2c8169a2d 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskAngle.py @@ -24,7 +24,6 @@ def name(self): return "MaskAngle" def PyInit(self): - instvalid= self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "",direction=mantid.kernel.Direction.Input,validator=mantid.api.InstrumentValidator()), "Input workspace") angleValidator=mantid.kernel.FloatBoundedValidator() angleValidator.setBounds(0.,180.) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py index 5d34e73dcbdc..28d94046dd6f 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskAngleTest.py @@ -18,6 +18,42 @@ def testMaskAngle(self): DeleteWorkspace(w) self.assertTrue(array_equal(masklist,arange(10)+10)) - + def testFailNoInstrument(self): + w1=CreateWorkspace(arange(5),arange(5)) + try: + MaskAngle(w1,10,20) + self.fail("Should not have got here. Should throw because no instrument.") + except ValueError: + pass + finally: + DeleteWorkspace(w1) + + def testFailLimits(self): + w2=WorkspaceCreationHelper.create2DWorkspaceWithFullInstrument(30,5,False,False) + AnalysisDataService.add('w2',w2) + w3=CloneWorkspace('w2') + w4=CloneWorkspace('w2') + try: + MaskAngle(w2,-100,20) + self.fail("Should not have got here. Wrong angle.") + except ValueError: + pass + finally: + DeleteWorkspace('w2') + try: + MaskAngle(w3,10,200) + self.fail("Should not have got here. Wrong angle.") + except ValueError: + pass + finally: + DeleteWorkspace('w3') + try: + MaskAngle(w4,100,20) + self.fail("Should not have got here. Wrong angle.") + except RuntimeError: + pass + finally: + DeleteWorkspace('w4') + if __name__ == '__main__': unittest.main() From b74c6ea87f28e06e6015765a4d69461c2fd30a63 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 11:28:56 -0500 Subject: [PATCH 249/403] Re #8634. Take advantage of reference return type. --- Code/Mantid/Framework/Algorithms/src/FitPeak.cpp | 3 +-- Code/Mantid/Framework/Algorithms/src/GeneratePeaks.cpp | 3 +-- Code/Mantid/Framework/Algorithms/src/GetDetectorOffsets.cpp | 3 +-- .../PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/FitPeak.cpp b/Code/Mantid/Framework/Algorithms/src/FitPeak.cpp index 3845c085903e..4ab7a2934829 100644 --- a/Code/Mantid/Framework/Algorithms/src/FitPeak.cpp +++ b/Code/Mantid/Framework/Algorithms/src/FitPeak.cpp @@ -107,8 +107,7 @@ namespace Algorithms mustBeNonNegative->setLower(0); declareProperty("WorkspaceIndex", 0, mustBeNonNegative, "Workspace index "); - std::vector peakNames = FunctionFactory::Instance().getFunctionNames(); - vector peakFullNames = addFunctionParameterNames(peakNames); + static vector peakFullNames = addFunctionParameterNames(FunctionFactory::Instance().getFunctionNames()); declareProperty("PeakFunctionType", "", boost::make_shared(peakFullNames), "Peak function type. "); diff --git a/Code/Mantid/Framework/Algorithms/src/GeneratePeaks.cpp b/Code/Mantid/Framework/Algorithms/src/GeneratePeaks.cpp index 2cf455c08846..d9f4b566b35b 100644 --- a/Code/Mantid/Framework/Algorithms/src/GeneratePeaks.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GeneratePeaks.cpp @@ -86,8 +86,7 @@ namespace Algorithms this->declareProperty(new API::WorkspaceProperty("PeakParametersWorkspace", "", Direction::Input), "Input TableWorkspace for peak's parameters."); - std::vector peakNames = FunctionFactory::Instance().getFunctionNames(); - this->declareProperty("PeakFunction", "Gaussian", boost::make_shared(peakNames), + this->declareProperty("PeakFunction", "Gaussian", boost::make_shared(FunctionFactory::Instance().getFunctionNames()), "Peak function to calculate."); this->declareProperty(new API::WorkspaceProperty("InputWorkspace", "", Direction::Input, PropertyMode::Optional), diff --git a/Code/Mantid/Framework/Algorithms/src/GetDetectorOffsets.cpp b/Code/Mantid/Framework/Algorithms/src/GetDetectorOffsets.cpp index 79e75a49edb8..d28e6bf67d35 100644 --- a/Code/Mantid/Framework/Algorithms/src/GetDetectorOffsets.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GetDetectorOffsets.cpp @@ -87,8 +87,7 @@ namespace Mantid declareProperty(new WorkspaceProperty<>("MaskWorkspace","Mask",Direction::Output), "An output workspace containing the mask."); // Only keep peaks - std::vector peakNames = FunctionFactory::Instance().getFunctionNames(); - declareProperty("PeakFunction", "Gaussian", boost::make_shared(peakNames)); + declareProperty("PeakFunction", "Gaussian", boost::make_shared(FunctionFactory::Instance().getFunctionNames())); declareProperty("MaxOffset", 1.0, "Maximum absolute value of offsets; default is 1"); } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp index f7e21755113e..af90f1f1c29d 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp @@ -30,7 +30,7 @@ namespace */ PyObject * getFunctionNames(FunctionFactoryImpl & self) { - std::vector names = self.getFunctionNames(); + const std::vector& names = self.getFunctionNames(); PyObject *registered = PyList_New(0); for (auto name = names.begin(); name != names.end(); ++name) From 2e0d9237bdb909f9d25bc270488a874c7b2990cb Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Tue, 17 Dec 2013 16:36:55 -0500 Subject: [PATCH 250/403] Re #8635. Moved LoadAscii::isAscii into FileDescriptor --- .../inc/MantidDataHandling/LoadAscii.h | 2 -- .../Framework/DataHandling/src/LoadAscii.cpp | 26 ------------------- .../DataHandling/src/LoadRawHelper.cpp | 2 +- .../Kernel/inc/MantidKernel/FileDescriptor.h | 2 ++ .../Framework/Kernel/src/FileDescriptor.cpp | 26 +++++++++++++++++++ .../Kernel/test/FileDescriptorTest.h | 22 ++++++++++++++++ 6 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadAscii.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadAscii.h index 9108cab0a0e6..068dbc125fc8 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadAscii.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadAscii.h @@ -58,8 +58,6 @@ namespace Mantid /// Returns a confidence value that this algorithm can load a file virtual int confidence(Kernel::FileDescriptor & descriptor) const; - static bool isAscii(FILE *file); - protected: /// Process the header information within the file. virtual void processHeader(std::ifstream & file) const; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp b/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp index aad02577bf20..d75d6669040d 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp @@ -81,32 +81,6 @@ namespace Mantid return confidence; } - /** - * Check if a file is a text file - * @param file :: The file pointer - * @returns true if the file an ascii text file, false otherwise - */ - bool LoadAscii::isAscii(FILE *file) - { - char data[256]; - char *pend = &data[fread(data, 1, sizeof(data), file)]; - fseek(file,0,SEEK_SET); - /* - * Call it a binary file if we find a non-ascii character in the - * first 256 bytes of the file. - */ - for( char *p = data; p < pend; ++p ) - { - unsigned long ch = (unsigned long)*p; - if( !(ch <= 0x7F) ) - { - return false; - } - - } - return true; - } - //-------------------------------------------------------------------------- // Protected methods //-------------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp b/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp index 13e615b49560..3acc90ad254d 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp @@ -455,7 +455,7 @@ namespace Mantid */ bool LoadRawHelper::isAscii(FILE* file) const { - return LoadAscii::isAscii(file); + return Kernel::FileDescriptor::isAscii(file); } diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileDescriptor.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileDescriptor.h index 1e94ba74e5d8..2408a7239449 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileDescriptor.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FileDescriptor.h @@ -45,6 +45,8 @@ namespace Mantid static bool isAscii(const std::string & filename, const size_t nbytes=256); /// Returns true if the stream is considered ascii static bool isAscii(std::istream & data, const size_t nbytes=256); + /// Returns true if the file is considered ascii + static bool isAscii(FILE* file, const size_t nbytes=256); public: /// Constructor accepting a filename diff --git a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp index 06be8ab9e2a8..923660cd8a84 100644 --- a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp @@ -69,6 +69,32 @@ namespace Mantid return result; } + /** + * Check if a file is a text file + * @param file :: The file pointer + * @returns true if the file an ascii text file, false otherwise + */ + bool FileDescriptor::isAscii(FILE* file, const size_t nbytes) + { + // read the data and reset the seek index back to the beginning + char data[nbytes]; + char *pend = &data[fread(data, 1, sizeof(data), file)]; + fseek(file,0,SEEK_SET); + + // Call it a binary file if we find a non-ascii character in the + // first nbytes bytes of the file. + for( char *p = data; p < pend; ++p ) + { + unsigned long ch = (unsigned long)*p; + if( !(ch <= 0x7F) ) + { + return false; + } + + } + return true; + } + //---------------------------------------------------------------------------------------------- // Public methods //---------------------------------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h b/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h index d5874df2c042..c06eb5424c5d 100644 --- a/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h +++ b/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h @@ -2,6 +2,7 @@ #define MANTID_KERNEL_FILEDESCRIPTORTEST_H_ #include +#include #include "MantidKernel/FileDescriptor.h" #include "MantidKernel/ConfigService.h" @@ -80,6 +81,27 @@ class FileDescriptorTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(1, is.tellg()); } + void test_isAscii_Returns_True_For_Stream_Pointing_At_Ascii() + { + FILE* handle = fopen(m_testAsciiPath.c_str(), "r"); + if (handle) + { + TS_ASSERT(!FileDescriptor::isAscii(handle)); + TS_ASSERT_EQUALS(0, ftell(handle)); + fclose(handle); + } + } + + void test_isAscii_Returns_False_For_Stream_Pointing_At_Ascii() + { + FILE* handle = fopen(m_testNonNexusPath.c_str(), "r"); + if (handle) + { + TS_ASSERT(FileDescriptor::isAscii(handle)); + TS_ASSERT_EQUALS(0, ftell(handle)); + fclose(handle); + } + } void test_Constructor_With_Existing_File_Initializes_Description_Fields() { From 2a6658c0e27392955b21e957479926954cff03bc Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Wed, 18 Dec 2013 13:35:31 -0500 Subject: [PATCH 251/403] Re #8635. Moving functions over. Old places are just passthrough. --- .../Framework/DataHandling/src/LoadAscii.cpp | 8 ++--- .../Kernel/inc/MantidKernel/Strings.h | 4 +++ Code/Mantid/Framework/Kernel/src/Strings.cpp | 33 ++++++++++++++++--- .../Framework/Kernel/test/StringsTest.h | 12 +++++++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp b/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp index d75d6669040d..c0697f85e383 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadAscii.cpp @@ -27,6 +27,7 @@ This algorithm cannot load a file created by [[SaveAscii]] if it has X errors wr #include "MantidAPI/RegisterFileLoader.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/ListValidator.h" +#include "MantidKernel/Strings.h" #include #include @@ -285,9 +286,7 @@ namespace Mantid */ void LoadAscii::peekLine(std::ifstream & is, std::string & str) const { - getline(is, str); - is.seekg(-(int)str.length(),std::ios::cur); - boost::trim(str); + str = Kernel::Strings::peekLine(is); } /** @@ -297,8 +296,7 @@ namespace Mantid */ bool LoadAscii::skipLine(const std::string & line) const { - // Empty or comment - return ( line.empty() || boost::starts_with(line, "#") ); + return Kernel::Strings::skipLine(line); } /** diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h index bba48a111ce9..cc4b5497329d 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h @@ -94,8 +94,12 @@ namespace Mantid MANTID_KERNEL_DLL void stripComment(std::string& A); /// Determines if a string is only spaces MANTID_KERNEL_DLL int isEmpty(const std::string& A); + /// Determines if a string starts with a # + MANTID_KERNEL_DLL bool skipLine(const std::string & line); /// Get a line and strip comments MANTID_KERNEL_DLL std::string getLine(std::istream& fh,const int spc = 256); + /// Peek at a line without extracting it from the stream + MANTID_KERNEL_DLL std::string peekLine(std::istream & fh); /// get a part of a long line MANTID_KERNEL_DLL int getPartLine(std::istream& fh,std::string& Out,std::string& Excess,const int spc = 256); diff --git a/Code/Mantid/Framework/Kernel/src/Strings.cpp b/Code/Mantid/Framework/Kernel/src/Strings.cpp index 2455fdbdba07..01491652e554 100644 --- a/Code/Mantid/Framework/Kernel/src/Strings.cpp +++ b/Code/Mantid/Framework/Kernel/src/Strings.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -330,6 +331,20 @@ namespace Mantid return Line; } + /** + * Peek at a line without extracting it from the stream + */ + std::string peekLine(std::istream & fh) + { + std::string str; + std::streampos pos = fh.tellg(); + getline(fh, str); + fh.seekg(pos); + + strip(str); + return str; + } + //------------------------------------------------------------------------------------------------ /** * Determines if a string is only spaces @@ -383,13 +398,21 @@ namespace Mantid */ std::string strip(const std::string& A) { - std::string::size_type posA=A.find_first_not_of(" "); - std::string::size_type posB=A.find_last_not_of(" "); - if (posA==std::string::npos) - return ""; - return A.substr(posA,1+posB-posA); + std::string result(A); + boost::trim(result); + return result; } + /** + * Return true if the line is to be skipped (starts with #). + * @param line :: The line to be checked + * @return True if the line should be skipped + */ + bool skipLine(const std::string & line) + { + // Empty or comment + return ( line.empty() || boost::starts_with(line, "#") ); + } //------------------------------------------------------------------------------------------------ /** diff --git a/Code/Mantid/Framework/Kernel/test/StringsTest.h b/Code/Mantid/Framework/Kernel/test/StringsTest.h index c38acada8733..d4b27369d87f 100644 --- a/Code/Mantid/Framework/Kernel/test/StringsTest.h +++ b/Code/Mantid/Framework/Kernel/test/StringsTest.h @@ -120,6 +120,18 @@ class StringsTest : public CxxTest::TestSuite TSM_ASSERT_THROWS(" this path should go out of range",split_path("/aaaa\\bbbbb/../../../",result),std::invalid_argument); } + void testSkipLine() + { + TS_ASSERT(skipLine("#blah blah")); + TS_ASSERT(!skipLine("blah blah")); + } + void testpeekLine() + { + std::istringstream text("blah blah\nfoo bar\n"); + TS_ASSERT(peekLine(text) == "blah blah"); + std::cout << peekLine(text) << std::endl; + TS_ASSERT(peekLine(text) == "blah blah"); + } void testExtractWord() /** Applies a test to the extractWord From e485be9a12f11662ae68e98f29fc10acef4d1a9d Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 13:50:18 -0500 Subject: [PATCH 252/403] Re #8638. Use workspace start time for added log. Not the time when the algorithm is run (a strange choice). If there's not start time, use the epoch (1990-1-1). --- Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp b/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp index 72a3c7454661..a7e009bdfba9 100644 --- a/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp @@ -84,9 +84,14 @@ void AddSampleLog::exec() double val; if (!Strings::convert(propValue, val)) throw std::invalid_argument("Error interpreting string '" + propValue + "' as a number."); - Kernel::DateAndTime now = Kernel::DateAndTime::getCurrentTime(); + Kernel::DateAndTime startTime; + try { + startTime = theRun.startTime(); + } catch (std::runtime_error&) { + // Swallow the error - startTime will just be 0 + } TimeSeriesProperty * tsp = new TimeSeriesProperty(propName); - tsp->addValue(now, val); + tsp->addValue(startTime, val); theRun.addLogData(tsp); } From 70eae4659e1a2c37cc2c353cb7b8daec8f4d56d5 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 13:52:27 -0500 Subject: [PATCH 253/403] Re #8638. Test for the addition of the start time. --- Code/Mantid/Framework/Algorithms/test/AddSampleLogTest.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Mantid/Framework/Algorithms/test/AddSampleLogTest.h b/Code/Mantid/Framework/Algorithms/test/AddSampleLogTest.h index 33b33a2c45bc..ab75cc486402 100644 --- a/Code/Mantid/Framework/Algorithms/test/AddSampleLogTest.h +++ b/Code/Mantid/Framework/Algorithms/test/AddSampleLogTest.h @@ -59,6 +59,7 @@ class AddSampleLogTest : public CxxTest::TestSuite void test_NumberSeries() { MatrixWorkspace_sptr ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + ws->mutableRun().setStartAndEndTime(DateAndTime("2013-12-18T13:40:00"),DateAndTime("2013-12-18T13:42:00")); ExecuteAlgorithm(ws, "My Name", "Number Series", "1.234", 1.234); ExecuteAlgorithm(ws, "My Name", "Number Series", "2.456", 2.456); } @@ -111,6 +112,7 @@ class AddSampleLogTest : public CxxTest::TestSuite { TimeSeriesProperty *testProp = dynamic_cast*>(prop); TS_ASSERT(testProp); + TS_ASSERT_EQUALS(testProp->firstTime(),DateAndTime("2013-12-18T13:40:00")); TS_ASSERT_DELTA(testProp->firstValue(), expectedValue, 1e-5); } From 2b484a0619eea65f10ac9df347ae20c6c8a02384 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Wed, 18 Dec 2013 13:59:38 -0500 Subject: [PATCH 254/403] Re #8635. Hopefully fixing broken windoze build. --- Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp index 923660cd8a84..852428844858 100644 --- a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp @@ -77,22 +77,25 @@ namespace Mantid bool FileDescriptor::isAscii(FILE* file, const size_t nbytes) { // read the data and reset the seek index back to the beginning - char data[nbytes]; - char *pend = &data[fread(data, 1, sizeof(data), file)]; + char *data = new char[nbytes]; + char *pend = &data[fread(data, 1, nbytes, file)]; fseek(file,0,SEEK_SET); // Call it a binary file if we find a non-ascii character in the // first nbytes bytes of the file. + bool result = true; for( char *p = data; p < pend; ++p ) { unsigned long ch = (unsigned long)*p; if( !(ch <= 0x7F) ) { - return false; + result = false; } } - return true; + delete data; + delete pend; + return result; } //---------------------------------------------------------------------------------------------- From 7d5a07e41a5858beae174e8c68d228f85a0d28dc Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 14:04:09 -0500 Subject: [PATCH 255/403] Re #8638. Remove redundant line. It was just setting the property to the value it already had (since it's an InOut). --- Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp b/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp index a7e009bdfba9..04fa93cb7b5f 100644 --- a/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Code/Mantid/Framework/Algorithms/src/AddSampleLog.cpp @@ -94,8 +94,6 @@ void AddSampleLog::exec() tsp->addValue(startTime, val); theRun.addLogData(tsp); } - - setProperty("Workspace", wSpace); } } // namespace Algorithms From 22085b00607f2b715e5e0c132d9112bc3764dbf0 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 14:28:51 -0500 Subject: [PATCH 256/403] Re #8634. Clear cache if functions are added or removed after startup. Can be done from python, and of course it invalidates the cache. --- .../Framework/API/inc/MantidAPI/FunctionFactory.h | 6 ++++++ Code/Mantid/Framework/API/src/FunctionFactory.cpp | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h b/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h index 09e27a04c20b..b9fed8c63c82 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/FunctionFactory.h @@ -80,6 +80,12 @@ namespace API template const std::vector& getFunctionNames() const; + using Kernel::DynamicFactory::subscribe; + void subscribe(const std::string& className, AbstractFactory* pAbstractFactory, + Kernel::DynamicFactory::SubscribeAction replace=ErrorIfExists); + + void unsubscribe(const std::string& className); + private: friend struct Mantid::Kernel::CreateUsingNew; diff --git a/Code/Mantid/Framework/API/src/FunctionFactory.cpp b/Code/Mantid/Framework/API/src/FunctionFactory.cpp index 819f2ce008b0..0b81cca608ff 100644 --- a/Code/Mantid/Framework/API/src/FunctionFactory.cpp +++ b/Code/Mantid/Framework/API/src/FunctionFactory.cpp @@ -335,6 +335,20 @@ namespace Mantid } } + void FunctionFactoryImpl::subscribe(const std::string& className, AbstractFactory* pAbstractFactory, + Kernel::DynamicFactory::SubscribeAction replace) + { + // Clear the cache, then do all the work in the base class method + m_cachedFunctionNames.clear(); + Kernel::DynamicFactory::subscribe(className,pAbstractFactory,replace); + } + + void FunctionFactoryImpl::unsubscribe(const std::string& className) + { + // Clear the cache, then do all the work in the base class method + m_cachedFunctionNames.clear(); + Kernel::DynamicFactory::unsubscribe(className); + } } // namespace API } // namespace Mantid From 24d035fb488aa6f2ddfdb41f562eed55ebefd4ef Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Wed, 18 Dec 2013 14:34:31 -0500 Subject: [PATCH 257/403] Re #8634. Make sure the FrameworkManager is started in tests. ...before the first time getFunctionNames is called. Otherwise the cache will be populated before the functions have been registered. --- Code/Mantid/Framework/Algorithms/test/FindPeaksTest.h | 9 +++++++++ .../Framework/MDAlgorithms/test/IntegratePeaksMD2Test.h | 1 + .../Framework/MDAlgorithms/test/IntegratePeaksMDTest.h | 1 + 3 files changed, 11 insertions(+) diff --git a/Code/Mantid/Framework/Algorithms/test/FindPeaksTest.h b/Code/Mantid/Framework/Algorithms/test/FindPeaksTest.h index e20c5160d407..f7624a3cb520 100644 --- a/Code/Mantid/Framework/Algorithms/test/FindPeaksTest.h +++ b/Code/Mantid/Framework/Algorithms/test/FindPeaksTest.h @@ -6,6 +6,7 @@ #include "MantidAlgorithms/FindPeaks.h" +#include "MantidAPI/FrameworkManager.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidDataHandling/LoadNexusProcessed.h" #include "MantidDataHandling/LoadInstrument.h" @@ -20,6 +21,14 @@ using namespace Mantid::API; class FindPeaksTest : public CxxTest::TestSuite { public: + static FindPeaksTest *createSuite() { return new FindPeaksTest(); } + static void destroySuite( FindPeaksTest *suite ) { delete suite; } + + FindPeaksTest() + { + FrameworkManager::Instance(); + } + void testTheBasics() { FindPeaks finder; diff --git a/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMD2Test.h b/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMD2Test.h index 89387cda21d2..c84458b08a21 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMD2Test.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMD2Test.h @@ -40,6 +40,7 @@ class IntegratePeaksMD2Test : public CxxTest::TestSuite void test_Init() { + FrameworkManager::Instance(); IntegratePeaksMD2 alg; TS_ASSERT_THROWS_NOTHING( alg.initialize() ) TS_ASSERT( alg.isInitialized() ) diff --git a/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMDTest.h index 80fc7aeb4697..892789cd86dc 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/IntegratePeaksMDTest.h @@ -40,6 +40,7 @@ class IntegratePeaksMDTest : public CxxTest::TestSuite void test_Init() { + FrameworkManager::Instance(); IntegratePeaksMD alg; TS_ASSERT_THROWS_NOTHING( alg.initialize() ) TS_ASSERT( alg.isInitialized() ) From 2b100813cbb8737f953afce371492954a60b671c Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 18 Dec 2013 14:43:13 -0500 Subject: [PATCH 258/403] Cleaned the code. Refs #8427. --- .../Algorithms/src/GenerateEventsFilter.cpp | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp index 9ea8de389598..b6fcb2ac3aba 100644 --- a/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -36,6 +36,12 @@ SNS DAS records log values upon its changing. The frequency of log sampling is The option to do interpolation is not supported at this moment. +== Comparison to FilterByLogValue == +1. If the first log value is within the specified range and the first log time is after run star time, +FilterByLogValue assumes that the log value before the first recorded log time is also within range, and thus +the first splitter starts from the run star time, while GenerateEventFilter tends to be more conservative, +and thus the first splitter will start from the first log time. + *WIKI*/ //---------------------------------------------------------------------- @@ -190,9 +196,8 @@ namespace Algorithms } Kernel::DateAndTime runstart = m_dataWS->run().startTime(); - // (m_dataWS->run().getProperty("run_start")->value()); g_log.debug() << "DB9441 Run Start = " << runstart << " / " << runstart.totalNanoseconds() - << std::endl; + << "\n"; std::string title = getProperty("TitleOfSplitters"); if (title.size() == 0) @@ -844,7 +849,14 @@ namespace Algorithms bool centre, bool filterIncrease, bool filterDecrease, DateAndTime startTime, DateAndTime stopTime) { - // 0. Set up + // Return if the log is empty. + if (m_dblLog->size() == 0) + { + g_log.warning() << "There is no entry in this property " << m_dblLog->name() << std::endl; + return; + } + + // Set up double timetolerance = 0.0; if (centre) { @@ -852,49 +864,41 @@ namespace Algorithms } time_duration tol = DateAndTime::durationFromSeconds( timetolerance ); - // 1. Do nothing if the log is empty. - if (m_dblLog->size() == 0) - { - g_log.warning() << "There is no entry in this property " << m_dblLog->name() << std::endl; - return; - } - - // 2. Go through the whole log to set up time intervals - Kernel::DateAndTime ZeroTime(0); + // Go through the whole log to set up time intervals + const Kernel::DateAndTime ZeroTime(0); int lastindex = -1; int currindex = -1; - DateAndTime lastTime, currTime; + DateAndTime lastTime; + DateAndTime currTime = ZeroTime; DateAndTime start, stop; size_t progslot = 0; int logsize = m_dblLog->size(); - for (int i = 0; i < logsize; i ++) { - // a) Initialize status flags and new entry - lastTime = currTime; // for loop i, currTime is not defined. + // Initialize status flags and new entry bool breakloop = false; - bool completehalf = false; - bool newsplitter = false; + bool createsplitter = false; + lastTime = currTime; currTime = m_dblLog->nthTime(i); double currValue = m_dblLog->nthValue(i); - // b) Filter out by time and direction (optional) + // Filter out by time and direction (optional) bool intime = false; if (currTime < startTime) { // case i. Too early, do nothing - completehalf = false; + createsplitter = false; } else if (currTime > stopTime) { - // case ii. Too later. Put to splitter if half of splitter is done. But still within range + // case ii. Too late. Put to splitter if half of splitter is done. But still within range breakloop = true; stop = currTime; if (start.totalNanoseconds() > 0) { - completehalf = true; + createsplitter = true; } } else @@ -903,12 +907,13 @@ namespace Algorithms intime = true; } - // c) Filter in time + // Check log within given time range + bool newsplitter = false; // Flag to start a new split in this loop + if (intime) { - // c1) Determine direction + // Determine direction bool correctdir = true; - if (filterIncrease && filterDecrease) { // Both direction is fine @@ -933,11 +938,11 @@ namespace Algorithms if (!correctdir && start.totalNanoseconds() > 0) { stop = currTime; - completehalf = true; + createsplitter = true; } } // END-IF-ELSE: Direction - // c2) See whether this value falls into any range + // Check this value whether it falls into any range if (correctdir) { size_t index = searchValue(logvalueranges, currValue); @@ -967,7 +972,7 @@ namespace Algorithms { // ii. Time to close a region and new a region stop = currTime; - completehalf = true; + createsplitter = true; newsplitter = true; } else if (currindex == lastindex && start.totalNanoseconds() > 0) @@ -977,7 +982,7 @@ namespace Algorithms { // Last entry in the log. Need to flag to close the pair stop = currTime; - completehalf = true; + createsplitter = true; newsplitter = false; } else @@ -1009,7 +1014,7 @@ namespace Algorithms { // Close the interval pair if it has been started. stop = currTime; - completehalf = true; + createsplitter = true; } } // [In-bound: Between interval] else if (!valuewithin2boundaries) @@ -1020,7 +1025,7 @@ namespace Algorithms { // End situation stop = currTime; - completehalf = true; + createsplitter = true; } else { @@ -1039,7 +1044,7 @@ namespace Algorithms if (start.totalNanoseconds() > 0) { stop = currTime; - completehalf = true; + createsplitter = true; g_log.debug() << "DBOP Log Index [2] " << i << " falls Out b/c value range... " << ".\n"; } } @@ -1058,7 +1063,7 @@ namespace Algorithms } // d) Create Splitter - if (completehalf) + if (createsplitter) { if (centre) { @@ -1091,7 +1096,6 @@ namespace Algorithms lastindex = currindex; // f) Progress - // Progress bar.. size_t tmpslot = i*90/m_dblLog->size(); if (tmpslot > progslot) { @@ -1298,12 +1302,10 @@ namespace Algorithms // a) Found if (value == sorteddata[stop]) { - // std::cout << "DB450 Found @ A " << dataranges[stop] << " Index = " << stop << std::endl; return stop; } else { - // std::cout << "DB450 Found @ B " << dataranges[start] << " Index = " << start << std::endl; return start; } } From 1207589dca639edb5c3df7c67e618a2ad05cdca6 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 18 Dec 2013 15:06:29 -0500 Subject: [PATCH 259/403] Cleaned the code. Refs #8427. --- Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp b/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp index c78a2a789737..542405cb33f2 100644 --- a/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp +++ b/Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp @@ -532,7 +532,6 @@ namespace Algorithms } else { - // FIXME - is there a way to avoid multiplying 1.0 to all TOF? Which can save CPU time input_el.splitByFullTime(m_splitters, outputs, 1.0, m_doTOFCorrection); } @@ -542,8 +541,9 @@ namespace Algorithms // FIXME - Turn on parallel // PARALLEL_END_INTERUPT_REGION } // END FOR i = 0 - // FIXME - Turn on parallel // PARALLEL_CHECK_INTERUPT_REGION + // FIXME - Turn on parallel + // Finish (1) adding events and splitting the sample logs in each target workspace. progress(0.1+progressamount, "Splitting logs"); From 4fca27e9b2bb60f3ad800695d2645704276cc159 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Wed, 18 Dec 2013 15:58:35 -0500 Subject: [PATCH 260/403] Refs #8449 Redid changes starting from updated master modified: LoadSassena.h modified: LoadSassena.cpp --- .../inc/MantidDataHandling/LoadSassena.h | 2 +- .../DataHandling/src/LoadSassena.cpp | 46 ++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h index 2afa1d3ed4ac..8781f56e4f8e 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h @@ -74,7 +74,7 @@ namespace Mantid /// Add a workspace to the group and register in the analysis data service void registerWorkspace(API::WorkspaceGroup_sptr gws, const std::string wsName, DataObjects::Workspace2D_sptr ws, const std::string &description); /// Read info about one HDF5 dataset, log if error - void dataSetInfo( const hid_t& h5file, const std::string setName, hsize_t* dims); + herr_t dataSetInfo( const hid_t& h5file, const std::string setName, hsize_t* dims) const; /// Read dataset data to a buffer ot type double void dataSetDouble( const hid_t& h5file, const std::string setName, double *buf ); /// Load qvectors dataset, calculate modulus of vectors diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp index d3d566e54f6c..c27f8a239d59 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp @@ -56,10 +56,25 @@ void LoadSassena::initDocs() * @param descriptor A descriptor for the file * @returns An integer specifying the confidence level. 0 indicates it will not be used */ -int LoadSassena::confidence(Kernel::NexusDescriptor & descriptor) const +int LoadSassena::confidence( Kernel::NexusDescriptor & descriptor ) const { - if(descriptor.hasRootAttr("sassena_version")) return 99; - return 0; + if( descriptor.hasRootAttr( "sassena_version" ) ) + { + return 99; + } + else + { + // Older sassena files do not have a sassena_version. Find out if "qvectors" is a dataset of the file + const hid_t h5file = H5Fopen( descriptor.filename().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT ); + const std::string setName( "qvectors"); + hsize_t dims[3]; + herr_t errorcode = dataSetInfo( h5file, setName, dims ); + if( errorcode < 0 ) + { + return 0; + } + return 99; + } } /** @@ -82,15 +97,18 @@ void LoadSassena::registerWorkspace( API::WorkspaceGroup_sptr gws, const std::st * @param setName string name of dataset * @param dims storing dimensionality */ -void LoadSassena::dataSetInfo( const hid_t& h5file, const std::string setName, hsize_t* dims) + +herr_t LoadSassena::dataSetInfo( const hid_t& h5file, const std::string setName, hsize_t* dims ) const { H5T_class_t class_id; size_t type_size; - if( H5LTget_dataset_info( h5file, setName.c_str(), dims, &class_id, &type_size ) < 0 ) + herr_t errorcode; + errorcode = H5LTget_dataset_info( h5file, setName.c_str(), dims, &class_id, &type_size ); + if( errorcode < 0 ) { - this->g_log.error("Unable to read "+setName+" dataset info"); - throw Kernel::Exception::FileError("Unable to read "+setName+" dataset info:" , m_filename); + g_log.error( "Unable to read " + setName + " dataset info" ); } + return errorcode; } /** @@ -119,10 +137,13 @@ void LoadSassena::dataSetDouble( const hid_t& h5file, const std::string setName, const MantidVec LoadSassena::loadQvectors(const hid_t& h5file, API::WorkspaceGroup_sptr gws) { const std::string gwsName = this->getPropertyValue("OutputWorkspace"); - std::string setName("qvectors"); + const std::string setName("qvectors"); hsize_t dims[3]; - this->dataSetInfo(h5file, setName, dims); + if ( dataSetInfo(h5file, setName, dims) < 0 ) + { + throw Kernel::Exception::FileError( "Unable to read " + setName + " dataset info:" , m_filename ); + } int nq = static_cast( dims[0] ); //number of q-vectors double* buf = new double[nq*3]; this->dataSetDouble(h5file,"qvectors",buf); @@ -201,7 +222,10 @@ void LoadSassena::loadFQT(const hid_t& h5file, API::WorkspaceGroup_sptr gws, con int nq = static_cast( qvmod.size() ); //number of q-vectors const double dt = getProperty("TimeUnit"); //time unit increment, in picoseconds; hsize_t dims[3]; - this->dataSetInfo(h5file, setName, dims); + if( dataSetInfo( h5file, setName, dims ) < 0 ) + { + throw Kernel::Exception::FileError( "Unable to read " + setName + " dataset info:" , m_filename ); + } int nnt = static_cast( dims[1] ); //number of non-negative time points int nt = 2*nnt - 1; //number of time points int origin = nnt-1; @@ -334,7 +358,7 @@ void LoadSassena::exec() char cversion[16]; if ( H5LTget_attribute_string( h5file, "/", "sassena_version", cversion ) < 0 ) { - throw Kernel::Exception::FileError("Unable to read Sassena version" , m_filename); + this->g_log.error("Unable to read Sassena version"); } //const std::string version(cversion); //determine which loader protocol to use based on the version From 8b2b71d1d3dc807bb8cb2f474b8ec2442add35a9 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Wed, 18 Dec 2013 15:59:50 -0500 Subject: [PATCH 261/403] Re #8635. Fixing mixed up tests. --- Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp | 3 ++- Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp index 852428844858..bcef5dae221b 100644 --- a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp @@ -90,11 +90,12 @@ namespace Mantid if( !(ch <= 0x7F) ) { result = false; + break; } } delete data; - delete pend; + return result; } diff --git a/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h b/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h index c06eb5424c5d..9e4583858951 100644 --- a/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h +++ b/Code/Mantid/Framework/Kernel/test/FileDescriptorTest.h @@ -81,23 +81,23 @@ class FileDescriptorTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(1, is.tellg()); } - void test_isAscii_Returns_True_For_Stream_Pointing_At_Ascii() + void test_isAscii_Returns_True_For_C_Handle() { FILE* handle = fopen(m_testAsciiPath.c_str(), "r"); if (handle) { - TS_ASSERT(!FileDescriptor::isAscii(handle)); + TS_ASSERT(FileDescriptor::isAscii(handle)); TS_ASSERT_EQUALS(0, ftell(handle)); fclose(handle); } } - void test_isAscii_Returns_False_For_Stream_Pointing_At_Ascii() + void test_isAscii_Returns_False_For_C_Handle() { FILE* handle = fopen(m_testNonNexusPath.c_str(), "r"); if (handle) { - TS_ASSERT(FileDescriptor::isAscii(handle)); + TS_ASSERT(!FileDescriptor::isAscii(handle)); TS_ASSERT_EQUALS(0, ftell(handle)); fclose(handle); } From 87bc7a52ac4bd40aaa2d40c761c6ff78fa8a56c9 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 19 Dec 2013 09:12:45 +0000 Subject: [PATCH 262/403] Revert "Revert "refs #8617. ReflectometryReductionOneAuto refined and tested."" This reverts commit 92a4205528842ed57a7e03af37c86edd58d451c3. --- .../ReflectometryReductionOneAuto.py | 37 ++- .../python/plugins/algorithms/CMakeLists.txt | 1 + .../ReflectometryReductionOneAutoTest.py | 48 +++ .../ReflectometryReductionOneBaseTest.py | 290 ++++++++++++++++++ .../ReflectometryReductionOneTest.py | 287 +---------------- 5 files changed, 377 insertions(+), 286 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py index 87727cc413aa..4bbc9cdb36aa 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py @@ -24,7 +24,7 @@ def name(self): def PyInit(self): input_validator = WorkspaceUnitValidator("TOF") - self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, optional=PropertyMode.Optional), "Input run in TOF") + self.declareProperty(MatrixWorkspaceProperty(name="InputWorkspace", defaultValue="", direction=Direction.Input, optional=PropertyMode.Mandatory), "Input run in TOF") analysis_modes = ["PointDetectorAnalysis", "MultiDetectorAnalysis"] analysis_mode_validator = StringListValidator(analysis_modes) @@ -82,9 +82,9 @@ def value_to_apply(self, prop_name, instrument, idf_name=""): def PyExec(self): in_ws = self.getProperty("InputWorkspace").value + instrument = in_ws.getInstrument() first_ws = self.getProperty("FirstTransmissionRun").value - instrument = first_ws.getInstrument() ''' Get all the inputs. @@ -147,14 +147,31 @@ def PyExec(self): ''' Pass the arguments and execute the main algorithm. ''' - new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne(InputWorkspace=in_ws, FirstTransmissionRun=first_ws, SecondTransmissionRun=second_ws, - OutputWorkspace=output_workspace_name, OutputWorkspaceWavelength=output_workspace_lam_name, - StartOverlap=start_overlap, EndOverlap=end_overlap, Params=params, I0MonitorIndex=i0_monitor_index, - WorkspaceIndexList=workspace_index_list, WavelengthMin=wavelength_min, WavelengthStep=wavelength_step, WavelengthMax=wavelength_max, - MonitorBackgroundWavelengthMin=wavelength_back_min, MonitorBackgroundWavelengthMax=wavelength_back_max, - MonitorIntegrationWavelengthMin=wavelength_integration_min, MonitorIntegrationWavelengthMax=wavelength_integration_max, - RegionOfInterest=region_of_interest, RegionOfDirectBeam=region_of_direct_beam, DetectorComponentName=detector_component_name, - SampleComponentName=sample_component_name) + new_IvsQ1, new_IvsLam1, thetaOut1 = ReflectometryReductionOne( + InputWorkspace=in_ws, + AnalysisMode = analysis_mode, + FirstTransmissionRun=first_ws, + SecondTransmissionRun=second_ws, + OutputWorkspace=output_workspace_name, + OutputWorkspaceWavelength=output_workspace_lam_name, + StartOverlap=start_overlap, + EndOverlap=end_overlap, + Params=params, + I0MonitorIndex=i0_monitor_index, + WorkspaceIndexList=workspace_index_list, + WavelengthMin=wavelength_min, + WavelengthStep=wavelength_step, + WavelengthMax=wavelength_max, + MonitorBackgroundWavelengthMin=wavelength_back_min, + MonitorBackgroundWavelengthMax=wavelength_back_max, + MonitorIntegrationWavelengthMin=wavelength_integration_min, + MonitorIntegrationWavelengthMax=wavelength_integration_max, + RegionOfInterest=region_of_interest, + RegionOfDirectBeam=region_of_direct_beam, + DetectorComponentName=detector_component_name, + SampleComponentName=sample_component_name, + ThetaIn=theta_in, + CorrectPositions=correct_positions) self.setProperty("OutputWorkspace", new_IvsQ1) self.setProperty("OutputWorkspaceWavelength", new_IvsLam1) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index 7bad2236ccb5..b7deb4b641e2 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -19,6 +19,7 @@ set ( TEST_PY_FILES MeanTest.py MergeCalFilesTest.py ReflectometryReductionOneTest.py + ReflectometryReductionOneAutoTest.py RetrieveRunInfoTest.py SANSWideAngleCorrectionTest.py SortXAxisTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py new file mode 100644 index 000000000000..e5f9bd38c42c --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneAutoTest.py @@ -0,0 +1,48 @@ +import unittest +from mantid.simpleapi import ReflectometryReductionOneAuto, Load, DeleteWorkspace +from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest + +class ReflectometryReductionOneAutoTest(unittest.TestCase, ReflectometryReductionOneBaseTest): + + def __init__(self, *args, **kwargs): + super(ReflectometryReductionOneAutoTest, self).__init__(*args, **kwargs) + + def setUp(self): + ReflectometryReductionOneBaseTest.setUp(self) + + def tearDown(self): + ReflectometryReductionOneBaseTest.setUp(self) + + def algorithm_type(self): + return ReflectometryReductionOneAuto + + def test_minimal_inputs(self): + + in_ws = Load('INTER00013460.nxs', OutputWorkspace="13460") + trans1 = Load('INTER00013463.nxs', OutputWorkspace="trans1") + + inst = trans1.getInstrument() + + out_ws, out_wsl_lam, thetafinal = ReflectometryReductionOneAuto(InputWorkspace=in_ws, AnalysisMode="PointDetectorAnalysis" + ,OutputWorkspace="InQ", OutputWorkspaceWavelength="InLam") + history = out_ws.getHistory() + alg = history.lastAlgorithm() + + ''' + Here we are checking that the applied values (passed to CreateTransmissionWorkspace come from the instrument parameters. + ''' + self.assertEqual(inst.getNumberParameter("LambdaMin")[0], alg.getProperty("WavelengthMin").value) + self.assertEqual(inst.getNumberParameter("LambdaMax")[0], alg.getProperty("WavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMin")[0], alg.getProperty("MonitorBackgroundWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorBackgroundMax")[0], alg.getProperty("MonitorBackgroundWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMin")[0], alg.getProperty("MonitorIntegrationWavelengthMin").value) + self.assertEqual(inst.getNumberParameter("MonitorIntegralMax")[0], alg.getProperty("MonitorIntegrationWavelengthMax").value) + self.assertEqual(inst.getNumberParameter("I0MonitorIndex")[0], alg.getProperty("I0MonitorIndex").value) + self.assertEqual(inst.getNumberParameter("PointDetectorStart")[0], alg.getProperty("WorkspaceIndexList").value[0]) + self.assertEqual(inst.getNumberParameter("PointDetectorStop")[0], alg.getProperty("WorkspaceIndexList").value[1]) + + DeleteWorkspace(in_ws) + DeleteWorkspace(trans1) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py new file mode 100644 index 000000000000..569a28f01483 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneBaseTest.py @@ -0,0 +1,290 @@ +import unittest +from mantid.simpleapi import * +from testhelpers.algorithm_decorator import make_decorator +import mantid.api +import math +import abc + +class ReflectometryReductionOneBaseTest(object): + + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def algorithm_type(self): + raise RuntimeError("Not implemented") + + def construct_standard_algorithm(self): + alg = make_decorator(self.algorithm_type()) + alg.set_InputWorkspace(self.__tof) + alg.set_WavelengthMin(0.0) + alg.set_WavelengthMax(1.0) + alg.set_I0MonitorIndex(0) + alg.set_WorkspaceIndexList([0, 1]) + alg.set_MonitorBackgroundWavelengthMin(0.0) + alg.set_MonitorBackgroundWavelengthMax(1.0) + alg.set_MonitorIntegrationWavelengthMin(0.0) + alg.set_MonitorIntegrationWavelengthMax(1.0) + alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) + return alg + + def setUp(self): + tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) + self.__tof = tof + self.__not_tof = not_tof + + def tearDown(self): + DeleteWorkspace(self.__tof) + DeleteWorkspace(self.__not_tof) + + + def test_check_input_workpace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_InputWorkspace(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_check_second_transmission_workspace_not_tof_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__not_tof) + self.assertRaises(Exception, alg.execute) + + def test_proivde_second_transmission_run_without_first_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_params_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + self.assertRaises(Exception, alg.execute) + + def test_provide_second_transmission_run_without_start_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_provide_end_transmission_run_without_end_overlap_q_throws(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): + alg = self.construct_standard_algorithm() + alg.set_FirstTransmissionRun(self.__tof) + alg.set_SecondTransmissionRun(self.__tof) + alg.set_Params([0, 0.1, 1]) + alg.set_StartOverlap( 0.6 ) + alg.set_EndOverlap( 0.4 ) + self.assertRaises(Exception, alg.execute) + + def test_must_provide_wavelengths(self): + self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) + self.assertRaises(RuntimeError, self.algorithm_type(), InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) + + def test_wavelength_min_greater_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WavelengthMin(1.0) + alg.set_WavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorBackgroundWavelengthMin(1.0) + alg.set_MonitorBackgroundWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): + alg = self.construct_standard_algorithm() + alg.set_MonitorIntegrationWavelengthMin(1.0) + alg.set_MonitorIntegrationWavelengthMax(0.0) + self.assertRaises(Exception, alg.execute) + + def test_monitor_index_positive(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_throw_if_not_pairs(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([0]) + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_values_not_positive_throws(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. + self.assertRaises(Exception, alg.execute) + + def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): + alg = self.construct_standard_algorithm() + alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 + self.assertRaises(Exception, alg.execute) + + def test_region_of_interest_throws_if_i0monitor_index_negative(self): + alg = self.construct_standard_algorithm() + alg.set_I0MonitorIndex(-1) + self.assertRaises(Exception, alg.execute) + + def test_cannot_set_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfInterest([1, 2]) + self.assertRaises(Exception, alg.execute) + + def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([0, -1]); + self.assertRaises(Exception, alg.execute) + + def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfInterest([1, 0]); + self.assertRaises(Exception, alg.execute) + + def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("PointDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 2]) + self.assertRaises(Exception, alg.execute) + + def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0, -1]); + self.assertRaises(Exception, alg.execute) + + def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): + alg = self.construct_standard_algorithm() + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([1, 0]); + self.assertRaises(Exception, alg.execute) + + def test_bad_detector_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_DetectorComponentName("made-up") + self.assertRaises(Exception, alg.execute) + + def test_bad_sample_component_name_throws(self): + alg = self.construct_standard_algorithm() + alg.set_SampleComponentName("made-up") + self.assertRaises(Exception, alg.execute) + + def test_point_detector_run_with_single_transmission_workspace(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertEqual(0.2, theta, "Theta in and out should be the same") + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + + self.assertEqual(2, out_ws_lam.getNumberHistograms()) + DeleteWorkspace(real_run) + + def test_point_detector_run_with_two_transmission_workspaces(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = Load('INTER00013464.nxs') + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + alg.set_Params([1.5, 0.02, 17]) + alg.set_StartOverlap( 10.0 ) + alg.set_EndOverlap( 12.0 ) + alg.set_ThetaIn(0.2) + + out_ws_q, out_ws_lam, theta = alg.execute() + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + DeleteWorkspace(trans_run2) + + def test_spectrum_map_mismatch_throws(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + trans_run1 = Load('INTER00013463.nxs') + trans_run2 = self.__tof + + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(trans_run1) + alg.set_SecondTransmissionRun(trans_run2) + + self.assertRaises(Exception, alg.execute) + + DeleteWorkspace(real_run) + DeleteWorkspace(trans_run1) + + def test_calculate_theta(self): + alg = self.construct_standard_algorithm() + real_run = Load('INTER00013460.nxs') + alg.set_InputWorkspace(real_run) + alg.set_WorkspaceIndexList([3,4]) + alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. + + out_ws_q, out_ws_lam, theta = alg.execute() + self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) + + DeleteWorkspace(real_run) + + def test_throw_if_no_roi_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_RegionOfDirectBeam([0,1]) + alg.set_DetectorComponentName('lineardetector') + self.assertRaises(Exception, alg.execute) + + def test_throw_if_no_db_for_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([0,1]) + self.assertRaises(Exception, alg.execute) + + def test_multidetector_run(self): + alg = self.construct_standard_algorithm() + real_run = Load('POLREF00004699.nxs') + alg.set_InputWorkspace(real_run[0]) + alg.set_AnalysisMode("MultiDetectorAnalysis") + alg.set_DetectorComponentName('lineardetector') + alg.set_RegionOfInterest([3, 10]) # Fictional values + alg.set_RegionOfDirectBeam([20, 30]) # Fictional values + alg.set_ThetaIn(0.1) # Fictional values + + out_ws_q, out_ws_lam, theta = alg.execute() + + self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) + + self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") + self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) + diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py index 104c18accbf9..f69604f9bae0 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/ReflectometryReductionOneTest.py @@ -1,286 +1,21 @@ import unittest -from mantid.simpleapi import * -from testhelpers.algorithm_decorator import make_decorator -import mantid.api -import math +from mantid.simpleapi import ReflectometryReductionOne +from ReflectometryReductionOneBaseTest import ReflectometryReductionOneBaseTest -class ReflectometryReductionOneTest(unittest.TestCase): +class ReflectometryReductionOneTest(unittest.TestCase, ReflectometryReductionOneBaseTest): - def construct_standard_algorithm(self): - alg = make_decorator(ReflectometryReductionOne) - alg.set_InputWorkspace(self.__tof) - alg.set_WavelengthMin(0.0) - alg.set_WavelengthMax(1.0) - alg.set_I0MonitorIndex(0) - alg.set_WorkspaceIndexList([0, 1]) - alg.set_MonitorBackgroundWavelengthMin(0.0) - alg.set_MonitorBackgroundWavelengthMax(1.0) - alg.set_MonitorIntegrationWavelengthMin(0.0) - alg.set_MonitorIntegrationWavelengthMax(1.0) - alg.set_additional({'OutputWorkspaceWavelength': 'out_ws_wav'}) - return alg + def __init__(self, *args, **kwargs): + super(ReflectometryReductionOneTest, self).__init__(*args, **kwargs) def setUp(self): - tof = CreateWorkspace(UnitX="TOF", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - not_tof = CreateWorkspace(UnitX="1/q", DataX=[0,0,0,0], DataY=[0,0,0], NSpec=1) - self.__tof = tof - self.__not_tof = not_tof + ReflectometryReductionOneBaseTest.setUp(self) def tearDown(self): - DeleteWorkspace(self.__tof) - DeleteWorkspace(self.__not_tof) + ReflectometryReductionOneBaseTest.setUp(self) + def algorithm_type(self): + return ReflectometryReductionOne - def test_check_input_workpace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_InputWorkspace(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_check_first_transmission_workspace_not_tof_or_wavelength_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_check_second_transmission_workspace_not_tof_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__not_tof) - self.assertRaises(ValueError, alg.execute) - - def test_proivde_second_transmission_run_without_first_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(ValueError, alg.execute) - - def test_provide_second_transmission_run_without_params_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - self.assertRaises(ValueError, alg.execute) - - def test_provide_second_transmission_run_without_start_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_provide_end_transmission_run_without_end_overlap_q_throws(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_end_overlap_q_must_be_greater_than_start_overlap_q_or_throw(self): - alg = self.construct_standard_algorithm() - alg.set_FirstTransmissionRun(self.__tof) - alg.set_SecondTransmissionRun(self.__tof) - alg.set_Params([0, 0.1, 1]) - alg.set_StartOverlap( 0.6 ) - alg.set_EndOverlap( 0.4 ) - self.assertRaises(ValueError, alg.execute) - - def test_must_provide_wavelengths(self): - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMin=1.0) - self.assertRaises(RuntimeError, ReflectometryReductionOne, InputWorkspace=self.__tof, FirstTransmissionRun=self.__tof, SecondTransmissionRun=self.__tof, WavelengthMax=1.0) - - def test_wavelength_min_greater_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WavelengthMin(1.0) - alg.set_WavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_background_wavelength_min_greater_monitor_background_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorBackgroundWavelengthMin(1.0) - alg.set_MonitorBackgroundWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_integration_wavelength_min_greater_monitor_integration_wavelength_max_throws(self): - alg = self.construct_standard_algorithm() - alg.set_MonitorIntegrationWavelengthMin(1.0) - alg.set_MonitorIntegrationWavelengthMax(0.0) - self.assertRaises(ValueError, alg.execute) - - def test_monitor_index_positive(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_throw_if_not_pairs(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([0]) - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_values_not_positive_throws(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([-1, 0]) # -1 is not acceptable. - self.assertRaises(ValueError, alg.execute) - - def test_workspace_index_list_min_max_pairs_throw_if_min_greater_than_max(self): - alg = self.construct_standard_algorithm() - alg.set_WorkspaceIndexList([1, 0]) # 1 > 0 - self.assertRaises(ValueError, alg.execute) - - def test_region_of_interest_throws_if_i0monitor_index_negative(self): - alg = self.construct_standard_algorithm() - alg.set_I0MonitorIndex(-1) - self.assertRaises(ValueError, alg.execute) - - def test_cannot_set_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfInterest([1, 2]) - self.assertRaises(ValueError, alg.execute) - - def test_region_of_interest_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([0, -1]); - self.assertRaises(ValueError, alg.execute) - - def test_region_of_integrest_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfInterest([1, 0]); - self.assertRaises(ValueError, alg.execute) - - def test_cannot_set_direct_beam_region_of_interest_without_multidetector_run(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("PointDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 2]) - self.assertRaises(ValueError, alg.execute) - - def test_region_of_direct_beam_indexes_cannot_be_negative_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0, -1]); - self.assertRaises(ValueError, alg.execute) - - def test_region_of_direct_beam_indexes_must_be_provided_as_min_max_order_or_throws(self): - alg = self.construct_standard_algorithm() - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([1, 0]); - self.assertRaises(ValueError, alg.execute) - - def test_bad_detector_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_DetectorComponentName("made-up") - self.assertRaises(ValueError, alg.execute) - - def test_bad_sample_component_name_throws(self): - alg = self.construct_standard_algorithm() - alg.set_SampleComponentName("made-up") - self.assertRaises(ValueError, alg.execute) - - def test_point_detector_run_with_single_transmission_workspace(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertEqual(0.2, theta, "Theta in and out should be the same") - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - - self.assertEqual(2, out_ws_lam.getNumberHistograms()) - DeleteWorkspace(real_run) - - def test_point_detector_run_with_two_transmission_workspaces(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = Load('INTER00013464.nxs') - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - alg.set_Params([1.5, 0.02, 17]) - alg.set_StartOverlap( 10.0 ) - alg.set_EndOverlap( 12.0 ) - alg.set_ThetaIn(0.2) - - out_ws_q, out_ws_lam, theta = alg.execute() - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - DeleteWorkspace(trans_run2) - - def test_spectrum_map_mismatch_throws(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - trans_run1 = Load('INTER00013463.nxs') - trans_run2 = self.__tof - - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(trans_run1) - alg.set_SecondTransmissionRun(trans_run2) - - self.assertRaises(ValueError, alg.execute) - - DeleteWorkspace(real_run) - DeleteWorkspace(trans_run1) - - def test_calculate_theta(self): - alg = self.construct_standard_algorithm() - real_run = Load('INTER00013460.nxs') - alg.set_InputWorkspace(real_run) - alg.set_WorkspaceIndexList([3,4]) - alg.set_FirstTransmissionRun(real_run) # Currently a requirement that one transmisson correction is provided. - - out_ws_q, out_ws_lam, theta = alg.execute() - self.assertAlmostEqual(0.7, theta*(180/math.pi), 1) - - DeleteWorkspace(real_run) - - def test_throw_if_no_roi_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_RegionOfDirectBeam([0,1]) - alg.set_DetectorComponentName('lineardetector') - self.assertRaises(ValueError, alg.execute) - - def test_throw_if_no_db_for_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([0,1]) - self.assertRaises(ValueError, alg.execute) - - def test_multidetector_run(self): - alg = self.construct_standard_algorithm() - real_run = Load('POLREF00004699.nxs') - alg.set_InputWorkspace(real_run[0]) - alg.set_AnalysisMode("MultiDetectorAnalysis") - alg.set_DetectorComponentName('lineardetector') - alg.set_RegionOfInterest([3, 10]) # Fictional values - alg.set_RegionOfDirectBeam([20, 30]) # Fictional values - alg.set_ThetaIn(0.1) # Fictional values - - out_ws_q, out_ws_lam, theta = alg.execute() - - self.assertTrue(isinstance(out_ws_lam, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("Wavelength", out_ws_lam.getAxis(0).getUnit().unitID()) - - self.assertTrue(isinstance(out_ws_q, mantid.api.MatrixWorkspace), "Should be a matrix workspace") - self.assertEqual("MomentumTransfer", out_ws_q.getAxis(0).getUnit().unitID()) - - + if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file From dc4a8da3eb3d0da867c444f5b47d3f3a6c2ee950 Mon Sep 17 00:00:00 2001 From: Peter Peterson Date: Thu, 19 Dec 2013 10:47:53 -0500 Subject: [PATCH 263/403] Re #8635. Using the correct kind of delete now. --- Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp index bcef5dae221b..b4420744375c 100644 --- a/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp +++ b/Code/Mantid/Framework/Kernel/src/FileDescriptor.cpp @@ -94,7 +94,7 @@ namespace Mantid } } - delete data; + delete[] data; return result; } From f212bdb912f73af0ad24189131e448a5dd29e096 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 19 Dec 2013 16:53:27 +0000 Subject: [PATCH 264/403] refs #8639. Separate make transmission corr function Separate make transmission corr function. Utilised by existing transcorr function, but external facing. If not all arguments provided, pick them out of the IDF. --- .../Reflectometry/isis_reflectometry/quick.py | 62 ++++++++++++++++--- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index 8e7042ab9331..bf2058c97a33 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -11,7 +11,7 @@ from l2q import * from combineMulti import * from mantid.simpleapi import * # New API -from mantid.api import WorkspaceGroup +from mantid.api import WorkspaceGroup, MatrixWorkspace from mantid.kernel import logger from convert_to_wavelength import ConvertToWavelength import math @@ -84,7 +84,6 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi ''' Version of quick where all parameters are explicitly provided. ''' - run_ws = ConvertToWavelength.to_workspace(run) to_lam = ConvertToWavelength(run_ws) nHist = run_ws.getNumberHistograms() @@ -188,15 +187,45 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi return mtd[RunNumber+'_IvsLam'], mtd[RunNumber+'_IvsQ'], theta - -def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index): - """ - Perform transmission corrections on i_vs_lam. - return the corrected result. - """ +def make_trans_corr(transrun, lambda_min=None, lambda_max=None, background_min=None, background_max=None, int_min=None, int_max=None, detector_index_ranges=None, i0_monitor_index=None): + ''' + Make the transmission correction workspace. + ''' + + ''' + Check to see whether all optional inputs have been provide. If not we have to get them from the IDF. + ''' + if not all((lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index)): + logger.notice("make_trans_corr: Fetching missing arguments from the IDF") + instrument_source = transrun + if isinstance(transrun, str): + instrument_source = transrun.split(',')[0] + trans_ws = ConvertToWavelength.to_workspace(instrument_source) + idf_defaults = get_defaults(trans_ws) + + # Fetch defaults for anything not specified + if not i0_monitor_index: + i0_monitor_index = idf_defaults['I0MonitorIndex'] + if not lambda_min: + lambda_min = idf_defaults['LambdaMin'] + if not lambda_max: + lambda_max = idf_defaults['LambdaMax'] + if not detector_index_ranges: + point_detector_start = idf_defaults['PointDetectorStart'] + point_detector_stop = idf_defaults['PointDetectorStop'] + detector_index_ranges = (point_detector_start, point_detector_stop) + if not background_min: + background_min = idf_defaults['MonitorBackgroundMin'] + if not background_max: + background_max = idf_defaults['MonitorBackgroundMax'] + if not int_min: + int_min = idf_defaults['MonitorIntegralMin'] + if not int_max: + int_max = idf_defaults['MonitorIntegralMax'] + transWS = None - if ',' in transrun: + if isinstance(transrun, str) and (',' in transrun): slam = transrun.split(',')[0] llam = transrun.split(',')[1] print "Transmission runs: ", transrun @@ -227,7 +256,20 @@ def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, backgr _mon_int_trans = Integration( InputWorkspace=_i0p_trans, RangeLower=int_min, RangeUpper=int_max ) _transWS = Divide( LHSWorkspace=_detector_ws_trans, RHSWorkspace=_mon_int_trans ) - + return _transWS + + +def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index): + """ + Perform transmission corrections on i_vs_lam. + return the corrected result. + """ + if isinstance(transrun, MatrixWorkspace) and transrun.getAxis(0).getUnit().unitID() == "Wavelength" : + _transWS = transrun + else: + # Make the transmission correction workspace. + _transWS = make_trans_corr(transrun, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index) + #got sometimes very slight binning diferences, so do this again: _i_vs_lam_trans = RebinToWorkspace(WorkspaceToRebin=_transWS, WorkspaceToMatch=i_vs_lam) # Normalise by transmission run. From 6717ecbd5d84398b3e15e01f2689bbd9b58464cf Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 19 Dec 2013 17:16:03 +0000 Subject: [PATCH 265/403] refs #8639. Refactor out hard-coded stitching values. This has been a long-standing problem, but is easily fixed now. --- .../Reflectometry/isis_reflectometry/quick.py | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py index bf2058c97a33..4acf0effe610 100644 --- a/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py +++ b/Code/Mantid/scripts/Reflectometry/isis_reflectometry/quick.py @@ -52,7 +52,8 @@ def apply(self, to_correct): return out -def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', debug=False): +def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, usemon=-1,outputType='pd', + debug=False, stitch_start_overlap=10, stitch_end_overlap=12, stitch_params=[1.5, 0.02, 17]): ''' Original quick parameters fetched from IDF ''' @@ -76,11 +77,14 @@ def quick(run, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', polcorr=0, point_detector_start = point_detector_start, point_detector_stop = point_detector_stop, multi_detector_start = multi_detector_start, background_min = background_min, background_max = background_max, int_min = int_min, int_max = int_max, theta = theta, pointdet = pointdet, roi = roi, db = db, trans = trans, - debug = debug, correction_strategy = correction_strategy ) + debug = debug, correction_strategy = correction_strategy, stitch_start_overlap=stitch_start_overlap, + stitch_end_overlap=stitch_end_overlap, stitch_params=stitch_params ) def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_min, background_max, int_min, int_max, - point_detector_start=0, point_detector_stop=0, multi_detector_start=0, theta=0, pointdet=True,roi=[0,0], db=[0,0], trans='', debug=False, correction_strategy=NullCorrectionStrategy): + point_detector_start=0, point_detector_stop=0, multi_detector_start=0, theta=0, + pointdet=True,roi=[0,0], db=[0,0], trans='', debug=False, correction_strategy=NullCorrectionStrategy, + stitch_start_overlap=None, stitch_end_overlap=None, stitch_params=None): ''' Version of quick where all parameters are explicitly provided. ''' @@ -144,7 +148,8 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi names = mtd.getObjectNames() IvsLam = transCorr(trans, IvsLam, lambda_min, lambda_max, background_min, background_max, - int_min, int_max, detector_index_ranges, i0_monitor_index) + int_min, int_max, detector_index_ranges, i0_monitor_index, stitch_start_overlap, + stitch_end_overlap, stitch_params ) RenameWorkspace(InputWorkspace=IvsLam, OutputWorkspace="IvsLam") # TODO: Hardcoded names are bad @@ -187,7 +192,10 @@ def quick_explicit(run, i0_monitor_index, lambda_min, lambda_max, background_mi return mtd[RunNumber+'_IvsLam'], mtd[RunNumber+'_IvsQ'], theta -def make_trans_corr(transrun, lambda_min=None, lambda_max=None, background_min=None, background_max=None, int_min=None, int_max=None, detector_index_ranges=None, i0_monitor_index=None): +def make_trans_corr(transrun, stitch_start_overlap, stitch_end_overlap, stitch_params, + lambda_min=None, lambda_max=None, background_min=None, + background_max=None, int_min=None, int_max=None, detector_index_ranges=None, + i0_monitor_index=None): ''' Make the transmission correction workspace. ''' @@ -244,8 +252,9 @@ def make_trans_corr(transrun, lambda_min=None, lambda_max=None, background_min=N _mon_int_trans = Integration(InputWorkspace=_i0p_llam, RangeLower=int_min,RangeUpper=int_max) _detector_ws_llam = Divide(LHSWorkspace=_detector_ws_llam, RHSWorkspace=_mon_int_trans) - # TODO: HARDCODED STITCHING VALUES!!!!! - _transWS, outputScaling = Stitch1D(LHSWorkspace=_detector_ws_slam, RHSWorkspace=_detector_ws_llam, StartOverlap=10, EndOverlap=12, Params="%f,%f,%f" % (1.5, 0.02, 17)) + print stitch_start_overlap, stitch_end_overlap, stitch_params + _transWS, outputScaling = Stitch1D(LHSWorkspace=_detector_ws_slam, RHSWorkspace=_detector_ws_llam, StartOverlap=stitch_start_overlap, + EndOverlap=stitch_end_overlap, Params=stitch_params) else: @@ -259,7 +268,8 @@ def make_trans_corr(transrun, lambda_min=None, lambda_max=None, background_min=N return _transWS -def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index): +def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index, + stitch_start_overlap, stitch_end_overlap, stitch_params ): """ Perform transmission corrections on i_vs_lam. return the corrected result. @@ -268,7 +278,9 @@ def transCorr(transrun, i_vs_lam, lambda_min, lambda_max, background_min, backgr _transWS = transrun else: # Make the transmission correction workspace. - _transWS = make_trans_corr(transrun, lambda_min, lambda_max, background_min, background_max, int_min, int_max, detector_index_ranges, i0_monitor_index) + _transWS = make_trans_corr(transrun, stitch_start_overlap, stitch_end_overlap, stitch_params, + lambda_min, lambda_max, background_min, background_max, + int_min, int_max, detector_index_ranges, i0_monitor_index,) #got sometimes very slight binning diferences, so do this again: _i_vs_lam_trans = RebinToWorkspace(WorkspaceToRebin=_transWS, WorkspaceToMatch=i_vs_lam) From 09694c8b5657e3448401c86bf77c81d80e3556da Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 13:55:26 -0500 Subject: [PATCH 266/403] Re #8638. Add missing unit test. --- .../Framework/API/test/LogManagerTest.h | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/API/test/LogManagerTest.h b/Code/Mantid/Framework/API/test/LogManagerTest.h index 9e4100ce351f..a9a732793952 100644 --- a/Code/Mantid/Framework/API/test/LogManagerTest.h +++ b/Code/Mantid/Framework/API/test/LogManagerTest.h @@ -91,7 +91,29 @@ class LogManagerTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( runInfo.getProperties().size(), 0 ); } - + void testStartTime() + { + LogManager runInfo; + // Nothing there yet + TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); + // Add run_start and see that get picked up + const std::string run_start("2013-12-19T13:38:00"); + auto run_start_prop = new PropertyWithValue("run_start",run_start); + runInfo.addProperty(run_start_prop); + TS_ASSERT_EQUALS( runInfo.startTime(), DateAndTime(run_start) ); + // Add start_time and see that get picked up in preference + const std::string start_time("2013-12-19T13:40:00"); + auto start_time_prop = new PropertyWithValue("start_time",start_time); + runInfo.addProperty(start_time_prop); + TS_ASSERT_EQUALS( runInfo.startTime(), DateAndTime(start_time) ); + // But get back run_start again if start_time is equal to the epoch + const std::string epoch("1990-01-01T00:00:00"); + start_time_prop->setValue(epoch); + TS_ASSERT_EQUALS( runInfo.startTime(), DateAndTime(run_start) ); + // And back to failure if they're both that + run_start_prop->setValue(epoch); + TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); + } void testMemory() From bc269d0cd07859690103d1b2eb8c754446033a05 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 13:57:52 -0500 Subject: [PATCH 267/403] Re #8638. Much simpler code, same behaviour. --- Code/Mantid/Framework/API/src/LogManager.cpp | 31 ++++---------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/Code/Mantid/Framework/API/src/LogManager.cpp b/Code/Mantid/Framework/API/src/LogManager.cpp index dd6b988c68cd..2ead05bfe63f 100644 --- a/Code/Mantid/Framework/API/src/LogManager.cpp +++ b/Code/Mantid/Framework/API/src/LogManager.cpp @@ -87,7 +87,6 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); const Kernel::DateAndTime LogManager::startTime() const { const std::string start_prop("start_time"); - const std::string run_start_prop("run_start"); if (this->hasProperty(start_prop)) { std::string start = this->getProperty(start_prop)->value(); @@ -95,39 +94,19 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); { return DateAndTime(start); } - else if (this->hasProperty(run_start_prop)) - { - std::string start = this->getProperty(run_start_prop)->value(); - if (DateAndTime(start) != DateAndTimeHelpers::GPS_EPOCH) - { - return DateAndTime(start); - } - else - { - throw std::runtime_error("Run::startTime() - No start time has been set for this run."); - } - } - else - { - throw std::runtime_error("Run::startTime() - No start time has been set for this run."); - } } - else if (this->hasProperty(run_start_prop)) + + const std::string run_start_prop("run_start"); + if (this->hasProperty(run_start_prop)) { std::string start = this->getProperty(run_start_prop)->value(); if (DateAndTime(start) != DateAndTimeHelpers::GPS_EPOCH) { return DateAndTime(start); } - else - { - throw std::runtime_error("Run::startTime() - No start time has been set for this run."); - } - } - else - { - throw std::runtime_error("Run::startTime() - No start time has been set for this run."); } + + throw std::runtime_error("Run::startTime() - No start time has been set for this run."); } /** Return the run end time as given by the 'end_time' or 'run_end' property. From 1fb224daec421aae7143e703e2a9a3fd97fdc7e3 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 14:26:51 -0500 Subject: [PATCH 268/403] Re #8638. Add test for desired behaviour on malformed start times. --- Code/Mantid/Framework/API/test/LogManagerTest.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Code/Mantid/Framework/API/test/LogManagerTest.h b/Code/Mantid/Framework/API/test/LogManagerTest.h index a9a732793952..6dd83932a8da 100644 --- a/Code/Mantid/Framework/API/test/LogManagerTest.h +++ b/Code/Mantid/Framework/API/test/LogManagerTest.h @@ -113,6 +113,22 @@ class LogManagerTest : public CxxTest::TestSuite // And back to failure if they're both that run_start_prop->setValue(epoch); TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); + + // Set run_start back to valid value and make start_time contain nonsense + run_start_prop->setValue(run_start); + start_time_prop->setValue("__"); + TS_ASSERT_EQUALS( runInfo.startTime(), DateAndTime(run_start) ); + // Now make start_time a completely different property type + runInfo.removeProperty("start_time"); + runInfo.addProperty(new PropertyWithValue("start_time",3.33)); + TS_ASSERT_EQUALS( runInfo.startTime(), DateAndTime(run_start) ); + // Now make run_start something invalid + run_start_prop->setValue("notADate"); + TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); + // And check things if it's the wrong property type + runInfo.removeProperty("run_start"); + addTimeSeriesEntry(runInfo,"run_start",4.44); + TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); } From 91e659b026d2afb33d32b3dda30f0bb7af06c6da Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 14:33:03 -0500 Subject: [PATCH 269/403] Re #8638. Catch invalid start times. Catch the exception if the contents of the run_start or start_time properties cannot be turned into a valid DateAndTime. Turn it into the exception for a generic failure of this method. --- Code/Mantid/Framework/API/src/LogManager.cpp | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/Framework/API/src/LogManager.cpp b/Code/Mantid/Framework/API/src/LogManager.cpp index 2ead05bfe63f..1fea9b3297f8 100644 --- a/Code/Mantid/Framework/API/src/LogManager.cpp +++ b/Code/Mantid/Framework/API/src/LogManager.cpp @@ -89,24 +89,28 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); const std::string start_prop("start_time"); if (this->hasProperty(start_prop)) { - std::string start = this->getProperty(start_prop)->value(); - if (DateAndTime(start) != DateAndTimeHelpers::GPS_EPOCH) - { - return DateAndTime(start); - } + try { + DateAndTime start_time(getProperty(start_prop)->value()); + if (start_time != DateAndTimeHelpers::GPS_EPOCH) + { + return start_time; + } + } catch (std::invalid_argument&) { /*Swallow and move on*/ } } const std::string run_start_prop("run_start"); if (this->hasProperty(run_start_prop)) { - std::string start = this->getProperty(run_start_prop)->value(); - if (DateAndTime(start) != DateAndTimeHelpers::GPS_EPOCH) - { - return DateAndTime(start); - } + try { + DateAndTime start_time(getProperty(run_start_prop)->value()); + if (start_time != DateAndTimeHelpers::GPS_EPOCH) + { + return start_time; + } + } catch (std::invalid_argument&) { /*Swallow and move on*/ } } - throw std::runtime_error("Run::startTime() - No start time has been set for this run."); + throw std::runtime_error("No valid start time has been set for this run."); } /** Return the run end time as given by the 'end_time' or 'run_end' property. From d5593ba3dffb82c7cea54d7819b0c6f494e66175 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 14:52:16 -0500 Subject: [PATCH 270/403] Re #8638. Add missing unit test for endTime. Including testing for yet-to-be-implemented behaviour when the end time string is not well-formed. --- .../Framework/API/test/LogManagerTest.h | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/API/test/LogManagerTest.h b/Code/Mantid/Framework/API/test/LogManagerTest.h index 6dd83932a8da..ac90623d21a9 100644 --- a/Code/Mantid/Framework/API/test/LogManagerTest.h +++ b/Code/Mantid/Framework/API/test/LogManagerTest.h @@ -131,7 +131,39 @@ class LogManagerTest : public CxxTest::TestSuite TS_ASSERT_THROWS( runInfo.startTime(), std::runtime_error ); } - + void testEndTime() + { + LogManager runInfo; + // Nothing there yet + TS_ASSERT_THROWS( runInfo.endTime(), std::runtime_error ); + // Add run_end and see that get picked up + const std::string run_end("2013-12-19T13:38:00"); + auto run_end_prop = new PropertyWithValue("run_end",run_end); + runInfo.addProperty(run_end_prop); + TS_ASSERT_EQUALS( runInfo.endTime(), DateAndTime(run_end) ); + // Add end_time and see that get picked up in preference + const std::string end_time("2013-12-19T13:40:00"); + auto end_time_prop = new PropertyWithValue("end_time",end_time); + runInfo.addProperty(end_time_prop); + TS_ASSERT_EQUALS( runInfo.endTime(), DateAndTime(end_time) ); + + // Set run_end back to valid value and make end_time contain nonsense + run_end_prop->setValue(run_end); + end_time_prop->setValue("__"); + TS_ASSERT_EQUALS( runInfo.endTime(), DateAndTime(run_end) ); + // Now make end_time a completely different property type + runInfo.removeProperty("end_time"); + runInfo.addProperty(new PropertyWithValue("end_time",3.33)); + TS_ASSERT_EQUALS( runInfo.endTime(), DateAndTime(run_end) ); + // Now make run_end something invalid + run_end_prop->setValue("notADate"); + TS_ASSERT_THROWS( runInfo.endTime(), std::runtime_error ); + // And check things if it's the wrong property type + runInfo.removeProperty("run_end"); + addTimeSeriesEntry(runInfo,"run_end",4.44); + TS_ASSERT_THROWS( runInfo.endTime(), std::runtime_error ); + } + void testMemory() { LogManager runInfo; From b8bf80d8e51f588162ce9a7601b643594031edd3 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 19 Dec 2013 14:56:58 -0500 Subject: [PATCH 271/403] Refs #8449 Python test fails, remove changes until problem fixed --- Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp index c27f8a239d59..ef38e5261152 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp @@ -62,6 +62,7 @@ int LoadSassena::confidence( Kernel::NexusDescriptor & descriptor ) const { return 99; } + /* else { // Older sassena files do not have a sassena_version. Find out if "qvectors" is a dataset of the file @@ -75,6 +76,7 @@ int LoadSassena::confidence( Kernel::NexusDescriptor & descriptor ) const } return 99; } + */ } /** From 9c4b78e941d707ad7432fe7bf130e67f62415171 Mon Sep 17 00:00:00 2001 From: Russell Taylor Date: Thu, 19 Dec 2013 14:59:27 -0500 Subject: [PATCH 272/403] Re #8638. Refactor to catch misformed times. --- Code/Mantid/Framework/API/src/LogManager.cpp | 27 ++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/Framework/API/src/LogManager.cpp b/Code/Mantid/Framework/API/src/LogManager.cpp index 1fea9b3297f8..7bd9a55bac8a 100644 --- a/Code/Mantid/Framework/API/src/LogManager.cpp +++ b/Code/Mantid/Framework/API/src/LogManager.cpp @@ -87,7 +87,7 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); const Kernel::DateAndTime LogManager::startTime() const { const std::string start_prop("start_time"); - if (this->hasProperty(start_prop)) + if ( hasProperty(start_prop) ) { try { DateAndTime start_time(getProperty(start_prop)->value()); @@ -99,7 +99,7 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); } const std::string run_start_prop("run_start"); - if (this->hasProperty(run_start_prop)) + if ( hasProperty(run_start_prop) ) { try { DateAndTime start_time(getProperty(run_start_prop)->value()); @@ -121,21 +121,22 @@ Kernel::Logger& LogManager::g_log = Kernel::Logger::get("LogManager"); const Kernel::DateAndTime LogManager::endTime() const { const std::string end_prop("end_time"); - const std::string run_end_prop("run_end"); - if (this->hasProperty(end_prop)) - { - std::string end = this->getProperty(end_prop)->value(); - return DateAndTime(end); - } - else if (this->hasProperty(run_end_prop)) + if ( hasProperty(end_prop) ) { - std::string end = this->getProperty(run_end_prop)->value(); - return DateAndTime(end); + try { + return DateAndTime(getProperty(end_prop)->value()); + } catch (std::invalid_argument&) { /*Swallow and move on*/ } } - else + + const std::string run_end_prop("run_end"); + if (hasProperty(run_end_prop)) { - throw std::runtime_error("Run::endTime() - No end time has been set for this run."); + try { + return DateAndTime(getProperty(run_end_prop)->value()); + } catch (std::invalid_argument&) { /*Swallow and move on*/ } } + + throw std::runtime_error("No valid end time has been set for this run."); } From 529e837da0628664c19d9ad83a2dbd983d5c1d1c Mon Sep 17 00:00:00 2001 From: Michael Reuter Date: Thu, 19 Dec 2013 15:37:43 -0500 Subject: [PATCH 273/403] Refs #8632. Fixing system, API and Algorithm doxygen issues. --- .../Framework/API/inc/MantidAPI/IMDNode.h | 1 + .../Framework/API/src/FileLoaderRegistry.cpp | 2 +- .../API/src/IPowderDiffPeakFunction.cpp | 77 ------------------- .../inc/MantidAlgorithms/CopySample.h | 1 - .../MultipleScatteringCylinderAbsorption.h | 15 +--- .../src/CalculateFlatBackground.cpp | 1 + .../Algorithms/src/CalculateTransmission.cpp | 2 +- .../Algorithms/src/CheckWorkspacesMatch.cpp | 3 +- .../src/CreateTransmissionWorkspace.cpp | 2 +- .../Algorithms/src/ExtractMaskToTable.cpp | 2 + .../Framework/Algorithms/src/FindPeaks.cpp | 11 +-- .../Algorithms/src/GenerateEventsFilter.cpp | 2 + .../Algorithms/src/MaskBinsFromTable.cpp | 1 - .../MultipleScatteringCylinderAbsorption.cpp | 20 ++++- .../Framework/Algorithms/src/RadiusSum.cpp | 2 +- .../src/ReflectometryReductionOne.cpp | 2 + .../src/ReflectometryWorkflowBase.cpp | 2 + .../Algorithms/src/SaveGSASInstrumentFile.cpp | 2 +- .../Doxygen/Mantid_template.doxyfile | 4 +- 19 files changed, 42 insertions(+), 110 deletions(-) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h index df36deeb8c83..bbba909b9cc1 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h @@ -177,6 +177,7 @@ class IMDNode * @param length :: length of cylinder below which to integrate * @param signal [out] :: set to the integrated signal * @param errorSquared [out] :: set to the integrated squared error. + * @param signal_fit [out] :: array of values for the fit. */ virtual void integrateCylinder(Mantid::API::CoordTransform & radiusTransform, const coord_t radius, const coord_t length, signal_t & signal, signal_t & errorSquared, std::vector & signal_fit) const = 0; diff --git a/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp b/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp index 084ce2c20f3e..bc3bef8f3790 100644 --- a/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp +++ b/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp @@ -23,7 +23,7 @@ namespace Mantid { void apply(Kernel::FileDescriptor & descriptor) { descriptor.resetStreamToStart(); } }; - ///endcond + /// @endcond /** * @param filename A string giving a filename diff --git a/Code/Mantid/Framework/API/src/IPowderDiffPeakFunction.cpp b/Code/Mantid/Framework/API/src/IPowderDiffPeakFunction.cpp index f6de38ca92c6..1bdacae671fc 100644 --- a/Code/Mantid/Framework/API/src/IPowderDiffPeakFunction.cpp +++ b/Code/Mantid/Framework/API/src/IPowderDiffPeakFunction.cpp @@ -213,83 +213,6 @@ namespace API return; } - //---------------------------------------------------------------------------------------------- - /** General implementation of the method for all peaks. Limits the peak evaluation to - * a certain number of FWHMs around the peak centre. The outside points are set to 0. - * Calls functionLocal() to compute the actual values - * @param out :: Output function values - * @param xValues :: X values for data points - * @param nData :: Number of data points - - void IPowderDiffPeakFunction::functionLocal(double* out, const double* xValues, const size_t nData)const - { - double c = this->centre(); - double dx = fabs(s_peakRadius*this->fwhm()); - int i0 = -1; - int n = 0; - for(size_t i = 0; i < nData; ++i) - { - if (fabs(xValues[i] - c) < dx) - { - if (i0 < 0) i0 = static_cast(i); - ++n; - } - else - { - out[i] = 0.0; - } - } - - if (i0 < 0 || n == 0) - return; - this->functionLocal(out+i0, xValues+i0, n); - - return; - } - */ - - //---------------------------------------------------------------------------------------------- - /** General implementation of the method for all peaks. Calculates derivatives only - * for a range of x values limited to a certain number of FWHM around the peak centre. - * For the points outside the range all derivatives are set to 0. - * Calls functionDerivLocal() to compute the actual values - * @param out :: Derivatives - * @param xValues :: X values for data points - * @param nData :: Number of data points - - void IPowderDiffPeakFunction::functionDeriv1D(Jacobian* out, const double* xValues, const size_t nData) const - { - double c = this->centre(); - double dx = fabs(s_peakRadius*this->fwhm()); - int i0 = -1; - int n = 0; - for(size_t i = 0; i < nData; ++i) - { - if (fabs(xValues[i] - c) < dx) - { - if (i0 < 0) i0 = static_cast(i); - ++n; - } - else - { - for(size_t ip = 0; ip < this->nParams(); ++ip) - { - out->set(i,ip, 0.0); - } - } - } - if (i0 < 0 || n == 0) return; -#if 0 - PartialJacobian1 J(out,i0); - this->functionDerivLocal(&J,xValues+i0,n); -#else - throw runtime_error("Need to think how to implement! Message 1026."); -#endif - - return; - } - */ - //---------------------------------------------------------------------------------------------- /** Set peak radius * @param r :: radius diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h index b6bf2960d8f2..5b9df6ab7865 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h @@ -55,7 +55,6 @@ namespace Algorithms virtual int version() const { return 1;}; /// Algorithm's category for identification virtual const std::string category() const { return "Sample;Utility\\Workspaces;DataHandling";} - /// @inheritdocs virtual std::map validateInputs(); private: /// Sets documentation strings for this algorithm diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MultipleScatteringCylinderAbsorption.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MultipleScatteringCylinderAbsorption.h index 9bf241c66c10..cf67562e7c71 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MultipleScatteringCylinderAbsorption.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/MultipleScatteringCylinderAbsorption.h @@ -75,20 +75,7 @@ class DLLExport MultipleScatteringCylinderAbsorption : public API::Algorithm // Wavelength function double wavelength( double path_length_m, double tof_us ); - /** MultipleScatteringCylinderAbsorption correction calculation. This - * method will change the values in the y_val array to correct for - * multiple scattering absorption. - * - * @param total_path :: The total flight path in meters - * @param angle_deg :: The scattering angle (two theta) in degrees - * @param radius :: The sample rod radius in cm - * @param coeff1 :: The absorption cross section / 1.81 - * @param coeff2 :: The density - * @param coeff3 :: The total scattering cross section - * @param tof :: Array of times-of-flight at bin boundaries - * (or bin centers) for the spectrum, in microseconds - * @param y_val :: The spectrum values - */ + /// MultipleScatteringCylinderAbsorption correction calculation. void apply_msa_correction( double total_path, double angle_deg, double radius, diff --git a/Code/Mantid/Framework/Algorithms/src/CalculateFlatBackground.cpp b/Code/Mantid/Framework/Algorithms/src/CalculateFlatBackground.cpp index 2c47252e0130..cf28238e6a01 100644 --- a/Code/Mantid/Framework/Algorithms/src/CalculateFlatBackground.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CalculateFlatBackground.cpp @@ -352,6 +352,7 @@ double CalculateFlatBackground::Mean(const API::MatrixWorkspace_const_sptr WS, c /** * Uses linear algorithm to do the fitting. * + * @param WS The workspace to fit * @param spectrum The spectrum index to fit, using the workspace numbering of the spectra * @param startX An X value in the first bin to be included in the fit * @param endX An X value in the last bin to be included in the fit diff --git a/Code/Mantid/Framework/Algorithms/src/CalculateTransmission.cpp b/Code/Mantid/Framework/Algorithms/src/CalculateTransmission.cpp index 748a77b63b34..83fa17aa2da6 100644 --- a/Code/Mantid/Framework/Algorithms/src/CalculateTransmission.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CalculateTransmission.cpp @@ -361,7 +361,7 @@ API::MatrixWorkspace_sptr CalculateTransmission::fitData(API::MatrixWorkspace_sp /** Uses Polynomial as a ChildAlgorithm to fit the log of the exponential curve expected for the transmission. * @param[in] WS The single-spectrum workspace to fit * @param[in] order The order of the polynomial from 2 to 6 - * @param[out] the coeficients of the polynomial. c[0] + c[1]x + c[2]x^2 + ... + * @param[out] coeficients of the polynomial. c[0] + c[1]x + c[2]x^2 + ... */ API::MatrixWorkspace_sptr CalculateTransmission::fitPolynomial(API::MatrixWorkspace_sptr WS, int order, std::vector & coeficients) { diff --git a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp index db83f1e91bc8..760975d1338e 100644 --- a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp @@ -99,7 +99,8 @@ bool CheckWorkspacesMatch::processGroups() * @param groupOne :: Input group 1 * @param groupTwo :: Input group 2 */ -void CheckWorkspacesMatch::processGroups(WorkspaceGroup_const_sptr groupOne, WorkspaceGroup_const_sptr groupTwo) +void CheckWorkspacesMatch::processGroups(boost::shared_ptr groupOne, + boost::shared_ptr groupTwo) { // Check their sizes const size_t totalNum = static_cast(groupOne->getNumberOfEntries()); diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index 5678f0c86bbd..0e154c2abaae 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -153,7 +153,7 @@ namespace Mantid * * Input workspaces are in TOF. These are converted to lambda, normalized and stitched together (if two given). * - * @param IvsLam : Run workspace which is to be normalized by the results of the transmission corrections. + * @param detectorIndexes : List of detector indexes to convert * @param wavelengthInterval : Wavelength interval for the run workspace. * @param wavelengthMonitorBackgroundInterval : Wavelength interval for the monitor background * @param wavelengthMonitorIntegrationInterval : Wavelength interval for the monitor integration diff --git a/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp b/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp index 3af6ea82e041..b6153af5e228 100644 --- a/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp @@ -143,6 +143,7 @@ namespace Algorithms //---------------------------------------------------------------------------------------------- /** Parse input TableWorkspace to get a list of detectors IDs of which detector are already masked * @param masktablews :: TableWorkspace containing masking information + * @param maskeddetectorids :: List for holding masked detector IDs */ void ExtractMaskToTable::parseMaskTable(DataObjects::TableWorkspace_sptr masktablews, std::vector& maskeddetectorids) { @@ -323,6 +324,7 @@ namespace Algorithms * @param maskeddetids :: vector of detector IDs of which detectors masked * @param xmin :: minumim x * @param xmax :: maximum x + * @param prevmaskedids :: vector of previous masked detector IDs */ void ExtractMaskToTable::addToTableWorkspace(TableWorkspace_sptr outws, vector maskeddetids, double xmin, double xmax, vector prevmaskedids) diff --git a/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp b/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp index 2003f1574f91..9245be3563cb 100644 --- a/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp +++ b/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp @@ -792,8 +792,8 @@ namespace Algorithms //---------------------------------------------------------------------------------------------- /** Find the index of a value (or nearest) in a given sorted vector (vector of x axis) - * @param X :: vector - * @param centre :: value to search + * @param vecX :: vector + * @param x :: value to search */ int FindPeaks::getVectorIndex(const MantidVec &vecX, double x) { @@ -1179,6 +1179,8 @@ namespace Algorithms * @param in_bg0: guessed value of a0 (output) * @param in_bg1: guessed value of a1 (output) * @param in_bg2: guessed value of a2 (output) + * @param i_peakmin :: index for minimum boundary of peak + * @param i_peakmax :: index for maximum boundary of peak */ void FindPeaks::fitPeakHighBackground(const API::MatrixWorkspace_sptr &input, const size_t spectrum, int i_centre, int i_min, int i_max, @@ -1333,7 +1335,7 @@ namespace Algorithms * @param peak :: peak function to fit * @param in_centre :: starting value of peak centre * @param in_height :: starting value of peak height - * @param in_fhwm :: starting value of peak width + * @param in_fwhms :: starting value of peak width * @param peakleftboundary :: left boundary of peak * @param peakrightboundary :: right boundary of peak * @param user_centre :: peak centre input by user @@ -1751,7 +1753,6 @@ namespace Algorithms * @param centre :: estimated peak centre (maximum position) * @param height :: maximum * @param fwhm :: 2 fwhm - * @param error :: reason for estimating peak parameters error. */ std::string FindPeaks::estimatePeakParameters(const MantidVec& vecX, const MantidVec& vecY, size_t i_min, size_t i_max, double& centre, double& height, double& fwhm) @@ -2103,7 +2104,7 @@ namespace Algorithms /** Check the results of the fit algorithm to see if they make sense and update the best parameters. * @param fitAlg :: algorithm object * @param bestEffparams :: vector of double for best effective parameters - * @param bestRarparams :: vector double for raw function parameters + * @param bestRawparams :: vector double for raw function parameters * @param mincost :: chi square * @param expPeakPos :: double as expected peak position * @param expPeakHeight :: double as expected peak height diff --git a/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp index 9ea8de389598..6966c1c4fe77 100644 --- a/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -1109,10 +1109,12 @@ namespace Algorithms } //----------------------------------------------------------------------------------------------- /** Generate filters for an integer log + * @param splitters :: splitting interval array * @param minvalue :: minimum allowed log value * @param maxvalue :: maximum allowed log value * @param filterIncrease :: include log value increasing period; * @param filterDecrease :: include log value decreasing period + * @param runend :: end of run date and time */ void GenerateEventsFilter::processIntegerValueFilter(TimeSplitterType& splitters, int minvalue, int maxvalue, bool filterIncrease, bool filterDecrease, DateAndTime runend) diff --git a/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp b/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp index 4e4102b6d8db..7e9adb92f52b 100644 --- a/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp @@ -91,7 +91,6 @@ namespace Algorithms //---------------------------------------------------------------------------------------------- /** Call MaskBins * @param dataws :: MatrixWorkspace to mask bins for - * @param maskws :: TableWorkspace containing the mask bin information */ void MaskBinsFromTable::maskBins(API::MatrixWorkspace_sptr dataws) { diff --git a/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp b/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp index afef6e3d9f8a..fec0868f9835 100644 --- a/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp @@ -306,10 +306,22 @@ inline double MultipleScatteringCylinderAbsorption::wavelength( double path_leng /** - * Alter the values in the y_vals[] to account for multiple scattering. - * Parameter total_path is in meters, and the sample radius is in cm. + * This method will change the values in the y_val array to correct for + * multiple scattering absorption. Parameter total_path is in meters, and + * the sample radius is in cm. + * + * @param total_path :: The total flight path in meters + * @param angle_deg :: The scattering angle (two theta) in degrees + * @param radius :: The sample rod radius in cm + * @param coeff1 :: The absorption cross section / 1.81 + * @param coeff2 :: The density + * @param coeff3 :: The total scattering cross section + * @param tof :: Array of times-of-flight at bin boundaries + * (or bin centers) for the spectrum, in microseconds + * @param y_val :: The spectrum values + * @param errors :: The spectrum errors */ -void MultipleScatteringCylinderAbsorption::apply_msa_correction(double total_path, double angle_rad, double radius, +void MultipleScatteringCylinderAbsorption::apply_msa_correction(double total_path, double angle_deg, double radius, double coeff1, double coeff2, double coeff3, vector& tof, vector& y_val, std::vector &errors) { @@ -323,7 +335,7 @@ void MultipleScatteringCylinderAbsorption::apply_msa_correction(double total_pat is_histogram = false; vector Z(Z_initial, Z_initial+Z_size); // initialize Z array for this angle - ZSet(angle_rad, Z); + ZSet(angle_deg, Z); double Q2 = coeff1 * coeff2; double sigsct = coeff2 * coeff3; diff --git a/Code/Mantid/Framework/Algorithms/src/RadiusSum.cpp b/Code/Mantid/Framework/Algorithms/src/RadiusSum.cpp index 977df0b80736..b7957e4cc7be 100644 --- a/Code/Mantid/Framework/Algorithms/src/RadiusSum.cpp +++ b/Code/Mantid/Framework/Algorithms/src/RadiusSum.cpp @@ -323,7 +323,7 @@ namespace Algorithms * It is important that the input workspace must be a numeric image, and not an instrument related workspace. * The function will raise exception (std::invalid_argument) if an invalid input is give. * - * @see ::inputWorkspaceHasInstrumentAssociated for reference. + * @see RadiusSum::inputWorkspaceHasInstrumentAssociated for reference. * * @param inWS reference to the workspace * @return a list of values that defines the limits of the image in this order: Xmin, Xmax, Ymin, Ymax diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 02d788913448..a3bce63b356a 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -234,6 +234,8 @@ namespace Mantid * Correct the position of the detectors based on the input theta value. * @param toCorrect : Workspace to correct detector posisitions on. * @param thetaInDeg : Theta in degrees to use in correction calculations. + * @param sample : Pointer to the sample + * @param detector : Pointer to a given detector */ void ReflectometryReductionOne::correctPosition(API::MatrixWorkspace_sptr toCorrect, const double& thetaInDeg, IComponent_const_sptr sample, IComponent_const_sptr detector) { diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp index 9ef98e83c82a..87b8be331701 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryWorkflowBase.cpp @@ -309,6 +309,8 @@ namespace Mantid * @param stitchingStart * @param stitchingDelta * @param stitchingEnd + * @param stitchingStartOverlap + * @param stitchingEndOverlap */ void ReflectometryWorkflowBase::getTransmissionRunInfo( OptionalMatrixWorkspace_sptr& firstTransmissionRun, diff --git a/Code/Mantid/Framework/Algorithms/src/SaveGSASInstrumentFile.cpp b/Code/Mantid/Framework/Algorithms/src/SaveGSASInstrumentFile.cpp index 51f32931f8e5..c82a79222160 100644 --- a/Code/Mantid/Framework/Algorithms/src/SaveGSASInstrumentFile.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SaveGSASInstrumentFile.cpp @@ -542,7 +542,7 @@ ChopperConfiguration::ChopperConfiguration(const int freq, const std::string& ba //---------------------------------------------------------------------------------------------- /** Set up some constant by default * Output--> m_configuration - * @param chopperfrequency :: chopper frequency of the profile for. + * @param profmap :: map of parameters */ void SaveGSASInstrumentFile::initConstants(const map >& profmap) { diff --git a/Code/Mantid/Framework/Doxygen/Mantid_template.doxyfile b/Code/Mantid/Framework/Doxygen/Mantid_template.doxyfile index 0b06739d7af5..38459889e687 100644 --- a/Code/Mantid/Framework/Doxygen/Mantid_template.doxyfile +++ b/Code/Mantid/Framework/Doxygen/Mantid_template.doxyfile @@ -127,8 +127,8 @@ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../Algorithms/inc \ @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/MantidWidgets/src \ @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/SliceViewer/inc \ @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/SliceViewer/src \ - @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/ImageViewer/inc \ - @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/ImageViewer/src \ + @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/SpectrumViewer/inc \ + @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/SpectrumViewer/src \ @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/RefDetectorViewer/inc \ @CMAKE_CURRENT_SOURCE_DIR@/../../MantidQt/RefDetectorViewer/src \ @CMAKE_CURRENT_SOURCE_DIR@/../../Vates/ParaviewPlugins \ From d31d25bdb89bd58e01db2640c7afc6ea3094ba90 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 19 Dec 2013 15:45:08 -0500 Subject: [PATCH 274/403] Refs #8449 Cmakefile commented until I figure out the error --- Code/Mantid/Framework/DataHandling/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index a6d2877b0070..795b4f535c75 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -80,7 +80,7 @@ set ( SRC_FILES src/LoadSNSspec.cpp src/LoadSPE.cpp src/LoadSampleDetailsFromRaw.cpp - src/LoadSassena.cpp +# src/LoadSassena.cpp src/LoadSpec.cpp src/LoadSpice2D.cpp src/LoadTOFRawNexus.cpp @@ -205,7 +205,7 @@ set ( INC_FILES inc/MantidDataHandling/LoadSNSspec.h inc/MantidDataHandling/LoadSPE.h inc/MantidDataHandling/LoadSampleDetailsFromRaw.h - inc/MantidDataHandling/LoadSassena.h +# inc/MantidDataHandling/LoadSassena.h inc/MantidDataHandling/LoadSpec.h inc/MantidDataHandling/LoadSpice2D.h inc/MantidDataHandling/LoadTOFRawNexus.h @@ -326,7 +326,7 @@ set ( TEST_FILES LoadSINQFocusTest.h LoadSNSspecTest.h LoadSPETest.h - LoadSassenaTest.h +# LoadSassenaTest.h LoadSaveAsciiTest.h LoadSpice2dTest.h LoadTOFRawNexusTest.h From 922d83437ab300cb5800f60f5592f99845fe351d Mon Sep 17 00:00:00 2001 From: Michael Reuter Date: Thu, 19 Dec 2013 16:22:40 -0500 Subject: [PATCH 275/403] Refs #8632. Fixing Crystal, DataObjects and Geometry doxygen issues. --- .../inc/MantidCrystal/SCDCalibratePanels.h | 4 +- .../Crystal/src/IntegratePeakTimeSlices.cpp | 52 ++++++++++--------- .../src/OptimizeLatticeForCellType.cpp | 7 +-- .../Crystal/src/SCDCalibratePanels.cpp | 8 +-- .../Framework/DataObjects/src/EventList.cpp | 1 + .../Geometry/src/Crystal/OrientedLattice.cpp | 4 +- 6 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h index dfbfbdd71c5e..b19226ffe85a 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h @@ -281,7 +281,7 @@ namespace Crystal * @param ws The workspace with the predicted qx,qy, and qz values for each * peak * - * @param nGroups The number of Groups-Sets of panels + * @param NGroups The number of Groups-Sets of panels * @param names The names of the variables that have been fit * * @param params The values of the variables that have been fit @@ -297,7 +297,7 @@ namespace Crystal * @param nData The number of xVals and out values */ void CreateFxnGetValues(DataObjects::Workspace2D_sptr const ws, - int const nGroups, std::vector const names, + int const NGroups, std::vector const names, std::vector const params, std::string const BankNameString, double *out, const double *xVals,const size_t nData) const; diff --git a/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp b/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp index 6178c48f73ac..5ec16550e800 100644 --- a/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp +++ b/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp @@ -801,10 +801,10 @@ namespace Mantid /** * Checks and updates if needed the list of NeighborIDs * @param comp Component with the neighboring pixels - * @CentPos new Center + * @param CentPos new Center * @param oldCenter old Center * @param NewRadius new Radius - * ¶m neighborRadius old the new neighborhood radius + * @param neighborRadius old the new neighborhood radius */ bool IntegratePeakTimeSlices::updateNeighbors( boost::shared_ptr< Geometry::IComponent> &comp, V3D CentPos, V3D oldCenter,double NewRadius, double &neighborRadius) @@ -1549,15 +1549,17 @@ namespace Mantid } /** * Initial phase at converting Detector data to workspace data that will be sent to the Fit Function, BivariateNormal. - * @param Data workspace that will be sent to the Fit Function, BivariateNormal + * @param Data -workspace that will be sent to the Fit Function, BivariateNormal * @param inpWkSpace -The MatrixWorkspace with all the experimental data - * @param comp -The parent of all the pixels that are neighbors of the peak being considered + * @param comp -The parent of all the pixels that are neighbors of the peak being considered * @param chanMin -The minimum channel to use - * @param chanMax-The maximum channel to be collapsed to one channel - * @param CentNghbr- The center of the current and next(if changed) neighbor pixels - * @param neighborRadius- The radius of the current neighbor pixels - * @param Radius The current starting Radius to use for neighbors. - * @param spec_idList-The list of spectral id's that are neighbors + * @param chanMax -The maximum channel to be collapsed to one channel + * @param CentX -The current peak row + * @param CentY -The current peak column + * @param CentNghbr -The center of the current and next(if changed) neighbor pixels + * @param neighborRadius -The radius of the current neighbor pixels + * @param Radius -The current starting Radius to use for neighbors. + * @param spec_idList -The list of spectral id's that are neighbors * */ void IntegratePeakTimeSlices::SetUpData( MatrixWorkspace_sptr & Data, @@ -1987,12 +1989,12 @@ namespace Mantid * Utility method to calculate variances from data given background and means * * @param background - the background to use - * @param meanx- the mean x( col) value to use - * @param meany- the mean y( row) value to use - * @param Varxx-The resultant variance in the x values around above mean with background removed - * @param Varyy-The resultant variance in the y values around above mean with background removed - * @param Varxy-The resultant covariance in the x and values around above mean with background removed - * @param StatBase- The "data". + * @param meanx - the mean x( col) value to use + * @param meany - the mean y( row) value to use + * @param Varxx - The resultant variance in the x values around above mean with background removed + * @param Varyy - The resultant variance in the y values around above mean with background removed + * @param Varxy - The resultant covariance in the x and values around above mean with background removed + * @param StatBase - The "data". */ void DataModeHandler::CalcVariancesFromData( double background, double meanx, double meany, double &Varxx, double &Varxy, double &Varyy, @@ -2026,6 +2028,7 @@ namespace Mantid /** * Calculates the string form of the constraints to be sent to the Fit Algorithm and also saves it in a vector form * @param Bounds The vector form for the constraints + * @param CalcVariances The to trigger variance calculation */ std::string DataModeHandler::CalcConstraints( std::vector< std::pair > & Bounds, bool CalcVariances) @@ -2127,7 +2130,7 @@ namespace Mantid * @param errs The parameter errorfrom the Fit Algorithm * @param lastRow The previous row( for log info only) * @param lastCol The previous col( for log info only) - * @param neighborhoodRadius The neighborhood radius( for log info only) + * @param neighborRadius The neighborhood radius( for log info only) */ void IntegratePeakTimeSlices::Fit(MatrixWorkspace_sptr &Data,double &chisqOverDOF, bool &done, std::vector&names, std::vector¶ms, @@ -2253,7 +2256,7 @@ namespace Mantid * @param errs The parameter errorfrom the Fit Algorithm * @param lastRow The previous row( for log info only) * @param lastCol The previous col( for log info only) - * @param neighborhoodRadius The neighborhood radius( for log info only) + * @param neighborRadius The neighborhood radius( for log info only) */ void IntegratePeakTimeSlices::PreFit(MatrixWorkspace_sptr &Data,double &chisqOverDOF, bool &done, std::vector&names, std::vector¶ms, @@ -2469,7 +2472,8 @@ namespace Mantid /** * Calculates if there is enough data to for there to be a peak * - * @param true if there is enough data, otherwise false + * @param ParameterValues pointer to the parameter values + * @return true if there is enough data, otherwise false */ bool DataModeHandler::IsEnoughData( const double *ParameterValues, Kernel::Logger& ) { @@ -2515,10 +2519,10 @@ namespace Mantid * Calculates the error in integration closest to the latest ISAW calculations * * @param background The background - * @param backError The error in this background value - * @param ChiSqOverDOF The fitting error - * @param TotVariance The Total square of the intensity errors in all the cells considered - * @param ncell The number of cells + * @param backError The error in this background value + * @param ChiSqOverDOF The fitting error + * @param TotVariance The Total square of the intensity errors in all the cells considered + * @param ncells The number of cells * * @return The error in the integrated intensity */ @@ -2728,7 +2732,7 @@ namespace Mantid /** * Calculates the Intensity designed for Edge Peaks * - * @param The Fitted parameters + * @param params The Fitted parameters * * @return this calculated intensity * @@ -2752,7 +2756,7 @@ namespace Mantid /** * Calculates the Error in the Intensity designed for Edge Peaks * - * @param The fitted parameter values + * @param params The fitted parameter values * @param errs The error in these fitted parameters * @param chiSqOvDOF The fitting error * diff --git a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp index 36a3bcff36e5..c2ac8b161031 100644 --- a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp +++ b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp @@ -206,12 +206,9 @@ namespace Mantid //----------------------------------------------------------------------------------------- /** * Calls Gaussian1D as a child algorithm to fit the offset peak in a spectrum - * @param mosaic - * @param rcrystallite * @param inname - * @param corrOption - * @param pointOption - * @param tofParams + * @param cell_type + * @param params * @return */ double OptimizeLatticeForCellType::optLattice(std::string inname, std::string cell_type, std::vector & params) diff --git a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp index 6f06dddb9415..daed93e21c9d 100644 --- a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp +++ b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp @@ -1114,6 +1114,7 @@ namespace Mantid * @param instrument The instrument to be modified * @param AllBankName The bank names in this instrument that will be modified * @param T0 The time offset from the DetCal file + * @param L0 The length offset from the DetCal file * @param filename The DetCal file name * @param bankPrefixName The prefix to the bank names. */ @@ -1327,12 +1328,11 @@ namespace Mantid * Really this is the operator SaveIsawDetCal but only the results of the given * banks are saved. L0 and T0 are also saved. * - * @param NewInstrument -The instrument with the correct panel geometries + * @param instrument -The instrument with the correct panel geometries * and initial path length - * * @param AllBankName -the set of the NewInstrument names of the banks(panels) - * @param T0 -The time offset - * @param FileName -The name of the DetCal file to save the results to + * @param T0 -The time offset from the DetCal file + * @param filename -The name of the DetCal file to save the results to */ void SCDCalibratePanels::saveIsawDetCal( boost::shared_ptr &instrument, set &AllBankName,double T0,string filename) diff --git a/Code/Mantid/Framework/DataObjects/src/EventList.cpp b/Code/Mantid/Framework/DataObjects/src/EventList.cpp index 4ee29fa8a00c..35115ab5133c 100644 --- a/Code/Mantid/Framework/DataObjects/src/EventList.cpp +++ b/Code/Mantid/Framework/DataObjects/src/EventList.cpp @@ -3757,6 +3757,7 @@ namespace DataObjects * be big enough to accommodate the indices. * @param events :: either this->events or this->weightedEvents. * @param tofcorrection :: a correction for each TOF to multiply with. + * @param docorrection :: flag to determine whether or not to apply correction */ template< class T > void EventList::splitByFullTimeHelper(Kernel::TimeSplitterType & splitter, std::map outputs, diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp index cecae9362640..a588cd53c6f7 100644 --- a/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp +++ b/Code/Mantid/Framework/Geometry/src/Crystal/OrientedLattice.cpp @@ -168,8 +168,8 @@ namespace Geometry } /** Calculate the hkl corresponding to a given Q-vector - * @return Q :: Q-vector in $AA^-1 in the sample frame - * @param a V3D with H,K,L + * @param hkl a V3D with H,K,L + * @return Q-vector in $AA^-1 in the sample frame */ V3D OrientedLattice::qFromHKL(const V3D & hkl) const { From cadabcbd1165376e405294226554f3488707d6e6 Mon Sep 17 00:00:00 2001 From: Jose Borreguero Date: Thu, 19 Dec 2013 17:37:12 -0500 Subject: [PATCH 276/403] Refs #8449 Addd extra check in confidence method --- .../Framework/DataHandling/CMakeLists.txt | 6 +++--- .../Framework/DataHandling/src/LoadSassena.cpp | 18 ++---------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 795b4f535c75..a6d2877b0070 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -80,7 +80,7 @@ set ( SRC_FILES src/LoadSNSspec.cpp src/LoadSPE.cpp src/LoadSampleDetailsFromRaw.cpp -# src/LoadSassena.cpp + src/LoadSassena.cpp src/LoadSpec.cpp src/LoadSpice2D.cpp src/LoadTOFRawNexus.cpp @@ -205,7 +205,7 @@ set ( INC_FILES inc/MantidDataHandling/LoadSNSspec.h inc/MantidDataHandling/LoadSPE.h inc/MantidDataHandling/LoadSampleDetailsFromRaw.h -# inc/MantidDataHandling/LoadSassena.h + inc/MantidDataHandling/LoadSassena.h inc/MantidDataHandling/LoadSpec.h inc/MantidDataHandling/LoadSpice2D.h inc/MantidDataHandling/LoadTOFRawNexus.h @@ -326,7 +326,7 @@ set ( TEST_FILES LoadSINQFocusTest.h LoadSNSspecTest.h LoadSPETest.h -# LoadSassenaTest.h + LoadSassenaTest.h LoadSaveAsciiTest.h LoadSpice2dTest.h LoadTOFRawNexusTest.h diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp index ef38e5261152..cbfc6466ed77 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp @@ -58,25 +58,11 @@ void LoadSassena::initDocs() */ int LoadSassena::confidence( Kernel::NexusDescriptor & descriptor ) const { - if( descriptor.hasRootAttr( "sassena_version" ) ) + if( descriptor.hasRootAttr( "sassena_version" ) || descriptor.pathExists("/qvectors") ) { return 99; } - /* - else - { - // Older sassena files do not have a sassena_version. Find out if "qvectors" is a dataset of the file - const hid_t h5file = H5Fopen( descriptor.filename().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT ); - const std::string setName( "qvectors"); - hsize_t dims[3]; - herr_t errorcode = dataSetInfo( h5file, setName, dims ); - if( errorcode < 0 ) - { - return 0; - } - return 99; - } - */ + return 0; } /** From e55c9c38ece6671b7c45be5b168fc467874c9a40 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 20 Dec 2013 08:35:27 +0000 Subject: [PATCH 277/403] Refs #8176 Updated column type. --- .../algorithms/WorkflowAlgorithms/IndirectTransmission.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index f3739aceb006..9f67f6da89e6 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -75,7 +75,7 @@ def PyExec(self): tableWs = nameStem + '_Transmission' tableWs = CreateEmptyTableWorkspace(OutputWorkspace=tableWs) tableWs.addColumn("str", "Name") - tableWs.addColumn("str", "Value") + tableWs.addColumn("double", "Value") # Names for each of the output values outputNames = ['Wavelength', 'Absorption Xsection', 'Coherent Xsection', 'Incoherent Xsection', @@ -84,13 +84,11 @@ def PyExec(self): # List of the calculated values outputValues = [wave, absorptionXSection, coherentXSection, incoherentXSection, scatteringXSection, density, thickness, transmission, scattering] - - outputValues = map(str, outputValues) - + #build table of values for data in zip (outputNames, outputValues): tableWs.addRow(list(data)) - logger.information(': '.join(list(data))) + logger.information(': '.join(map(str,list(data)))) #remove idf/ipf workspace DeleteWorkspace(workspace) From a5e472c0dd364bad46cfbc6beb982ce0ad32747a Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 20 Dec 2013 08:54:07 +0000 Subject: [PATCH 278/403] Refs #8176 Give algorithm a proper output workspace property. --- .../WorkflowAlgorithms/IndirectTransmission.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py index 9f67f6da89e6..024daf448b3c 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/IndirectTransmission.py @@ -6,8 +6,8 @@ *WIKI*""" from mantid.simpleapi import * -from mantid.api import PythonAlgorithm, AlgorithmFactory -from mantid.kernel import StringListValidator, StringMandatoryValidator +from mantid.api import * +from mantid.kernel import * from mantid import config import os.path, math @@ -23,7 +23,8 @@ def PyInit(self): self.declareProperty(name='ChemicalFormula',defaultValue='',validator=StringMandatoryValidator(), doc='Sample chemical formula') self.declareProperty(name='NumberDensity', defaultValue=0.1, doc='Number denisty. Default=0.1') self.declareProperty(name='Thickness', defaultValue=0.1, doc='Sample thickness. Default=0.1') - + self.declareProperty(WorkspaceProperty('OutputWorkspace', "", Direction.Output), doc="The name of the output workspace.") + def PyExec(self): from IndirectCommon import StartTime, EndTime @@ -72,7 +73,7 @@ def PyExec(self): scattering = 1.0 - math.exp(-density*scatteringXSection*thickness) #Create table workspace to store calculations - tableWs = nameStem + '_Transmission' + tableWs = self.getPropertyValue('OutputWorkspace') tableWs = CreateEmptyTableWorkspace(OutputWorkspace=tableWs) tableWs.addColumn("str", "Name") tableWs.addColumn("double", "Value") @@ -92,7 +93,7 @@ def PyExec(self): #remove idf/ipf workspace DeleteWorkspace(workspace) - + self.setProperty("OutputWorkspace", tableWs) EndTime('IndirectTransmission') # Register algorithm with Mantid From 8e2fbe6ac255e589579aba73682d6eb7d1ca5c4e Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Fri, 20 Dec 2013 09:24:34 +0000 Subject: [PATCH 279/403] Refs #8346 Check if d-range between files matches exactly. --- .../WorkflowAlgorithms/OSIRISDiffractionReduction.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py index 0cafeaf3fbc0..b71d8c4d6aeb 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/OSIRISDiffractionReduction.py @@ -52,6 +52,18 @@ def addWs(self, wsname): # Add the workspace to the map, alongside its DRange. if dRange not in self._map: self._map[dRange] = [wsname] + else: + #check if x ranges matchs and existing run + for ws_name in self._map[dRange]: + map_lastx = mtd[ws_name].readX(0)[-1] + ws_lastx = ws.readX(0)[-1] + + #if it matches ignore it + if map_lastx == ws_lastx: + DeleteWorkspace(ws) + return + + self._map[dRange].append(wsname) def setItem(self, dRange, wsname): """ Set a dRange and corresponding *single* ws. From 0cbfe355e94cf41c6af3ff11f2b66643f0772eb0 Mon Sep 17 00:00:00 2001 From: Karl Palmen Date: Fri, 20 Dec 2013 11:34:23 +0000 Subject: [PATCH 280/403] Add a not yet correct test of a parameter re #8398 Test does not pass because it is not yet correct. Do not git checkbuild. Signed-off-by: Karl Palmen --- .../test/LoadFullprofResolutionTest.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h index 3be2ede3cd29..63330d411883 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h @@ -8,6 +8,9 @@ #include "MantidAPI/TableRow.h" #include "MantidDataHandling/LoadInstrument.h" #include "MantidDataObjects/Workspace2D.h" +#include "MantidGeometry/Instrument.h" +#include "MantidGeometry/Instrument/Component.h" +#include "MantidGeometry/Instrument/FitParameter.h" #include #include @@ -297,6 +300,18 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite TS_ASSERT(alg.isExecuted()); // Check parameters in workspace + MatrixWorkspace_sptr ws; + ws = AnalysisDataService::Instance().retrieveWS(wsName); + Mantid::Geometry::ParameterMap& paramMap = ws->instrumentParameters(); + boost::shared_ptr instr = ws->getInstrument(); + + + Mantid::Geometry::Parameter_sptr alpha0Param = paramMap.get(&(*instr), "IkedaCarpenterPV:Alpha0", "fitting"); + TS_ASSERT(alpha0Param); + if(alpha0Param) { + const Mantid::Geometry::FitParameter& fitParam1 = alpha0Param->value(); + TS_ASSERT_DELTA( fitParam1.getValue(), 100.0, 0.0001); + } // Clean Poco::File("TestWorskpace.irf").remove(); From 4b69262e8876e6278584415f1f04a44fb00c09ef Mon Sep 17 00:00:00 2001 From: Michael Reuter Date: Fri, 20 Dec 2013 09:03:22 -0500 Subject: [PATCH 281/403] Refs #8632. Fixing CurveFitting doxygen errors. --- .../inc/MantidCurveFitting/Lorentzian.h | 4 +- .../src/AugmentedLagrangianOptimizer.cpp | 6 +- .../src/ComptonScatteringCountRate.cpp | 2 - .../CurveFitting/src/CubicSpline.cpp | 5 +- .../CurveFitting/src/LeBailFunction.cpp | 14 +- .../Framework/CurveFitting/src/Linear.cpp | 266 ------------------ .../Framework/CurveFitting/src/SeqDomain.cpp | 2 +- .../CurveFitting/src/SplineInterpolation.cpp | 1 - 8 files changed, 19 insertions(+), 281 deletions(-) delete mode 100644 Code/Mantid/Framework/CurveFitting/src/Linear.cpp diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h index e966eef72b61..18fbb764193c 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/Lorentzian.h @@ -12,9 +12,9 @@ namespace Mantid { /** Provide lorentzian peak shape function interface to IPeakFunction. - I.e. the function: \frac{A}{\pi}( \Gamma/2((x-PeakCentre)^2+(\Gamma/2)^2) ). + I.e. the function: \f$ \frac{A}{\pi}( \Gamma/2((x-PeakCentre)^2+(\Gamma/2)^2) )\f$. - \Gamma/2 (HWHM) - half-width at half-maximum + \f$\Gamma/2\f$ (HWHM) - half-width at half-maximum Lorentzian parameters: