From 405b5090557cf4029139471f672dca81fefacecc Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 10:15:17 +0100 Subject: [PATCH 01/46] Refs #7860 Move existing code into python algorithm. --- .../WorkflowAlgorithms/Symmetrise.py | 161 ++++++++++++++---- 1 file changed, 128 insertions(+), 33 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 8fc7432fad09..29d93d5701bd 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -5,43 +5,138 @@ *WIKI*""" -# Algorithm to start Symmetrise +from mantid import config, logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory from mantid.kernel import StringListValidator, StringMandatoryValidator +from mantid.simpleapi import * +import sys, platform, math, os.path, numpy as np class Symmetrise(PythonAlgorithm): + + def category(self): + return "Workflow\\MIDAS;PythonAlgorithms" + + def PyInit(self): + self.setOptionalMessage("Takes and asymmetric S(Q,w) and makes it symmetric") + self.setWikiSummary("Takes and asymmetric S(Q,w) and makes it symmetric") + + self.declareProperty(name='InputType',defaultValue='File',validator=StringListValidator(['File','Workspace']), doc='Origin of data input - File (_red.nxs) or Workspace') + self.declareProperty(name='Instrument',defaultValue='iris',validator=StringListValidator(['irs','iris','osi','osiris']), doc='Instrument') + self.declareProperty(name='Analyser',defaultValue='graphite002',validator=StringListValidator(['graphite002','graphite004']), doc='Analyser & reflection') + self.declareProperty(name='SamNumber',defaultValue='',validator=StringMandatoryValidator(), doc='Sample run number') + self.declareProperty(name='Xcut',defaultValue='',validator=StringMandatoryValidator(), doc='X cutoff value') + self.declareProperty('Verbose',defaultValue=True, doc='Switch Verbose Off/On') + self.declareProperty('Plot',defaultValue=True, doc='Switch Plot Off/On') + self.declareProperty('Save',defaultValue=False, doc='Switch Save result to nxs file Off/On') - def category(self): - return "Workflow\\MIDAS;PythonAlgorithms" - - def PyInit(self): - self.setOptionalMessage("Takes and asymmetric S(Q,w) and makes it symmetric") - self.setWikiSummary("Takes and asymmetric S(Q,w) and makes it symmetric") - - self.declareProperty(name='InputType',defaultValue='File',validator=StringListValidator(['File','Workspace']), doc='Origin of data input - File (_red.nxs) or Workspace') - self.declareProperty(name='Instrument',defaultValue='iris',validator=StringListValidator(['irs','iris','osi','osiris']), doc='Instrument') - self.declareProperty(name='Analyser',defaultValue='graphite002',validator=StringListValidator(['graphite002','graphite004']), doc='Analyser & reflection') - self.declareProperty(name='SamNumber',defaultValue='',validator=StringMandatoryValidator(), doc='Sample run number') - self.declareProperty(name='Xcut',defaultValue='',validator=StringMandatoryValidator(), doc='X cutoff value') - self.declareProperty('Verbose',defaultValue=True, doc='Switch Verbose Off/On') - self.declareProperty('Plot',defaultValue=True, doc='Switch Plot Off/On') - self.declareProperty('Save',defaultValue=False, doc='Switch Save result to nxs file Off/On') - - def PyExec(self): - - self.log().information('Symmetrise') - inType = self.getPropertyValue('InputType') - prefix = self.getPropertyValue('Instrument') - ana = self.getPropertyValue('Analyser') - sn = self.getPropertyValue('SamNumber') - sam = prefix+sn+'_'+ana+'_red' - cut = self.getPropertyValue('Xcut') - cut = float(cut) - - verbOp = self.getProperty('Verbose').value - plotOp = self.getProperty('Plot').value - saveOp = self.getProperty('Save').value - import IndirectSymm as Main - Main.SymmStart(inType,sam,cut,verbOp,plotOp,saveOp) + def PyExec(self): + + self.log().information('Symmetrise') + inType = self.getPropertyValue('InputType') + prefix = self.getPropertyValue('Instrument') + ana = self.getPropertyValue('Analyser') + sn = self.getPropertyValue('SamNumber') + sam = prefix+sn+'_'+ana+'_red' + cut = self.getPropertyValue('Xcut') + cut = float(cut) + + verbOp = self.getProperty('Verbose').value + plotOp = self.getProperty('Plot').value + saveOp = self.getProperty('Save').value + + self.SymmStart(inType,sam,cut,verbOp,plotOp,saveOp) + + + def SymmRun(self, sample,cut,Verbose,Plot,Save): + workdir = config['defaultsave.directory'] + symWS = sample[:-3] + 'sym' + hist,npt = CheckHistZero(sample) + Xin = mtd[sample].readX(0) + delx = Xin[1]-Xin[0] + if math.fabs(cut) < 1e-5: + error = 'Cut point is Zero' + logger.notice('ERROR *** ' + error) + sys.exit(error) + for n in range(0,npt): + x = Xin[n]-cut + if math.fabs(x) < delx: + ineg = n + if ineg <= 0: + error = 'Negative point('+str(ineg)+') < 0' + logger.notice('ERROR *** ' + error) + sys.exit(error) + if ineg >= npt: + error = type + 'Negative point('+str(ineg)+') > '+str(npt) + logger.notice('ERROR *** ' + error) + sys.exit(error) + for n in range(0,npt): + x = Xin[n]+Xin[ineg] + if math.fabs(x) < delx: + ipos = n + if ipos <= 0: + error = 'Positive point('+str(ipos)+') < 0' + logger.notice('ERROR *** ' + error) + sys.exit(error) + if ipos >= npt: + error = type + 'Positive point('+str(ipos)+') > '+str(npt) + logger.notice('ERROR *** ' + error) + sys.exit(error) + ncut = npt-ipos+1 + if Verbose: + logger.notice('No. points = '+str(npt)) + logger.notice('Negative : at i ='+str(ineg)+' ; x = '+str(Xin[ineg])) + logger.notice('Positive : at i ='+str(ipos)+' ; x = '+str(Xin[ipos])) + logger.notice('Copy points = '+str(ncut)) + for m in range(0,hist): + Xin = mtd[sample].readX(m) + Yin = mtd[sample].readY(m) + Ein = mtd[sample].readE(m) + Xout = [] + Yout = [] + Eout = [] + for n in range(0,ncut): + icut = npt-n-1 + Xout.append(-Xin[icut]) + Yout.append(Yin[icut]) + Eout.append(Ein[icut]) + for n in range(ncut,npt): + Xout.append(Xin[n]) + Yout.append(Yin[n]) + Eout.append(Ein[n]) + if m == 0: + CreateWorkspace(OutputWorkspace=symWS, DataX=Xout, DataY=Yout, DataE=Eout, + Nspec=1, UnitX='DeltaE') + else: + CreateWorkspace(OutputWorkspace='__tmp', DataX=Xout, DataY=Yout, DataE=Eout, + Nspec=1, UnitX='DeltaE') + ConjoinWorkspaces(InputWorkspace1=symWS, InputWorkspace2='__tmp',CheckOverlapping=False) + if Save: + path = os.path.join(workdir,symWS+'.nxs') + SaveNexusProcessed(InputWorkspace=symWS, Filename=path) + if Verbose: + logger.notice('Output file : ' + path) + if Plot: + self.plotSymm(symWS,sample) + + def SymmStart(self, inType,sname,cut,Verbose,Plot,Save): + from IndirectCommon import CheckHistZero, StartTime, EndTime, getDefaultWorkingDirectory + from IndirectImport import import_mantidplot + + StartTime('Symmetrise') + workdir = config['defaultsave.directory'] + if inType == 'File': + spath = os.path.join(workdir, sname+'.nxs') # path name for sample nxs file + LoadNexusProcessed(FileName=spath, OutputWorkspace=sname) + message = 'Input from File : '+spath + else: + message = 'Input from Workspace : '+sname + if Verbose: + logger.notice(message) + self.SymmRun(sname,cut,Verbose,Plot,Save) + EndTime('Symmetrise') + + def plotSymm(self, sym,sample): + mp = import_mantidplot() + tot_plot=mp.plotSpectrum([sym,sample],0) AlgorithmFactory.subscribe(Symmetrise) # Register algorithm with Mantid From bf80fa0ce81733b929af4f7d303c1e455f2832e3 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 11:15:37 +0100 Subject: [PATCH 02/46] Refs #7860 Modify algorithm to just take a workspace as input. Also do some light refactoring at the same time. --- .../WorkflowAlgorithms/Symmetrise.py | 164 +++++++++--------- 1 file changed, 85 insertions(+), 79 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 29d93d5701bd..902d58eed6d4 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -1,13 +1,13 @@ """*WIKI* Symmetrise takes an asymmetric S(Q,w) - i.e. one in which the moduli of xmin & xmax are different. Typically xmax is > mod(xmin). -A negative value of x is chosen (Xcut) so that the curve for mod(Xcut) to xmax is reflected and inserted for x less than the Xcut. +A negative value of x is chosen (XCut) so that the curve for mod(XCut) to xmax is reflected and inserted for x less than the XCut. *WIKI*""" from mantid import config, logger, mtd -from mantid.api import PythonAlgorithm, AlgorithmFactory -from mantid.kernel import StringListValidator, StringMandatoryValidator +from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty +from mantid.kernel import StringListValidator, StringMandatoryValidator, Direction from mantid.simpleapi import * import sys, platform, math, os.path, numpy as np @@ -17,126 +17,132 @@ def category(self): return "Workflow\\MIDAS;PythonAlgorithms" def PyInit(self): - self.setOptionalMessage("Takes and asymmetric S(Q,w) and makes it symmetric") - self.setWikiSummary("Takes and asymmetric S(Q,w) and makes it symmetric") - - self.declareProperty(name='InputType',defaultValue='File',validator=StringListValidator(['File','Workspace']), doc='Origin of data input - File (_red.nxs) or Workspace') - self.declareProperty(name='Instrument',defaultValue='iris',validator=StringListValidator(['irs','iris','osi','osiris']), doc='Instrument') - self.declareProperty(name='Analyser',defaultValue='graphite002',validator=StringListValidator(['graphite002','graphite004']), doc='Analyser & reflection') - self.declareProperty(name='SamNumber',defaultValue='',validator=StringMandatoryValidator(), doc='Sample run number') - self.declareProperty(name='Xcut',defaultValue='',validator=StringMandatoryValidator(), doc='X cutoff value') - self.declareProperty('Verbose',defaultValue=True, doc='Switch Verbose Off/On') - self.declareProperty('Plot',defaultValue=True, doc='Switch Plot Off/On') - self.declareProperty('Save',defaultValue=False, doc='Switch Save result to nxs file Off/On') + self.setOptionalMessage("Takes an asymmetric S(Q,w) and makes it symmetric") + self.setWikiSummary("Takes an asymmetric S(Q,w) and makes it symmetric") + + self.declareProperty(WorkspaceProperty("Sample", "", Direction.Input), doc='Sample to run with') + self.declareProperty('XCut', 0.0, doc='X cut off value') + + self.declareProperty('Verbose',defaultValue=True, doc='Switch verbose output Off/On') + self.declareProperty('Plot',defaultValue=True, doc='Switch plotting Off/On') + self.declareProperty('Save',defaultValue=False, doc='Switch saving result to nxs file Off/On') + self.declareProperty(WorkspaceProperty("OutputWorkspace", "", Direction.Output), doc='Name to call the output workspace.') + def PyExec(self): + from IndirectCommon import CheckHistZero, StartTime, EndTime, getDefaultWorkingDirectory - self.log().information('Symmetrise') - inType = self.getPropertyValue('InputType') - prefix = self.getPropertyValue('Instrument') - ana = self.getPropertyValue('Analyser') - sn = self.getPropertyValue('SamNumber') - sam = prefix+sn+'_'+ana+'_red' - cut = self.getPropertyValue('Xcut') - cut = float(cut) - - verbOp = self.getProperty('Verbose').value - plotOp = self.getProperty('Plot').value - saveOp = self.getProperty('Save').value + StartTime('Symmetrise') + self._setup() + num_spectra, npt = CheckHistZero(self._sample) - self.SymmStart(inType,sam,cut,verbOp,plotOp,saveOp) + sample_x = mtd[self._sample].readX(0) + if math.fabs(self._x_cut) < 1e-5: + raise ValueError('XCut point is Zero') + + delta_x = sample_x[1]-sample_x[0] + # diff = np.absolute(sample_x - self._x_cut) + # ineg = np.where(diff < delta_x)[0] - def SymmRun(self, sample,cut,Verbose,Plot,Save): - workdir = config['defaultsave.directory'] - symWS = sample[:-3] + 'sym' - hist,npt = CheckHistZero(sample) - Xin = mtd[sample].readX(0) - delx = Xin[1]-Xin[0] - if math.fabs(cut) < 1e-5: - error = 'Cut point is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - for n in range(0,npt): - x = Xin[n]-cut - if math.fabs(x) < delx: + for n in range(npt): + x = sample_x[n]-self._x_cut + if math.fabs(x) < delta_x: ineg = n + if ineg <= 0: error = 'Negative point('+str(ineg)+') < 0' logger.notice('ERROR *** ' + error) sys.exit(error) + if ineg >= npt: error = type + 'Negative point('+str(ineg)+') > '+str(npt) logger.notice('ERROR *** ' + error) sys.exit(error) - for n in range(0,npt): - x = Xin[n]+Xin[ineg] - if math.fabs(x) < delx: + + for n in range(npt): + x = sample_x[n]+sample_x[ineg] + if math.fabs(x) < delta_x: ipos = n + if ipos <= 0: error = 'Positive point('+str(ipos)+') < 0' logger.notice('ERROR *** ' + error) sys.exit(error) + if ipos >= npt: error = type + 'Positive point('+str(ipos)+') > '+str(npt) logger.notice('ERROR *** ' + error) sys.exit(error) + ncut = npt-ipos+1 - if Verbose: + + if self._verbose: logger.notice('No. points = '+str(npt)) - logger.notice('Negative : at i ='+str(ineg)+' ; x = '+str(Xin[ineg])) - logger.notice('Positive : at i ='+str(ipos)+' ; x = '+str(Xin[ipos])) - logger.notice('Copy points = '+str(ncut)) - for m in range(0,hist): - Xin = mtd[sample].readX(m) - Yin = mtd[sample].readY(m) - Ein = mtd[sample].readE(m) + logger.notice('Negative : at i ='+str(ineg)+' ; x = '+str(sample_x[ineg])) + logger.notice('Positive : at i ='+str(ipos)+' ; x = '+str(sample_x[ipos])) + logger.notice('Copy points = '+str(xcut)) + + for m in range(num_spectra): + sample_x = mtd[self._sample].readX(m) + Yin = mtd[self._sample].readY(m) + Ein = mtd[self._sample].readE(m) Xout = [] Yout = [] Eout = [] for n in range(0,ncut): icut = npt-n-1 - Xout.append(-Xin[icut]) + Xout.append(-sample_x[icut]) Yout.append(Yin[icut]) Eout.append(Ein[icut]) for n in range(ncut,npt): - Xout.append(Xin[n]) + Xout.append(sample_x[n]) Yout.append(Yin[n]) Eout.append(Ein[n]) + if m == 0: - CreateWorkspace(OutputWorkspace=symWS, DataX=Xout, DataY=Yout, DataE=Eout, + CreateWorkspace(OutputWorkspace=self._output_workspace, DataX=Xout, DataY=Yout, DataE=Eout, Nspec=1, UnitX='DeltaE') else: CreateWorkspace(OutputWorkspace='__tmp', DataX=Xout, DataY=Yout, DataE=Eout, Nspec=1, UnitX='DeltaE') - ConjoinWorkspaces(InputWorkspace1=symWS, InputWorkspace2='__tmp',CheckOverlapping=False) - if Save: - path = os.path.join(workdir,symWS+'.nxs') - SaveNexusProcessed(InputWorkspace=symWS, Filename=path) - if Verbose: - logger.notice('Output file : ' + path) - if Plot: - self.plotSymm(symWS,sample) - - def SymmStart(self, inType,sname,cut,Verbose,Plot,Save): - from IndirectCommon import CheckHistZero, StartTime, EndTime, getDefaultWorkingDirectory - from IndirectImport import import_mantidplot + ConjoinWorkspaces(InputWorkspace1=self._output_workspace, InputWorkspace2='__tmp',CheckOverlapping=False) - StartTime('Symmetrise') - workdir = config['defaultsave.directory'] - if inType == 'File': - spath = os.path.join(workdir, sname+'.nxs') # path name for sample nxs file - LoadNexusProcessed(FileName=spath, OutputWorkspace=sname) - message = 'Input from File : '+spath - else: - message = 'Input from Workspace : '+sname - if Verbose: - logger.notice(message) - self.SymmRun(sname,cut,Verbose,Plot,Save) + + if self._save: + workdir = getDefaultWorkingDirectory() + file_path = os.path.join(workdir,self._output_workspace+'.nxs') + SaveNexusProcessed(InputWorkspace=self._output_workspace, Filename=file_path) + + if self._verbose: + logger.notice('Output file : ' + file_path) + + if self._plot: + self._plotSymmetrise() + + self.setProperty("OutputWorkspace", self._output_workspace) EndTime('Symmetrise') - def plotSymm(self, sym,sample): + + def _setup(self): + """ + Get the algorithm properties. + """ + self._sample = self.getPropertyValue('Sample') + self._x_cut = self.getProperty('XCut').value + + self._verbose = self.getProperty('Verbose').value + self._plot = self.getProperty('Plot').value + self._save = self.getProperty('Save').value + + self._output_workspace = self.getPropertyValue('OutputWorkspace') + + def _plotSymmetrise(self): + """ + Plot the first spectrum of the input and output workspace together + """ + from IndirectImport import import_mantidplot mp = import_mantidplot() - tot_plot=mp.plotSpectrum([sym,sample],0) + tot_plot = mp.plotSpectrum([self._output_workspace, self._sample],0) AlgorithmFactory.subscribe(Symmetrise) # Register algorithm with Mantid From 01ee9ecdc780c6023eb8715c89ddaf2f5d9cec35 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 13:23:28 +0100 Subject: [PATCH 03/46] Refs #7860 Refactor code with numpy and slicing. --- .../WorkflowAlgorithms/Symmetrise.py | 126 ++++++++---------- 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 902d58eed6d4..e5d862c173c9 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -5,11 +5,15 @@ *WIKI*""" -from mantid import config, logger, mtd +from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty -from mantid.kernel import StringListValidator, StringMandatoryValidator, Direction +from mantid.kernel import Direction from mantid.simpleapi import * -import sys, platform, math, os.path, numpy as np + +import math +import os.path +import numpy as np + class Symmetrise(PythonAlgorithm): @@ -35,80 +39,52 @@ def PyExec(self): StartTime('Symmetrise') self._setup() num_spectra, npt = CheckHistZero(self._sample) - sample_x = mtd[self._sample].readX(0) if math.fabs(self._x_cut) < 1e-5: raise ValueError('XCut point is Zero') delta_x = sample_x[1]-sample_x[0] - # diff = np.absolute(sample_x - self._x_cut) - # ineg = np.where(diff < delta_x)[0] - for n in range(npt): - x = sample_x[n]-self._x_cut - if math.fabs(x) < delta_x: - ineg = n - - if ineg <= 0: - error = 'Negative point('+str(ineg)+') < 0' - logger.notice('ERROR *** ' + error) - sys.exit(error) - - if ineg >= npt: - error = type + 'Negative point('+str(ineg)+') > '+str(npt) - logger.notice('ERROR *** ' + error) - sys.exit(error) - - for n in range(npt): - x = sample_x[n]+sample_x[ineg] - if math.fabs(x) < delta_x: - ipos = n - - if ipos <= 0: - error = 'Positive point('+str(ipos)+') < 0' - logger.notice('ERROR *** ' + error) - sys.exit(error) - - if ipos >= npt: - error = type + 'Positive point('+str(ipos)+') > '+str(npt) - logger.notice('ERROR *** ' + error) - sys.exit(error) - + negative_diff = np.absolute(sample_x - self._x_cut) + ineg = np.where(negative_diff < delta_x)[0][-1] + self._check_bounds(ineg, npt, label='Negative') + + positive_diff = np.absolute(sample_x + sample_x[ineg]) + ipos = np.where(positive_diff < delta_x)[0][-1] + self._check_bounds(ipos, npt, label='Positive') + ncut = npt-ipos+1 if self._verbose: - logger.notice('No. points = '+str(npt)) - logger.notice('Negative : at i ='+str(ineg)+' ; x = '+str(sample_x[ineg])) - logger.notice('Positive : at i ='+str(ipos)+' ; x = '+str(sample_x[ipos])) - logger.notice('Copy points = '+str(xcut)) + logger.notice('No. points = %d' % npt) + logger.notice('Negative : at i =%d; x = %f' % (ineg, sample_x[ineg])) + logger.notice('Positive : at i =%d; x = %f' % (ipos, sample_x[ipos])) + logger.notice('Copy points = %d' % ncut) - for m in range(num_spectra): - sample_x = mtd[self._sample].readX(m) - Yin = mtd[self._sample].readY(m) - Ein = mtd[self._sample].readE(m) - Xout = [] - Yout = [] - Eout = [] - for n in range(0,ncut): - icut = npt-n-1 - Xout.append(-sample_x[icut]) - Yout.append(Yin[icut]) - Eout.append(Ein[icut]) - for n in range(ncut,npt): - Xout.append(sample_x[n]) - Yout.append(Yin[n]) - Eout.append(Ein[n]) - - if m == 0: - CreateWorkspace(OutputWorkspace=self._output_workspace, DataX=Xout, DataY=Yout, DataE=Eout, - Nspec=1, UnitX='DeltaE') - else: - CreateWorkspace(OutputWorkspace='__tmp', DataX=Xout, DataY=Yout, DataE=Eout, - Nspec=1, UnitX='DeltaE') - ConjoinWorkspaces(InputWorkspace1=self._output_workspace, InputWorkspace2='__tmp',CheckOverlapping=False) + CloneWorkspace(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + for m in xrange(num_spectra): + x = mtd[self._sample].readX(m) + y = mtd[self._output_workspace].readY(m) + e = mtd[self._output_workspace].readE(m) + + x_out = np.zeros(x.size) + y_out = np.zeros(y.size) + e_out = np.zeros(e.size) + + x_out[:ncut] = -x[npt:npt-ncut:-1] + y_out[:ncut] = y[npt:npt-ncut-1:-1] + e_out[:ncut] = e[npt:npt-ncut-1:-1] + x_out[ncut:] = x[ncut:] + y_out[ncut:] = y[ncut:] + e_out[ncut:] = e[ncut:] + + mtd[self._output_workspace].setX(m, np.asarray(x_out)) + mtd[self._output_workspace].setY(m, np.asarray(y_out)) + mtd[self._output_workspace].setE(m, np.asarray(e_out)) + if self._save: workdir = getDefaultWorkingDirectory() file_path = os.path.join(workdir,self._output_workspace+'.nxs') @@ -123,7 +99,6 @@ def PyExec(self): self.setProperty("OutputWorkspace", self._output_workspace) EndTime('Symmetrise') - def _setup(self): """ Get the algorithm properties. @@ -135,7 +110,21 @@ def _setup(self): self._plot = self.getProperty('Plot').value self._save = self.getProperty('Save').value - self._output_workspace = self.getPropertyValue('OutputWorkspace') + self._output_workspace = self.getPropertyValue('OutputWorkspace') + + def _check_bounds(self, index, num_pts, label=''): + """ + Check if the index falls within the bounds of the x range. + Throws a ValueError if the x point falls outside of the range. + + @param index - value of the index within the x range. + @param num_pts - total number of points in the range. + @param label - label to call the point if an error is thrown. + """ + if index <= 0: + raise ValueError('%s point %d < 0' % (label, index)) + elif index >= num_pts: + raise ValueError('%s point %d > %d' % (label, index, num_pts)) def _plotSymmetrise(self): """ @@ -143,6 +132,7 @@ def _plotSymmetrise(self): """ from IndirectImport import import_mantidplot mp = import_mantidplot() - tot_plot = mp.plotSpectrum([self._output_workspace, self._sample],0) + mp.plotSpectrum([self._output_workspace, self._sample],0) -AlgorithmFactory.subscribe(Symmetrise) # Register algorithm with Mantid +# Register algorithm with Mantid +AlgorithmFactory.subscribe(Symmetrise) From 47061039e6ec11c3e0bed5f7b15907673aac48e2 Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 13:44:16 +0100 Subject: [PATCH 04/46] Refs #7860 Fix PEP8 warnings. --- .../WorkflowAlgorithms/Symmetrise.py | 253 +++++++++--------- 1 file changed, 132 insertions(+), 121 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index e5d862c173c9..0e38deff58ee 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -1,14 +1,15 @@ -"""*WIKI* - -Symmetrise takes an asymmetric S(Q,w) - i.e. one in which the moduli of xmin & xmax are different. Typically xmax is > mod(xmin). -A negative value of x is chosen (XCut) so that the curve for mod(XCut) to xmax is reflected and inserted for x less than the XCut. +"""*WIKI* +Symmetrise takes an asymmetric S(Q,w) - i.e. one in which the +moduli of xmin & xmax are different. Typically xmax is > mod(xmin). +A negative value of x is chosen (XCut) so that the curve for mod(XCut) to xmax +is reflected and inserted for x less than the XCut. *WIKI*""" from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty from mantid.kernel import Direction -from mantid.simpleapi import * +from mantid.simpleapi import CloneWorkspace, SaveNexusProcessed import math import os.path @@ -17,122 +18,132 @@ class Symmetrise(PythonAlgorithm): - def category(self): - return "Workflow\\MIDAS;PythonAlgorithms" - - def PyInit(self): - self.setOptionalMessage("Takes an asymmetric S(Q,w) and makes it symmetric") - self.setWikiSummary("Takes an asymmetric S(Q,w) and makes it symmetric") - - self.declareProperty(WorkspaceProperty("Sample", "", Direction.Input), doc='Sample to run with') - self.declareProperty('XCut', 0.0, doc='X cut off value') - - self.declareProperty('Verbose',defaultValue=True, doc='Switch verbose output Off/On') - self.declareProperty('Plot',defaultValue=True, doc='Switch plotting Off/On') - self.declareProperty('Save',defaultValue=False, doc='Switch saving result to nxs file Off/On') - - self.declareProperty(WorkspaceProperty("OutputWorkspace", "", Direction.Output), doc='Name to call the output workspace.') - - def PyExec(self): - from IndirectCommon import CheckHistZero, StartTime, EndTime, getDefaultWorkingDirectory - - StartTime('Symmetrise') - self._setup() - num_spectra, npt = CheckHistZero(self._sample) - sample_x = mtd[self._sample].readX(0) - - if math.fabs(self._x_cut) < 1e-5: - raise ValueError('XCut point is Zero') - - delta_x = sample_x[1]-sample_x[0] - - negative_diff = np.absolute(sample_x - self._x_cut) - ineg = np.where(negative_diff < delta_x)[0][-1] - self._check_bounds(ineg, npt, label='Negative') - - positive_diff = np.absolute(sample_x + sample_x[ineg]) - ipos = np.where(positive_diff < delta_x)[0][-1] - self._check_bounds(ipos, npt, label='Positive') - - ncut = npt-ipos+1 - - if self._verbose: - logger.notice('No. points = %d' % npt) - logger.notice('Negative : at i =%d; x = %f' % (ineg, sample_x[ineg])) - logger.notice('Positive : at i =%d; x = %f' % (ipos, sample_x[ipos])) - logger.notice('Copy points = %d' % ncut) - - CloneWorkspace(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - - for m in xrange(num_spectra): - x = mtd[self._sample].readX(m) - y = mtd[self._output_workspace].readY(m) - e = mtd[self._output_workspace].readE(m) - - x_out = np.zeros(x.size) - y_out = np.zeros(y.size) - e_out = np.zeros(e.size) - - x_out[:ncut] = -x[npt:npt-ncut:-1] - y_out[:ncut] = y[npt:npt-ncut-1:-1] - e_out[:ncut] = e[npt:npt-ncut-1:-1] - - x_out[ncut:] = x[ncut:] - y_out[ncut:] = y[ncut:] - e_out[ncut:] = e[ncut:] - - mtd[self._output_workspace].setX(m, np.asarray(x_out)) - mtd[self._output_workspace].setY(m, np.asarray(y_out)) - mtd[self._output_workspace].setE(m, np.asarray(e_out)) - - if self._save: - workdir = getDefaultWorkingDirectory() - file_path = os.path.join(workdir,self._output_workspace+'.nxs') - SaveNexusProcessed(InputWorkspace=self._output_workspace, Filename=file_path) - - if self._verbose: - logger.notice('Output file : ' + file_path) - - if self._plot: - self._plotSymmetrise() - - self.setProperty("OutputWorkspace", self._output_workspace) - EndTime('Symmetrise') - - def _setup(self): - """ - Get the algorithm properties. - """ - self._sample = self.getPropertyValue('Sample') - self._x_cut = self.getProperty('XCut').value - - self._verbose = self.getProperty('Verbose').value - self._plot = self.getProperty('Plot').value - self._save = self.getProperty('Save').value - - self._output_workspace = self.getPropertyValue('OutputWorkspace') - - def _check_bounds(self, index, num_pts, label=''): - """ - Check if the index falls within the bounds of the x range. - Throws a ValueError if the x point falls outside of the range. - - @param index - value of the index within the x range. - @param num_pts - total number of points in the range. - @param label - label to call the point if an error is thrown. - """ - if index <= 0: - raise ValueError('%s point %d < 0' % (label, index)) - elif index >= num_pts: - raise ValueError('%s point %d > %d' % (label, index, num_pts)) - - def _plotSymmetrise(self): - """ - Plot the first spectrum of the input and output workspace together - """ - from IndirectImport import import_mantidplot - mp = import_mantidplot() - mp.plotSpectrum([self._output_workspace, self._sample],0) + def category(self): + return "Workflow\\MIDAS;PythonAlgorithms" + + def PyInit(self): + self.setOptionalMessage("Takes an asymmetric S(Q,w) and makes it symmetric") + self.setWikiSummary("Takes an asymmetric S(Q,w) and makes it symmetric") + + self.declareProperty(WorkspaceProperty("Sample", "", Direction.Input), + doc='Sample to run with') + self.declareProperty('XCut', 0.0, doc='X cut off value') + + self.declareProperty('Verbose', defaultValue=True, + doc='Switch verbose output Off/On') + self.declareProperty('Plot', defaultValue=True, + doc='Switch plotting Off/On') + self.declareProperty('Save', defaultValue=False, + doc='Switch saving result to nxs file Off/On') + + self.declareProperty(WorkspaceProperty("OutputWorkspace", "", + Direction.Output), doc='Name to call the output workspace.') + + def PyExec(self): + from IndirectCommon import CheckHistZero, StartTime, EndTime, \ + getDefaultWorkingDirectory + + StartTime('Symmetrise') + self._setup() + num_spectra, num_pts = CheckHistZero(self._sample) + sample_x = mtd[self._sample].readX(0) + + if math.fabs(self._x_cut) < 1e-5: + raise ValueError('XCut point is Zero') + + delta_x = sample_x[1] - sample_x[0] + + negative_diff = np.absolute(sample_x - self._x_cut) + negative_index = np.where(negative_diff < delta_x)[0][-1] + self._check_bounds(negative_index, num_pts, label='Negative') + + positive_diff = np.absolute(sample_x + sample_x[negative_index]) + positive_index = np.where(positive_diff < delta_x)[0][-1] + self._check_bounds(positive_index, num_pts, label='Positive') + + pivot = num_pts - positive_index + 1 + + if self._verbose: + logger.notice('No. points = %d' % num_pts) + logger.notice('Negative : at i =%d; x = %f' + % (negative_index, sample_x[negative_index])) + logger.notice('Positive : at i =%d; x = %f' + % (positive_index, sample_x[positive_index])) + logger.notice('Copy points = %d' % pivot) + + CloneWorkspace(InputWorkspace=self._sample, + OutputWorkspace=self._output_workspace) + + for index in xrange(num_spectra): + x = mtd[self._output_workspace].readX(index) + y = mtd[self._output_workspace].readY(index) + e = mtd[self._output_workspace].readE(index) + + x_out = np.zeros(x.size) + y_out = np.zeros(y.size) + e_out = np.zeros(e.size) + + x_out[:pivot] = -x[num_pts:num_pts - pivot:-1] + y_out[:pivot] = y[num_pts:num_pts - pivot - 1:-1] + e_out[:pivot] = e[num_pts:num_pts - pivot - 1:-1] + + x_out[pivot:] = x[pivot:] + y_out[pivot:] = y[pivot:] + e_out[pivot:] = e[pivot:] + + mtd[self._output_workspace].setX(index, np.asarray(x_out)) + mtd[self._output_workspace].setY(index, np.asarray(y_out)) + mtd[self._output_workspace].setE(index, np.asarray(e_out)) + + if self._save: + workdir = getDefaultWorkingDirectory() + file_path = os.path.join(workdir, self._output_workspace + '.nxs') + SaveNexusProcessed(InputWorkspace=self._output_workspace, + Filename=file_path) + + if self._verbose: + logger.notice('Output file : ' + file_path) + + if self._plot: + self._plotSymmetrise() + + self.setProperty("OutputWorkspace", self._output_workspace) + EndTime('Symmetrise') + + def _setup(self): + """ + Get the algorithm properties. + """ + self._sample = self.getPropertyValue('Sample') + self._x_cut = self.getProperty('XCut').value + + self._verbose = self.getProperty('Verbose').value + self._plot = self.getProperty('Plot').value + self._save = self.getProperty('Save').value + + self._output_workspace = self.getPropertyValue('OutputWorkspace') + + def _check_bounds(self, index, num_pts, label=''): + """ + Check if the index falls within the bounds of the x range. + Throws a ValueError if the x point falls outside of the range. + + @param index - value of the index within the x range. + @param num_pts - total number of points in the range. + @param label - label to call the point if an error is thrown. + """ + if index <= 0: + raise ValueError('%s point %d < 0' % (label, index)) + elif index >= num_pts: + raise ValueError('%s point %d > %d' % (label, index, num_pts)) + + def _plotSymmetrise(self): + """ + Plot the first spectrum of the input and output workspace together. + """ + from IndirectImport import import_mantidplot + mp = import_mantidplot() + mp.plotSpectrum([self._output_workspace, self._sample], 0) # Register algorithm with Mantid AlgorithmFactory.subscribe(Symmetrise) From 71e15db31477226793585e2bbc207fb1d23f73bb Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 14:50:53 +0100 Subject: [PATCH 05/46] Refs #7860 Further refactoring --- .../WorkflowAlgorithms/Symmetrise.py | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 0e38deff58ee..9d16bb3b90a8 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -40,8 +40,7 @@ def PyInit(self): Direction.Output), doc='Name to call the output workspace.') def PyExec(self): - from IndirectCommon import CheckHistZero, StartTime, EndTime, \ - getDefaultWorkingDirectory + from IndirectCommon import CheckHistZero, StartTime, EndTime StartTime('Symmetrise') self._setup() @@ -51,6 +50,7 @@ def PyExec(self): if math.fabs(self._x_cut) < 1e-5: raise ValueError('XCut point is Zero') + #find range of values to flip delta_x = sample_x[1] - sample_x[0] negative_diff = np.absolute(sample_x - self._x_cut) @@ -74,6 +74,7 @@ def PyExec(self): CloneWorkspace(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + #for each spectrum copy positive values to the negative for index in xrange(num_spectra): x = mtd[self._output_workspace].readX(index) y = mtd[self._output_workspace].readY(index) @@ -91,21 +92,15 @@ def PyExec(self): y_out[pivot:] = y[pivot:] e_out[pivot:] = e[pivot:] - mtd[self._output_workspace].setX(index, np.asarray(x_out)) - mtd[self._output_workspace].setY(index, np.asarray(y_out)) - mtd[self._output_workspace].setE(index, np.asarray(e_out)) + mtd[self._output_workspace].setX(index, x_out) + mtd[self._output_workspace].setY(index, y_out) + mtd[self._output_workspace].setE(index, e_out) if self._save: - workdir = getDefaultWorkingDirectory() - file_path = os.path.join(workdir, self._output_workspace + '.nxs') - SaveNexusProcessed(InputWorkspace=self._output_workspace, - Filename=file_path) - - if self._verbose: - logger.notice('Output file : ' + file_path) + self._save_output() if self._plot: - self._plotSymmetrise() + self._plot_output() self.setProperty("OutputWorkspace", self._output_workspace) EndTime('Symmetrise') @@ -137,7 +132,20 @@ def _check_bounds(self, index, num_pts, label=''): elif index >= num_pts: raise ValueError('%s point %d > %d' % (label, index, num_pts)) - def _plotSymmetrise(self): + def _save_output(self): + """ + Save the output workspace to the user's default working directory + """ + from IndirectCommon import getDefaultWorkingDirectory + workdir = getDefaultWorkingDirectory() + file_path = os.path.join(workdir, self._output_workspace + '.nxs') + SaveNexusProcessed(InputWorkspace=self._output_workspace, + Filename=file_path) + + if self._verbose: + logger.notice('Output file : ' + file_path) + + def _plot_output(self): """ Plot the first spectrum of the input and output workspace together. """ From 19b887b9004748785eaeef475ab4bf7bdade109c Mon Sep 17 00:00:00 2001 From: Samuel Jackson Date: Mon, 14 Apr 2014 14:52:15 +0100 Subject: [PATCH 06/46] Refs #7860 Remove redundant code from project. --- Code/Mantid/scripts/Inelastic/IndirectSymm.py | 98 ------------------- 1 file changed, 98 deletions(-) delete mode 100644 Code/Mantid/scripts/Inelastic/IndirectSymm.py diff --git a/Code/Mantid/scripts/Inelastic/IndirectSymm.py b/Code/Mantid/scripts/Inelastic/IndirectSymm.py deleted file mode 100644 index d22e7da68771..000000000000 --- a/Code/Mantid/scripts/Inelastic/IndirectSymm.py +++ /dev/null @@ -1,98 +0,0 @@ -# SYMMetrise -# -from mantid.simpleapi import * -from mantid import config, logger, mtd -from IndirectCommon import * -from IndirectImport import import_mantidplot -import sys, platform, math, os.path, numpy as np -mp = import_mantidplot() - -def SymmRun(sample,cut,Verbose,Plot,Save): - workdir = config['defaultsave.directory'] - symWS = sample[:-3] + 'sym' - hist,npt = CheckHistZero(sample) - Xin = mtd[sample].readX(0) - delx = Xin[1]-Xin[0] - if math.fabs(cut) < 1e-5: - error = 'Cut point is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - for n in range(0,npt): - x = Xin[n]-cut - if math.fabs(x) < delx: - ineg = n - if ineg <= 0: - error = 'Negative point('+str(ineg)+') < 0' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if ineg >= npt: - error = type + 'Negative point('+str(ineg)+') > '+str(npt) - logger.notice('ERROR *** ' + error) - sys.exit(error) - for n in range(0,npt): - x = Xin[n]+Xin[ineg] - if math.fabs(x) < delx: - ipos = n - if ipos <= 0: - error = 'Positive point('+str(ipos)+') < 0' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if ipos >= npt: - error = type + 'Positive point('+str(ipos)+') > '+str(npt) - logger.notice('ERROR *** ' + error) - sys.exit(error) - ncut = npt-ipos+1 - if Verbose: - logger.notice('No. points = '+str(npt)) - logger.notice('Negative : at i ='+str(ineg)+' ; x = '+str(Xin[ineg])) - logger.notice('Positive : at i ='+str(ipos)+' ; x = '+str(Xin[ipos])) - logger.notice('Copy points = '+str(ncut)) - for m in range(0,hist): - Xin = mtd[sample].readX(m) - Yin = mtd[sample].readY(m) - Ein = mtd[sample].readE(m) - Xout = [] - Yout = [] - Eout = [] - for n in range(0,ncut): - icut = npt-n-1 - Xout.append(-Xin[icut]) - Yout.append(Yin[icut]) - Eout.append(Ein[icut]) - for n in range(ncut,npt): - Xout.append(Xin[n]) - Yout.append(Yin[n]) - Eout.append(Ein[n]) - if m == 0: - CreateWorkspace(OutputWorkspace=symWS, DataX=Xout, DataY=Yout, DataE=Eout, - Nspec=1, UnitX='DeltaE') - else: - CreateWorkspace(OutputWorkspace='__tmp', DataX=Xout, DataY=Yout, DataE=Eout, - Nspec=1, UnitX='DeltaE') - ConjoinWorkspaces(InputWorkspace1=symWS, InputWorkspace2='__tmp',CheckOverlapping=False) -# Nspec=nt, UnitX='MomentumTransfer', VerticalAxisUnit='Text', VerticalAxisValues='Taxis') -# start output - if Save: - path = os.path.join(workdir,symWS+'.nxs') - SaveNexusProcessed(InputWorkspace=symWS, Filename=path) - if Verbose: - logger.notice('Output file : ' + path) - if Plot: - plotSymm(symWS,sample) - -def SymmStart(inType,sname,cut,Verbose,Plot,Save): - StartTime('Symmetrise') - workdir = config['defaultsave.directory'] - if inType == 'File': - spath = os.path.join(workdir, sname+'.nxs') # path name for sample nxs file - LoadNexusProcessed(FileName=spath, OutputWorkspace=sname) - message = 'Input from File : '+spath - else: - message = 'Input from Workspace : '+sname - if Verbose: - logger.notice(message) - SymmRun(sname,cut,Verbose,Plot,Save) - EndTime('Symmetrise') - -def plotSymm(sym,sample): - tot_plot=mp.plotSpectrum([sym,sample],0) From 95b576f94a3d0bf4834ebef1cfbd3fea11e1ef82 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 19 Aug 2014 12:18:27 +0100 Subject: [PATCH 07/46] Remove WIKI header from Symmetrise.py Refs #7860 --- .../plugins/algorithms/WorkflowAlgorithms/Symmetrise.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 9d16bb3b90a8..722432d7e584 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -1,11 +1,3 @@ -"""*WIKI* -Symmetrise takes an asymmetric S(Q,w) - i.e. one in which the -moduli of xmin & xmax are different. Typically xmax is > mod(xmin). - -A negative value of x is chosen (XCut) so that the curve for mod(XCut) to xmax -is reflected and inserted for x less than the XCut. -*WIKI*""" - from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty from mantid.kernel import Direction From d4290a1a8f366529b58d8f295a6cf6a5d43f4292 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 19 Aug 2014 17:00:06 +0100 Subject: [PATCH 08/46] Initial addition of Symmetrise tab Refs #7860 --- .../WorkflowAlgorithms/Symmetrise.py | 6 +- .../MantidQt/CustomInterfaces/CMakeLists.txt | 31 ++-- .../IndirectDataReduction.h | 1 + .../IndirectDataReduction.ui | 138 ++++++++++++++++-- .../IndirectSymmetrise.h | 76 ++++++++++ .../src/IndirectDataReduction.cpp | 16 +- .../src/IndirectSymmetrise.cpp | 96 ++++++++++++ 7 files changed, 332 insertions(+), 32 deletions(-) create mode 100644 Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h create mode 100644 Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index 722432d7e584..a7874877fb8c 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -13,10 +13,10 @@ class Symmetrise(PythonAlgorithm): def category(self): return "Workflow\\MIDAS;PythonAlgorithms" - def PyInit(self): - self.setOptionalMessage("Takes an asymmetric S(Q,w) and makes it symmetric") - self.setWikiSummary("Takes an asymmetric S(Q,w) and makes it symmetric") + def summary(self): + return "Takes an asymmetric S(Q,w) and makes it symmetric" + def PyInit(self): self.declareProperty(WorkspaceProperty("Sample", "", Direction.Input), doc='Sample to run with') self.declareProperty('XCut', 0.0, doc='X cut off value') diff --git a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt index 8bfa3c243c24..8907caa89dc3 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt +++ b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt @@ -4,7 +4,7 @@ set ( SRC_FILES src/ConvFit.cpp src/CreateMDWorkspace.cpp src/CreateMDWorkspaceAlgDialog.cpp - src/DirectConvertToEnergy.cpp + src/DirectConvertToEnergy.cpp src/Elwin.cpp src/EventNexusFileMemento.cpp src/Fury.cpp @@ -13,12 +13,12 @@ set ( SRC_FILES src/IDATab.cpp src/IndirectBayes.cpp src/IndirectBayesTab.cpp - src/IndirectCalibration.cpp - src/IndirectConvertToEnergy.cpp + src/IndirectCalibration.cpp + src/IndirectConvertToEnergy.cpp src/IndirectDataAnalysis.cpp - src/IndirectDataReduction.cpp - src/IndirectDataReductionTab.cpp - src/IndirectDiagnostics.cpp + src/IndirectDataReduction.cpp + src/IndirectDataReductionTab.cpp + src/IndirectDiagnostics.cpp src/IndirectDiffractionReduction.cpp src/IndirectLoadAscii.cpp src/IndirectLoadAsciiTab.cpp @@ -27,8 +27,9 @@ set ( SRC_FILES src/IndirectNeutron.cpp src/IndirectSimulation.cpp src/IndirectSimulationTab.cpp - src/IndirectSqw.cpp - src/IndirectTransmission.cpp + src/IndirectSqw.cpp + src/IndirectSymmetrise.cpp + src/IndirectTransmission.cpp src/JumpFit.cpp src/MSDFit.cpp src/MantidEV.cpp @@ -75,7 +76,7 @@ set ( INC_FILES inc/MantidQtCustomInterfaces/ConvFit.h inc/MantidQtCustomInterfaces/CreateMDWorkspace.h inc/MantidQtCustomInterfaces/CreateMDWorkspaceAlgDialog.h - inc/MantidQtCustomInterfaces/DirectConvertToEnergy.h + inc/MantidQtCustomInterfaces/DirectConvertToEnergy.h inc/MantidQtCustomInterfaces/DllConfig.h inc/MantidQtCustomInterfaces/Elwin.h inc/MantidQtCustomInterfaces/EventNexusFileMemento.h @@ -85,11 +86,11 @@ set ( INC_FILES inc/MantidQtCustomInterfaces/IDATab.h inc/MantidQtCustomInterfaces/IndirectBayes.h inc/MantidQtCustomInterfaces/IndirectBayesTab.h - inc/MantidQtCustomInterfaces/IndirectCalibration.h - inc/MantidQtCustomInterfaces/IndirectConvertToEnergy.h + inc/MantidQtCustomInterfaces/IndirectCalibration.h + inc/MantidQtCustomInterfaces/IndirectConvertToEnergy.h inc/MantidQtCustomInterfaces/IndirectDataAnalysis.h - inc/MantidQtCustomInterfaces/IndirectDataReduction.h - inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h + inc/MantidQtCustomInterfaces/IndirectDataReduction.h + inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h inc/MantidQtCustomInterfaces/IndirectDiagnostics.h inc/MantidQtCustomInterfaces/IndirectDiffractionReduction.h inc/MantidQtCustomInterfaces/IndirectLoadAscii.h @@ -100,7 +101,8 @@ set ( INC_FILES inc/MantidQtCustomInterfaces/IndirectSimulation.h inc/MantidQtCustomInterfaces/IndirectSimulationTab.h inc/MantidQtCustomInterfaces/IndirectSqw.h - inc/MantidQtCustomInterfaces/IndirectTransmission.h + inc/MantidQtCustomInterfaces/IndirectSymmetrise.h + inc/MantidQtCustomInterfaces/IndirectTransmission.h inc/MantidQtCustomInterfaces/JumpFit.h inc/MantidQtCustomInterfaces/MSDFit.h inc/MantidQtCustomInterfaces/MantidEV.h @@ -175,6 +177,7 @@ set ( MOC_FILES inc/MantidQtCustomInterfaces/Background.h inc/MantidQtCustomInterfaces/IndirectSimulation.h inc/MantidQtCustomInterfaces/IndirectSimulationTab.h inc/MantidQtCustomInterfaces/IndirectSqw.h + inc/MantidQtCustomInterfaces/IndirectSymmetrise.h inc/MantidQtCustomInterfaces/IndirectTransmission.h inc/MantidQtCustomInterfaces/JumpFit.h inc/MantidQtCustomInterfaces/MSDFit.h diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.h index 3806e24b16f9..53514feebbbb 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.h @@ -113,6 +113,7 @@ namespace MantidQt IndirectDataReductionTab* m_tab_calibration; IndirectDataReductionTab* m_tab_trans; IndirectDataReductionTab* m_tab_moments; + IndirectDataReductionTab* m_tab_symmetrise; Poco::NObserver m_changeObserver; ///< Poco observer for changes in user directory settings QString m_dataDir; ///< default data search directory diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui index 36818279961e..f747e684f5e0 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui @@ -6,7 +6,7 @@ 0 0 - 621 + 672 761 @@ -1513,16 +1513,12 @@ Later steps in the process (saving, renaming) will not be done. Time Slice - + - - - - - - - - + + + + @@ -1739,6 +1735,128 @@ Later steps in the process (saving, renaming) will not be done. + + + Symmetrise + + + + + + Input + + + + + + + 0 + 0 + + + + false + + + + + + + + + + Symmetrise + + + + 6 + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Output + + + + 6 + + + + + true + + + Verbose + + + + + + + Qt::Horizontal + + + + 165 + 20 + + + + + + + + Plot Result + + + + + + + Qt::Horizontal + + + + 164 + 20 + + + + + + + + Save Result + + + + + + + + S(Q, w) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h new file mode 100644 index 000000000000..8ca2db7e1540 --- /dev/null +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -0,0 +1,76 @@ +#ifndef MANTIDQTCUSTOMINTERFACES_INDIRECTSYMMETRISE_H_ +#define MANTIDQTCUSTOMINTERFACES_INDIRECTSYMMETRISE_H_ + +#include "MantidQtCustomInterfaces/IndirectDataReductionTab.h" + +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidKernel/System.h" + +// Suppress a warning coming out of code that isn't ours +#if defined(__INTEL_COMPILER) + #pragma warning disable 1125 +#elif defined(__GNUC__) + #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6 ) + #pragma GCC diagnostic push + #endif + #pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif +#include +#if defined(__INTEL_COMPILER) + #pragma warning enable 1125 +#elif defined(__GNUC__) + #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6 ) + #pragma GCC diagnostic pop + #endif +#endif + +namespace MantidQt +{ +namespace CustomInterfaces +{ + /** IndirectSymmetrise + + @author Dan Nixon + @date 23/07/2014 + + 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 IndirectSymmetrise : public IndirectDataReductionTab + { + Q_OBJECT + + public: + IndirectSymmetrise(Ui::IndirectDataReduction& uiForm, QWidget * parent = 0); + virtual ~IndirectSymmetrise(); + + virtual void setup(); + virtual void run(); + virtual bool validate(); + + private slots: + void plotRawInput(); + void updateRangeSelector(QtProperty *prop, double value); + + }; +} // namespace CustomInterfaces +} // namespace Mantid + +#endif //MANTIDQTCUSTOMINTERFACES_INDIRECTSYMMETRISE_H_ diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReduction.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReduction.cpp index 4f2fe9195e69..bcbd8721f4a3 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReduction.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReduction.cpp @@ -13,6 +13,7 @@ #include "MantidQtCustomInterfaces/IndirectDiagnostics.h" #include "MantidQtCustomInterfaces/IndirectMoments.h" #include "MantidQtCustomInterfaces/IndirectSqw.h" +#include "MantidQtCustomInterfaces/IndirectSymmetrise.h" #include "MantidQtCustomInterfaces/IndirectTransmission.h" #include @@ -105,6 +106,8 @@ void IndirectDataReduction::runClicked() m_tab_diagnostics->runTab(); else if ( tabName == "S(Q, w)" ) m_tab_sqw->runTab(); + else if ( tabName == "Symmetrise" ) + m_tab_symmetrise->runTab(); else if (tabName == "Transmission") m_tab_trans->runTab(); else if(tabName == "Moments") @@ -124,6 +127,7 @@ void IndirectDataReduction::initLayout() m_tab_calibration = new IndirectCalibration(m_uiForm, this); m_tab_trans = new IndirectTransmission(m_uiForm, this); m_tab_moments = new IndirectMoments(m_uiForm, this); + m_tab_symmetrise = new IndirectSymmetrise(m_uiForm, this); // Assume we get a incompatiable instrument to start with m_uiForm.pbRun->setEnabled(false); @@ -133,14 +137,14 @@ void IndirectDataReduction::initLayout() // signal/slot connections to respond to changes in instrument selection combo boxes connect(m_uiForm.cbInst, SIGNAL(instrumentSelectionChanged(const QString&)), this, SLOT(userSelectInstrument(const QString&))); - // connect "?" (Help) Button + // Connect "?" (Help) Button connect(m_uiForm.pbHelp, SIGNAL(clicked()), this, SLOT(helpClicked())); - // connect the "Run" button + // Connect the "Run" button connect(m_uiForm.pbRun, SIGNAL(clicked()), this, SLOT(runClicked())); - // connect the "Manage User Directories" Button + // Connect the "Manage User Directories" Button connect(m_uiForm.pbManageDirectories, SIGNAL(clicked()), this, SLOT(openDirectoryDialog())); - // ignals for tabs running Python + // Signals for tabs running Python connect(m_tab_convert_to_energy, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); connect(m_tab_sqw, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); connect(m_tab_calibration, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); @@ -148,13 +152,14 @@ void IndirectDataReduction::initLayout() connect(m_tab_trans, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); connect(m_tab_moments, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); - // ignals for tabs showing mesage boxes + // Signals for tabs showing mesage boxes connect(m_tab_convert_to_energy, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); connect(m_tab_sqw, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); connect(m_tab_calibration, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); connect(m_tab_diagnostics, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); connect(m_tab_trans, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); connect(m_tab_moments, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); + connect(m_tab_symmetrise, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); // Run any tab setup code m_tab_convert_to_energy->setupTab(); @@ -163,6 +168,7 @@ void IndirectDataReduction::initLayout() m_tab_calibration->setupTab(); m_tab_trans->setupTab(); m_tab_moments->setupTab(); + m_tab_symmetrise->setupTab(); } /** diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp new file mode 100644 index 000000000000..99750711a15d --- /dev/null +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -0,0 +1,96 @@ +#include "MantidQtCustomInterfaces/IndirectSymmetrise.h" + +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidKernel/Logger.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" + +#include + +namespace +{ + Mantid::Kernel::Logger g_log("IndirectSymmetrise"); +} + +namespace MantidQt +{ +namespace CustomInterfaces +{ + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + IndirectSymmetrise::IndirectSymmetrise(Ui::IndirectDataReduction& uiForm, QWidget * parent) : + IndirectDataReductionTab(uiForm, parent) + { + // Property Tree + m_propTrees["SymmPropTree"] = new QtTreePropertyBrowser(); + m_uiForm.symm_properties->addWidget(m_propTrees["SymmPropTree"]); + + // Editor Factories + DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(); + m_propTrees["SymmPropTree"]->setFactoryForManager(m_dblManager, doubleEditorFactory); + + // Create Properties + m_properties["XCut"] = m_dblManager->addProperty("X Cut"); + /* m_dblManager->setMinimum(m_properties["XCut"], 0); */ + m_propTrees["SymmPropTree"]->addProperty(m_properties["XCut"]); + + // Raw plot + m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); + m_curves["SymmRawPlot"] = new QwtPlotCurve(); + + m_rangeSelectors["SlicePeak"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); + m_rangeSelectors["SliceBackground"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); + + m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); + m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); + m_plots["SymmRawPlot"]->setCanvasBackground(Qt::white); + m_uiForm.symm_plot->addWidget(m_plots["SymmRawPlot"]); + + // Refresh the plot windows + /* m_plots["SymmRawPlot"]->replot(); */ + + // SIGNAL/SLOT CONNECTIONS + + /* // Update properties when a range selector is changed */ + /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */ + /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */ + /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */ + /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */ + /* // Update range selctors when a property is changed */ + /* connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(sliceUpdateRS(QtProperty*, double))); */ + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + IndirectSymmetrise::~IndirectSymmetrise() + { + } + + void IndirectSymmetrise::setup() + { + } + + void IndirectSymmetrise::run() + { + //TODO + } + + bool IndirectSymmetrise::validate() + { + //TODO + return false; + } + + void IndirectSymmetrise::plotRawInput() + { + //TODO + } + + void IndirectSymmetrise::updateRangeSelector(QtProperty *prop, double value) + { + //TODO + } + +} // namespace CustomInterfaces +} // namespace Mantid From 4dae20b9f7711e2ca2c078b694db77fff3860abe Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 20 Aug 2014 10:56:10 +0100 Subject: [PATCH 09/46] Added more to Symmetrise tab Refs #7860 --- .../IndirectSymmetrise.h | 6 +- .../src/IndirectDataReductionTab.cpp | 5 +- .../src/IndirectSymmetrise.cpp | 127 +++++++++++++++--- 3 files changed, 115 insertions(+), 23 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h index 8ca2db7e1540..a66902bd9206 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -66,8 +66,10 @@ namespace CustomInterfaces virtual bool validate(); private slots: - void plotRawInput(); - void updateRangeSelector(QtProperty *prop, double value); + void plotRawInput(const QString &workspaceName); + void updateRawPlot(); + void replotNewSpectrum(QtProperty *prop, double value); + void updateRangeSelectors(QtProperty *prop, double value); }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp index bcb3456cb015..04ad1e643dd9 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp @@ -228,9 +228,12 @@ namespace CustomInterfaces if(cID == "") cID = plotID; - //check if we can plot + // Check if we can plot if( wsIndex >= workspace->getNumberHistograms() || workspace->readX(0).size() < 2 ) + { + g_log.error("Spectrum index out of range for this workspace"); return; + } QwtWorkspaceSpectrumData wsData(*workspace, static_cast(wsIndex), false); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 99750711a15d..17c87c5a637f 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -31,15 +31,29 @@ namespace CustomInterfaces // Create Properties m_properties["XCut"] = m_dblManager->addProperty("X Cut"); - /* m_dblManager->setMinimum(m_properties["XCut"], 0); */ m_propTrees["SymmPropTree"]->addProperty(m_properties["XCut"]); + QtProperty* rawPlotProps = m_grpManager->addProperty("Raw Plot"); + m_propTrees["SymmPropTree"]->addProperty(rawPlotProps); + + m_properties["PreviewSpec"] = m_dblManager->addProperty("Spectrum No"); + m_dblManager->setDecimals(m_properties["PreviewSpec"], 0); + rawPlotProps->addSubProperty(m_properties["PreviewSpec"]); + + m_properties["PreviewRange"] = m_dblManager->addProperty("X Range"); + rawPlotProps->addSubProperty(m_properties["PreviewRange"]); + // Raw plot m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmRawPlot"] = new QwtPlotCurve(); - m_rangeSelectors["SlicePeak"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); - m_rangeSelectors["SliceBackground"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); + m_rangeSelectors["NegativeXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE); + m_rangeSelectors["PositiveXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE); + + m_rangeSelectors["CentreMark"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["CentreMark"]->setColour(Qt::cyan); + m_rangeSelectors["CentreMark"]->setMinimum(0.0); m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); @@ -47,17 +61,22 @@ namespace CustomInterfaces m_uiForm.symm_plot->addWidget(m_plots["SymmRawPlot"]); // Refresh the plot windows - /* m_plots["SymmRawPlot"]->replot(); */ + m_plots["SymmRawPlot"]->replot(); // SIGNAL/SLOT CONNECTIONS - - /* // Update properties when a range selector is changed */ - /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */ - /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */ - /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */ - /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */ - /* // Update range selctors when a property is changed */ - /* connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(sliceUpdateRS(QtProperty*, double))); */ + // Update range selctors when a property is changed + connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updateRangeSelectors(QtProperty*, double))); + // Plot a new spectrum when the user changes the value of the preview spectrum + connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(replotNewSpectrum(QtProperty*, double))); + // Plot miniplot when file has finished loading + connect(m_uiForm.symm_dsInput, SIGNAL(dataReady(const QString&)), this, SLOT(plotRawInput(const QString&))); + + // Set default XCut value + m_dblManager->setValue(m_properties["XCut"], 0.3); + + // Set default x axis range + std::pair defaultRange(-1.0, 1.0); + setAxisRange("SymmRawPlot", QwtPlot::xBottom, defaultRange); } //---------------------------------------------------------------------------------------------- @@ -71,25 +90,93 @@ namespace CustomInterfaces { } + bool IndirectSymmetrise::validate() + { + // Check for a valid input file + if(!m_uiForm.symm_dsInput->isValid()) + return false; + + // Check for a valid XCut value + if(m_dblManager->value(m_properties["XCut"]) <= 0.0) + return false; + + return true; + } + void IndirectSymmetrise::run() { - //TODO + using namespace Mantid::API; + + QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); + QString outputWorkspaceName = workspaceName.left(workspaceName.length() - 4) + "_Symmetrise"; + + bool plot = m_uiForm.symm_ckPlot->isChecked(); + bool verbose = m_uiForm.symm_ckVerbose->isChecked(); + bool save = m_uiForm.symm_ckSave->isChecked(); + + double x_cut = m_dblManager->value(m_properties["XCut"]); + + IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); + symmetriseAlg->initialize(); + symmetriseAlg->setProperty("Sample", workspaceName.toStdString()); + symmetriseAlg->setProperty("XCut", x_cut); + symmetriseAlg->setProperty("Plot", plot); + symmetriseAlg->setProperty("Verbose", verbose); + symmetriseAlg->setProperty("Save", save); + symmetriseAlg->setProperty("OutputWorkspace", outputWorkspaceName.toStdString()); + + // Execute algorithm on seperate thread + runAlgorithm(symmetriseAlg); + } + + void IndirectSymmetrise::plotRawInput(const QString &workspaceName) + { + UNUSED_ARG(workspaceName); + + updateRawPlot(); + + auto axisRange = getCurveRange("SymmRawPlot"); + double symmRange = fmax(fabs(axisRange.first), fabs(axisRange.second)); + g_log.information() << "Symmetrise x axis range +/- " << symmRange << std::endl; + m_dblManager->setValue(m_properties["PreviewRange"], symmRange); + + updateRawPlot(); } - bool IndirectSymmetrise::validate() + void IndirectSymmetrise::updateRawPlot() { - //TODO - return false; + if(!m_uiForm.symm_dsInput->isValid()) + return; + + QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); + int spectrumNumber = static_cast(m_dblManager->value(m_properties["PreviewSpec"])); + + Mantid::API::MatrixWorkspace_sptr input = boost::dynamic_pointer_cast( + Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName.toStdString())); + + std::pairrange; + range.first = -m_dblManager->value(m_properties["PreviewRange"]); + range.second = m_dblManager->value(m_properties["PreviewRange"]); + setAxisRange("SymmRawPlot", QwtPlot::xBottom, range); + + plotMiniPlot(input, spectrumNumber, "SymmRawPlot"); } - void IndirectSymmetrise::plotRawInput() + void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) { - //TODO + UNUSED_ARG(value); + + if((prop == m_properties["PreviewSpec"]) || (prop == m_properties["PreviewRange"])) + updateRawPlot(); } - void IndirectSymmetrise::updateRangeSelector(QtProperty *prop, double value) + void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) { - //TODO + if(prop == m_properties["XCut"]) + { + m_rangeSelectors["NegativeXCut"]->setMinimum(-value); + m_rangeSelectors["PositiveXCut"]->setMinimum(value); + } } } // namespace CustomInterfaces From e96cf67c779b9b2a71a5c0101d423bd5b1c4cce9 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 20 Aug 2014 11:16:48 +0100 Subject: [PATCH 10/46] Fix Windows compile error Refs #7860 --- .../Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 17c87c5a637f..2ef9cfc31548 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -136,7 +136,7 @@ namespace CustomInterfaces updateRawPlot(); auto axisRange = getCurveRange("SymmRawPlot"); - double symmRange = fmax(fabs(axisRange.first), fabs(axisRange.second)); + double symmRange = std::max(fabs(axisRange.first), fabs(axisRange.second)); g_log.information() << "Symmetrise x axis range +/- " << symmRange << std::endl; m_dblManager->setValue(m_properties["PreviewRange"], symmRange); From 2fd5ce03af13b68feb1ba5f1a9c038bad2d5d5d1 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 20 Aug 2014 15:08:09 +0100 Subject: [PATCH 11/46] Temp removal of failing usage example Refs #7860 --- .../docs/source/algorithms/Symmetrise-v1.rst | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index bc93a312b7dc..5db2b72386b4 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -14,26 +14,26 @@ moduli of xmin & xmax are different. Typically xmax is > mod(xmin). A negative value of x is chosen (Xcut) so that the curve for mod(Xcut) to xmax is reflected and inserted for x less than the Xcut. -Usage ------ +.. Usage +.. ----- -**Example - Running Symmetrise on an asymmetric workspace.** +.. **Example - Running Symmetrise on an asymmetric workspace.** -.. testcode:: ExSymmetriseSimple +.. .. testcode:: ExSymmetriseSimple - import numpy as np +.. import numpy as np - #create an asymmetric line shape - def rayleigh(x, sigma): - return (x / sigma**2) * np.exp( -x**2 / (2*sigma**2)) +.. #create an asymmetric line shape +.. def rayleigh(x, sigma): +.. return (x / sigma**2) * np.exp( -x**2 / (2*sigma**2)) - dataX = np.arange(0, 10, 0.01) - dataY = rayleigh(dataX, 1) +.. dataX = np.arange(0, 10, 0.01) +.. dataY = rayleigh(dataX, 1) - ws = CreateWorkspace(dataX, dataY) - ws = ScaleX(ws, -1, "Add") #centre the peak over 0 +.. ws = CreateWorkspace(dataX, dataY) +.. ws = ScaleX(ws, -1, "Add") #centre the peak over 0 - ws = RenameWorkspace(ws, OutputWorkspace="iris00001_graphite002_red") - Symmetrise('00001', '-0.001', InputType='Workspace') +.. ws = RenameWorkspace(ws, OutputWorkspace="iris00001_graphite002_red") +.. Symmetrise('00001', '-0.001', InputType='Workspace') .. categories:: From 1267f5ab25528e7fc20e955c4ded35e1b7e296fa Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 21 Aug 2014 10:28:50 +0100 Subject: [PATCH 12/46] Refactoring, fixed usage example Refs #7860 --- .../WorkflowAlgorithms/Symmetrise.py | 35 +++++++++---------- .../docs/source/algorithms/Symmetrise-v1.rst | 27 +++++++------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py index a7874877fb8c..16957d20a5ff 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py @@ -21,9 +21,9 @@ def PyInit(self): doc='Sample to run with') self.declareProperty('XCut', 0.0, doc='X cut off value') - self.declareProperty('Verbose', defaultValue=True, + self.declareProperty('Verbose', defaultValue=False, doc='Switch verbose output Off/On') - self.declareProperty('Plot', defaultValue=True, + self.declareProperty('Plot', defaultValue=False, doc='Switch plotting Off/On') self.declareProperty('Save', defaultValue=False, doc='Switch saving result to nxs file Off/On') @@ -42,7 +42,7 @@ def PyExec(self): if math.fabs(self._x_cut) < 1e-5: raise ValueError('XCut point is Zero') - #find range of values to flip + # find range of values to flip delta_x = sample_x[1] - sample_x[0] negative_diff = np.absolute(sample_x - self._x_cut) @@ -53,36 +53,33 @@ def PyExec(self): positive_index = np.where(positive_diff < delta_x)[0][-1] self._check_bounds(positive_index, num_pts, label='Positive') - pivot = num_pts - positive_index + 1 - if self._verbose: logger.notice('No. points = %d' % num_pts) logger.notice('Negative : at i =%d; x = %f' % (negative_index, sample_x[negative_index])) logger.notice('Positive : at i =%d; x = %f' % (positive_index, sample_x[positive_index])) - logger.notice('Copy points = %d' % pivot) CloneWorkspace(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - #for each spectrum copy positive values to the negative + # for each spectrum copy positive values to the negative for index in xrange(num_spectra): - x = mtd[self._output_workspace].readX(index) - y = mtd[self._output_workspace].readY(index) - e = mtd[self._output_workspace].readE(index) + x_in = mtd[self._output_workspace].readX(index) + y_in = mtd[self._output_workspace].readY(index) + e_in = mtd[self._output_workspace].readE(index) - x_out = np.zeros(x.size) - y_out = np.zeros(y.size) - e_out = np.zeros(e.size) + x_out = np.zeros(x_in.size) + y_out = np.zeros(y_in.size) + e_out = np.zeros(e_in.size) - x_out[:pivot] = -x[num_pts:num_pts - pivot:-1] - y_out[:pivot] = y[num_pts:num_pts - pivot - 1:-1] - e_out[:pivot] = e[num_pts:num_pts - pivot - 1:-1] + x_out[:positive_index] = -x_in[negative_index + positive_index:negative_index:-1] + y_out[:positive_index] = y_in[negative_index + positive_index:negative_index:-1] + e_out[:positive_index] = e_in[negative_index + positive_index:negative_index:-1] - x_out[pivot:] = x[pivot:] - y_out[pivot:] = y[pivot:] - e_out[pivot:] = e[pivot:] + x_out[positive_index:] = x_in[positive_index:] + y_out[positive_index:] = y_in[positive_index:] + e_out[positive_index:] = e_in[positive_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index 5db2b72386b4..fb0eb92a347b 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -14,26 +14,25 @@ moduli of xmin & xmax are different. Typically xmax is > mod(xmin). A negative value of x is chosen (Xcut) so that the curve for mod(Xcut) to xmax is reflected and inserted for x less than the Xcut. -.. Usage -.. ----- +Usage +----- -.. **Example - Running Symmetrise on an asymmetric workspace.** +**Example - Running Symmetrise on an asymmetric workspace.** -.. .. testcode:: ExSymmetriseSimple +.. testcode:: ExSymmetriseSimple -.. import numpy as np + import numpy as np -.. #create an asymmetric line shape -.. def rayleigh(x, sigma): -.. return (x / sigma**2) * np.exp( -x**2 / (2*sigma**2)) + # create an asymmetric line shape + def rayleigh(x, sigma): + return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) -.. dataX = np.arange(0, 10, 0.01) -.. dataY = rayleigh(dataX, 1) + dataX = np.arange(0, 10, 0.01) + dataY = rayleigh(dataX, 1) -.. ws = CreateWorkspace(dataX, dataY) -.. ws = ScaleX(ws, -1, "Add") #centre the peak over 0 + ws = CreateWorkspace(dataX, dataY) + ws = ScaleX(ws, -1, "Add") # centre the peak over 0 -.. ws = RenameWorkspace(ws, OutputWorkspace="iris00001_graphite002_red") -.. Symmetrise('00001', '-0.001', InputType='Workspace') + symm_ws = Symmetrise(Sample=ws, XCut=-0.001) .. categories:: From a134ee0513b4e13f9f9d9dcb9ce18d354830c8c4 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 3 Sep 2014 15:27:03 +0100 Subject: [PATCH 13/46] Edited algo to act as intended Refs #7860 --- .../{WorkflowAlgorithms => }/Symmetrise.py | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) rename Code/Mantid/Framework/PythonInterface/plugins/algorithms/{WorkflowAlgorithms => }/Symmetrise.py (74%) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py similarity index 74% rename from Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py rename to Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 16957d20a5ff..ba0da303ac43 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -1,7 +1,7 @@ from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty from mantid.kernel import Direction -from mantid.simpleapi import CloneWorkspace, SaveNexusProcessed +from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed import math import os.path @@ -42,7 +42,7 @@ def PyExec(self): if math.fabs(self._x_cut) < 1e-5: raise ValueError('XCut point is Zero') - # find range of values to flip + # Find range of values to flip delta_x = sample_x[1] - sample_x[0] negative_diff = np.absolute(sample_x - self._x_cut) @@ -53,6 +53,8 @@ def PyExec(self): positive_index = np.where(positive_diff < delta_x)[0][-1] self._check_bounds(positive_index, num_pts, label='Positive') + new_data_size = 2*num_pts - (positive_index + negative_index) + 1 + if self._verbose: logger.notice('No. points = %d' % num_pts) logger.notice('Negative : at i =%d; x = %f' @@ -60,26 +62,34 @@ def PyExec(self): logger.notice('Positive : at i =%d; x = %f' % (positive_index, sample_x[positive_index])) - CloneWorkspace(InputWorkspace=self._sample, - OutputWorkspace=self._output_workspace) - - # for each spectrum copy positive values to the negative - for index in xrange(num_spectra): - x_in = mtd[self._output_workspace].readX(index) - y_in = mtd[self._output_workspace].readY(index) - e_in = mtd[self._output_workspace].readE(index) + zeros = np.zeros(new_data_size * num_spectra) + CreateWorkspace(OutputWorkspace=self._output_workspace, + DataX=zeros, DataY=zeros, DataE=zeros, + NSpec=num_spectra) - x_out = np.zeros(x_in.size) - y_out = np.zeros(y_in.size) - e_out = np.zeros(e_in.size) + CopyLogs(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + # CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + # CopySample(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - x_out[:positive_index] = -x_in[negative_index + positive_index:negative_index:-1] - y_out[:positive_index] = y_in[negative_index + positive_index:negative_index:-1] - e_out[:positive_index] = e_in[negative_index + positive_index:negative_index:-1] - - x_out[positive_index:] = x_in[positive_index:] - y_out[positive_index:] = y_in[positive_index:] - e_out[positive_index:] = e_in[positive_index:] + # For each spectrum copy positive values to the negative + for index in xrange(num_spectra): + x_in = mtd[self._sample].readX(index) + y_in = mtd[self._sample].readY(index) + e_in = mtd[self._sample].readE(index) + + x_out = np.zeros(new_data_size) + y_out = np.zeros(new_data_size) + e_out = np.zeros(new_data_size) + + # Left hand side of cut + x_out[:num_pts - negative_index] = -x_in[num_pts:negative_index:-1] + y_out[:num_pts - negative_index] = y_in[num_pts:negative_index:-1] + e_out[:num_pts - negative_index] = e_in[num_pts:negative_index:-1] + + # Right hand side of cut + x_out[num_pts - negative_index:] = x_in[positive_index:] + y_out[num_pts - negative_index:] = y_in[positive_index:] + e_out[num_pts - negative_index:] = e_in[positive_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) From 9801cb6bcac49639a6188dc94ea57cc4138057b7 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 3 Sep 2014 15:50:49 +0100 Subject: [PATCH 14/46] Fixed negative and positive edge finding Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index ba0da303ac43..0d86699f2d3e 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -45,7 +45,7 @@ def PyExec(self): # Find range of values to flip delta_x = sample_x[1] - sample_x[0] - negative_diff = np.absolute(sample_x - self._x_cut) + negative_diff = np.absolute(sample_x + self._x_cut) negative_index = np.where(negative_diff < delta_x)[0][-1] self._check_bounds(negative_index, num_pts, label='Negative') @@ -53,7 +53,7 @@ def PyExec(self): positive_index = np.where(positive_diff < delta_x)[0][-1] self._check_bounds(positive_index, num_pts, label='Positive') - new_data_size = 2*num_pts - (positive_index + negative_index) + 1 + new_data_size = 2 * num_pts - (positive_index + negative_index) + 1 if self._verbose: logger.notice('No. points = %d' % num_pts) @@ -82,14 +82,14 @@ def PyExec(self): e_out = np.zeros(new_data_size) # Left hand side of cut - x_out[:num_pts - negative_index] = -x_in[num_pts:negative_index:-1] - y_out[:num_pts - negative_index] = y_in[num_pts:negative_index:-1] - e_out[:num_pts - negative_index] = e_in[num_pts:negative_index:-1] + x_out[:num_pts - positive_index] = -x_in[num_pts:positive_index:-1] + y_out[:num_pts - positive_index] = y_in[num_pts:positive_index:-1] + e_out[:num_pts - positive_index] = e_in[num_pts:positive_index:-1] # Right hand side of cut - x_out[num_pts - negative_index:] = x_in[positive_index:] - y_out[num_pts - negative_index:] = y_in[positive_index:] - e_out[num_pts - negative_index:] = e_in[positive_index:] + x_out[num_pts - positive_index:] = x_in[negative_index:] + y_out[num_pts - positive_index:] = y_in[negative_index:] + e_out[num_pts - positive_index:] = e_in[negative_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) From de5e53745c62a4fff2299c9dc1ea2ca502933ce3 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 3 Sep 2014 16:25:26 +0100 Subject: [PATCH 15/46] Refactoring, restrict IDR UI to reduced files/ws Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 40 ++++++++++--------- .../IndirectDataReduction.ui | 6 +++ .../src/IndirectSymmetrise.cpp | 8 ++-- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 0d86699f2d3e..43d36e99ca5b 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -36,7 +36,7 @@ def PyExec(self): StartTime('Symmetrise') self._setup() - num_spectra, num_pts = CheckHistZero(self._sample) + num_spectra, sample_aray_len = CheckHistZero(self._sample) sample_x = mtd[self._sample].readX(0) if math.fabs(self._x_cut) < 1e-5: @@ -47,28 +47,29 @@ def PyExec(self): negative_diff = np.absolute(sample_x + self._x_cut) negative_index = np.where(negative_diff < delta_x)[0][-1] - self._check_bounds(negative_index, num_pts, label='Negative') + self._check_bounds(negative_index, sample_aray_len, label='Negative') positive_diff = np.absolute(sample_x + sample_x[negative_index]) positive_index = np.where(positive_diff < delta_x)[0][-1] - self._check_bounds(positive_index, num_pts, label='Positive') + self._check_bounds(positive_index, sample_aray_len, label='Positive') - new_data_size = 2 * num_pts - (positive_index + negative_index) + 1 + new_array_len = 2 * sample_aray_len - (positive_index + negative_index) + 1 if self._verbose: - logger.notice('No. points = %d' % num_pts) + logger.notice('No. points = %d' % sample_aray_len) logger.notice('Negative : at i =%d; x = %f' % (negative_index, sample_x[negative_index])) logger.notice('Positive : at i =%d; x = %f' % (positive_index, sample_x[positive_index])) + logger.notice('New array size = %d' % new_array_len) - zeros = np.zeros(new_data_size * num_spectra) + zeros = np.zeros(new_array_len * num_spectra) CreateWorkspace(OutputWorkspace=self._output_workspace, DataX=zeros, DataY=zeros, DataE=zeros, NSpec=num_spectra) CopyLogs(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - # CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) # CopySample(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) # For each spectrum copy positive values to the negative @@ -77,24 +78,27 @@ def PyExec(self): y_in = mtd[self._sample].readY(index) e_in = mtd[self._sample].readE(index) - x_out = np.zeros(new_data_size) - y_out = np.zeros(new_data_size) - e_out = np.zeros(new_data_size) + x_out = np.zeros(new_array_len) + y_out = np.zeros(new_array_len) + e_out = np.zeros(new_array_len) # Left hand side of cut - x_out[:num_pts - positive_index] = -x_in[num_pts:positive_index:-1] - y_out[:num_pts - positive_index] = y_in[num_pts:positive_index:-1] - e_out[:num_pts - positive_index] = e_in[num_pts:positive_index:-1] + x_out[:sample_aray_len - positive_index] = -x_in[sample_aray_len:positive_index:-1] + y_out[:sample_aray_len - positive_index] = y_in[sample_aray_len:positive_index:-1] + e_out[:sample_aray_len - positive_index] = e_in[sample_aray_len:positive_index:-1] # Right hand side of cut - x_out[num_pts - positive_index:] = x_in[negative_index:] - y_out[num_pts - positive_index:] = y_in[negative_index:] - e_out[num_pts - positive_index:] = e_in[negative_index:] + x_out[sample_aray_len - positive_index:] = x_in[negative_index:] + y_out[sample_aray_len - positive_index:] = y_in[negative_index:] + e_out[sample_aray_len - positive_index:] = e_in[negative_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) mtd[self._output_workspace].setE(index, e_out) + logger.information('Spectra %d out of %d done' + % (index, num_spectra)) + if self._save: self._save_output() @@ -149,8 +153,8 @@ def _plot_output(self): Plot the first spectrum of the input and output workspace together. """ from IndirectImport import import_mantidplot - mp = import_mantidplot() - mp.plotSpectrum([self._output_workspace, self._sample], 0) + mtd_plot = import_mantidplot() + mtd_plot.plotSpectrum([self._output_workspace, self._sample], 0) # Register algorithm with Mantid AlgorithmFactory.subscribe(Symmetrise) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui index f747e684f5e0..2ef55e4e8b35 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui @@ -1757,6 +1757,12 @@ Later steps in the process (saving, renaming) will not be done. false + + _red + + + _red.nxs + diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 2ef9cfc31548..87bb582bbe83 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -47,8 +47,8 @@ namespace CustomInterfaces m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmRawPlot"] = new QwtPlotCurve(); - m_rangeSelectors["NegativeXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE); - m_rangeSelectors["PositiveXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE); + m_rangeSelectors["NegativeXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["PositiveXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); m_rangeSelectors["CentreMark"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); @@ -78,14 +78,14 @@ namespace CustomInterfaces std::pair defaultRange(-1.0, 1.0); setAxisRange("SymmRawPlot", QwtPlot::xBottom, defaultRange); } - + //---------------------------------------------------------------------------------------------- /** Destructor */ IndirectSymmetrise::~IndirectSymmetrise() { } - + void IndirectSymmetrise::setup() { } From f695f9a5263be7d63a5d83f40c4d0861c70ff54a Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 3 Sep 2014 16:56:44 +0100 Subject: [PATCH 16/46] Refactor, fix issue with some sample workspaces Some workspaces have differing numbers of array elements for X, Y and E values, just choose the samllest and trim the longer arrays Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 43d36e99ca5b..cd39d58b8398 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -36,68 +36,80 @@ def PyExec(self): StartTime('Symmetrise') self._setup() - num_spectra, sample_aray_len = CheckHistZero(self._sample) + num_spectra, _ = CheckHistZero(self._sample) sample_x = mtd[self._sample].readX(0) if math.fabs(self._x_cut) < 1e-5: raise ValueError('XCut point is Zero') - # Find range of values to flip + # Find the smallest data array in the first spectra + len_x = len(mtd[self._sample].readX(0)) + len_y = len(mtd[self._sample].readY(0)) + len_e = len(mtd[self._sample].readE(0)) + sample_array_len = min(len_x, len_y, len_e) - 1 + delta_x = sample_x[1] - sample_x[0] + # Find array index of negative XCut negative_diff = np.absolute(sample_x + self._x_cut) negative_index = np.where(negative_diff < delta_x)[0][-1] - self._check_bounds(negative_index, sample_aray_len, label='Negative') + self._check_bounds(negative_index, sample_array_len, label='Negative') + # FInd array index of positive XCut positive_diff = np.absolute(sample_x + sample_x[negative_index]) positive_index = np.where(positive_diff < delta_x)[0][-1] - self._check_bounds(positive_index, sample_aray_len, label='Positive') + self._check_bounds(positive_index, sample_array_len, label='Positive') - new_array_len = 2 * sample_aray_len - (positive_index + negative_index) + 1 + # Calculate number of elements neede dfor new array (per spectra) + new_array_len = 2 * sample_array_len - (positive_index + negative_index) + 1 if self._verbose: - logger.notice('No. points = %d' % sample_aray_len) - logger.notice('Negative : at i =%d; x = %f' + logger.notice('No. points = %d' % sample_array_len) + logger.notice('Negative at i=%d, x=%f' % (negative_index, sample_x[negative_index])) - logger.notice('Positive : at i =%d; x = %f' + logger.notice('Positive at i=%d, x=%f' % (positive_index, sample_x[positive_index])) logger.notice('New array size = %d' % new_array_len) + # Create an empty workspace with enough storage for the new data zeros = np.zeros(new_array_len * num_spectra) CreateWorkspace(OutputWorkspace=self._output_workspace, DataX=zeros, DataY=zeros, DataE=zeros, NSpec=num_spectra) + # Copy logs and properties from sample workspace CopyLogs(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) # CopySample(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) # For each spectrum copy positive values to the negative for index in xrange(num_spectra): - x_in = mtd[self._sample].readX(index) - y_in = mtd[self._sample].readY(index) - e_in = mtd[self._sample].readE(index) + # Strip any additional array cells + x_in = mtd[self._sample].readX(index)[:sample_array_len + 1] + y_in = mtd[self._sample].readY(index)[:sample_array_len + 1] + e_in = mtd[self._sample].readE(index)[:sample_array_len + 1] + # Get some zeroed data to overwrite with copies from sample x_out = np.zeros(new_array_len) y_out = np.zeros(new_array_len) e_out = np.zeros(new_array_len) # Left hand side of cut - x_out[:sample_aray_len - positive_index] = -x_in[sample_aray_len:positive_index:-1] - y_out[:sample_aray_len - positive_index] = y_in[sample_aray_len:positive_index:-1] - e_out[:sample_aray_len - positive_index] = e_in[sample_aray_len:positive_index:-1] + x_out[:sample_array_len - positive_index] = -x_in[sample_array_len:positive_index:-1] + y_out[:sample_array_len - positive_index] = y_in[sample_array_len:positive_index:-1] + e_out[:sample_array_len - positive_index] = e_in[sample_array_len:positive_index:-1] # Right hand side of cut - x_out[sample_aray_len - positive_index:] = x_in[negative_index:] - y_out[sample_aray_len - positive_index:] = y_in[negative_index:] - e_out[sample_aray_len - positive_index:] = e_in[negative_index:] + x_out[sample_array_len - positive_index:] = x_in[negative_index:] + y_out[sample_array_len - positive_index:] = y_in[negative_index:] + e_out[sample_array_len - positive_index:] = e_in[negative_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) mtd[self._output_workspace].setE(index, e_out) logger.information('Spectra %d out of %d done' - % (index, num_spectra)) + % (index + 1, num_spectra)) if self._save: self._save_output() @@ -154,7 +166,7 @@ def _plot_output(self): """ from IndirectImport import import_mantidplot mtd_plot = import_mantidplot() - mtd_plot.plotSpectrum([self._output_workspace, self._sample], 0) + mtd_plot.plotSpectrum([self._sample, self._output_workspace], 0) # Register algorithm with Mantid AlgorithmFactory.subscribe(Symmetrise) From 8f76688d74471d3c930450859e3db4ef674ae267 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 4 Sep 2014 08:59:37 +0100 Subject: [PATCH 17/46] Added unit test, improved usage example Refs #7860 --- .../python/plugins/algorithms/CMakeLists.txt | 1 + .../plugins/algorithms/SymmetriseTest.py | 29 +++++++++++++++++++ .../docs/source/algorithms/Symmetrise-v1.rst | 10 +++---- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py 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 a49dab7bcbd5..17fdc6610d61 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -33,6 +33,7 @@ set ( TEST_PY_FILES Stitch1DManyTest.py SuggestTibCNCSTest.py SuggestTibHYSPECTest.py + SymmetriseTest.py UpdatePeakParameterTableValueTest.py SANSSubtractTest.py ExportSampleLogsToCSVFileTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py new file mode 100644 index 000000000000..713c9edfa7da --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py @@ -0,0 +1,29 @@ +import unittest +import numpy as np +from mantid.simpleapi import * +from mantid.api import * + + +class SymmetriseTest(unittest.TestCase): + + def setUp(self): + self._sample_ws = self._generate_sample_ws('symm_test_sample_ws') + + def test_basic(self): + symm_test_out_ws= Symmetrise(Sample=self._sample_ws, XCut=0.05) + + def _rayleigh(self, x, sigma): + return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) + + def _generate_sample_ws(self, ws_name): + data_x = np.arange(0, 10, 0.01) + data_y = self._rayleigh(data_x, 1) + + CreateWorkspace(DataX=data_x, DataY=data_y, OutputWorkspace=ws_name) + ScaleX(InputWorkspace=ws_name, Factor=-1, Operation="Add", OutputWorkspace=ws_name) # centre the peak over 0 + + return mtd[ws_name] + + +if __name__ == '__main__': + unittest.main() diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index fb0eb92a347b..3c5704b229f6 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -27,12 +27,12 @@ Usage def rayleigh(x, sigma): return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) - dataX = np.arange(0, 10, 0.01) - dataY = rayleigh(dataX, 1) + data_x = np.arange(0, 10, 0.01) + data_y = rayleigh(data_x, 1) - ws = CreateWorkspace(dataX, dataY) - ws = ScaleX(ws, -1, "Add") # centre the peak over 0 + sample_ws = CreateWorkspace(data_x, data_y) + sample_ws = ScaleX(sample_ws, -1, "Add") # centre the peak over 0 - symm_ws = Symmetrise(Sample=ws, XCut=-0.001) + symm_ws = Symmetrise(Sample=sample_ws, XCut=0.05) .. categories:: From 97cb4ba78c0ace867633b227f18c9b175a61ef79 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 4 Sep 2014 12:30:25 +0100 Subject: [PATCH 18/46] Added preview window to IDR:Symmetrise Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 63 ++++++--- .../IndirectDataReduction.ui | 26 ++++ .../IndirectSymmetrise.h | 2 + .../src/IndirectDataReductionTab.cpp | 16 +-- .../src/IndirectSymmetrise.cpp | 133 ++++++++++++++++-- 5 files changed, 200 insertions(+), 40 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index cd39d58b8398..1f7bc06b6951 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -1,7 +1,7 @@ from mantid import logger, mtd -from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty +from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty, PropertyMode from mantid.kernel import Direction -from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed +from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed, CreateEmptyTableWorkspace import math import os.path @@ -11,13 +11,13 @@ class Symmetrise(PythonAlgorithm): def category(self): - return "Workflow\\MIDAS;PythonAlgorithms" + return 'Workflow\\MIDAS;PythonAlgorithms' def summary(self): - return "Takes an asymmetric S(Q,w) and makes it symmetric" + return 'Takes an asymmetric S(Q,w) and makes it symmetric' def PyInit(self): - self.declareProperty(WorkspaceProperty("Sample", "", Direction.Input), + self.declareProperty(WorkspaceProperty('Sample', '', Direction.Input), doc='Sample to run with') self.declareProperty('XCut', 0.0, doc='X cut off value') @@ -28,9 +28,12 @@ def PyInit(self): self.declareProperty('Save', defaultValue=False, doc='Switch saving result to nxs file Off/On') - self.declareProperty(WorkspaceProperty("OutputWorkspace", "", + self.declareProperty(WorkspaceProperty('OutputWorkspace', '', Direction.Output), doc='Name to call the output workspace.') + self.declareProperty(WorkspaceProperty('OutputPropertiesTable', '', + Direction.Output, PropertyMode.Optional), doc='Name to call the properties output table workspace.') + def PyExec(self): from IndirectCommon import CheckHistZero, StartTime, EndTime @@ -52,23 +55,23 @@ def PyExec(self): # Find array index of negative XCut negative_diff = np.absolute(sample_x + self._x_cut) - negative_index = np.where(negative_diff < delta_x)[0][-1] - self._check_bounds(negative_index, sample_array_len, label='Negative') + self._negative_index = np.where(negative_diff < delta_x)[0][-1] + self._check_bounds(self._negative_index, sample_array_len, label='Negative') # FInd array index of positive XCut - positive_diff = np.absolute(sample_x + sample_x[negative_index]) - positive_index = np.where(positive_diff < delta_x)[0][-1] - self._check_bounds(positive_index, sample_array_len, label='Positive') + positive_diff = np.absolute(sample_x + sample_x[self._negative_index]) + self._positive_index = np.where(positive_diff < delta_x)[0][-1] + self._check_bounds(self._positive_index, sample_array_len, label='Positive') # Calculate number of elements neede dfor new array (per spectra) - new_array_len = 2 * sample_array_len - (positive_index + negative_index) + 1 + new_array_len = 2 * sample_array_len - (self._positive_index + self._negative_index) + 1 if self._verbose: logger.notice('No. points = %d' % sample_array_len) logger.notice('Negative at i=%d, x=%f' - % (negative_index, sample_x[negative_index])) + % (self._negative_index, sample_x[self._negative_index])) logger.notice('Positive at i=%d, x=%f' - % (positive_index, sample_x[positive_index])) + % (self._positive_index, sample_x[self._positive_index])) logger.notice('New array size = %d' % new_array_len) # Create an empty workspace with enough storage for the new data @@ -95,14 +98,14 @@ def PyExec(self): e_out = np.zeros(new_array_len) # Left hand side of cut - x_out[:sample_array_len - positive_index] = -x_in[sample_array_len:positive_index:-1] - y_out[:sample_array_len - positive_index] = y_in[sample_array_len:positive_index:-1] - e_out[:sample_array_len - positive_index] = e_in[sample_array_len:positive_index:-1] + x_out[:sample_array_len - self._positive_index] = -x_in[sample_array_len:self._positive_index:-1] + y_out[:sample_array_len - self._positive_index] = y_in[sample_array_len:self._positive_index:-1] + e_out[:sample_array_len - self._positive_index] = e_in[sample_array_len:self._positive_index:-1] # Right hand side of cut - x_out[sample_array_len - positive_index:] = x_in[negative_index:] - y_out[sample_array_len - positive_index:] = y_in[negative_index:] - e_out[sample_array_len - positive_index:] = e_in[negative_index:] + x_out[sample_array_len - self._positive_index:] = x_in[self._negative_index:] + y_out[sample_array_len - self._positive_index:] = y_in[self._negative_index:] + e_out[sample_array_len - self._positive_index:] = e_in[self._negative_index:] mtd[self._output_workspace].setX(index, x_out) mtd[self._output_workspace].setY(index, y_out) @@ -117,7 +120,11 @@ def PyExec(self): if self._plot: self._plot_output() - self.setProperty("OutputWorkspace", self._output_workspace) + if self._props_output_workspace != '': + self._generate_props_table() + + self.setProperty('OutputWorkspace', self._output_workspace) + EndTime('Symmetrise') def _setup(self): @@ -132,6 +139,7 @@ def _setup(self): self._save = self.getProperty('Save').value self._output_workspace = self.getPropertyValue('OutputWorkspace') + self._props_output_workspace = self.getPropertyValue('OutputPropertiesTable') def _check_bounds(self, index, num_pts, label=''): """ @@ -147,6 +155,19 @@ def _check_bounds(self, index, num_pts, label=''): elif index >= num_pts: raise ValueError('%s point %d > %d' % (label, index, num_pts)) + def _generate_props_table(self): + """ + Creates a table workspace with values calculated in algorithm. + """ + props_table = CreateEmptyTableWorkspace(OutputWorkspace=self._props_output_workspace) + + props_table.addColumn('int', 'NegativeCutIndex') + props_table.addColumn('int', 'PositiveCutIndex') + + props_table.addRow([self._negative_index, self._positive_index]) + + self.setProperty('OutputPropertiesTable', self._props_output_workspace) + def _save_output(self): """ Save the output workspace to the user's default working directory diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui index 2ef55e4e8b35..10cdd7649540 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui @@ -1786,6 +1786,32 @@ Later steps in the process (saving, renaming) will not be done. + + + + Preview + + + + + + + + Preview + + + + + + + + + + + + + + diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h index a66902bd9206..a6b88d632e70 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -70,6 +70,8 @@ namespace CustomInterfaces void updateRawPlot(); void replotNewSpectrum(QtProperty *prop, double value); void updateRangeSelectors(QtProperty *prop, double value); + void preview(); + void previewAlgDone(bool error); }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp index 04ad1e643dd9..830928f6edc1 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp @@ -41,7 +41,7 @@ namespace CustomInterfaces IndirectDataReductionTab::~IndirectDataReductionTab() { } - + void IndirectDataReductionTab::runTab() { if(validate()) @@ -66,7 +66,7 @@ namespace CustomInterfaces /** * Run the load algorithm with the supplied filename and spectrum range - * + * * @param filename :: The name of the file to load * @param outputName :: The name of the output workspace * @param specMin :: Lower spectra bound @@ -91,7 +91,7 @@ namespace CustomInterfaces load->setProperty("SpectrumMax", specMax); load->execute(); - + //If reloading fails we're out of options return load->isExecuted(); } @@ -104,7 +104,7 @@ namespace CustomInterfaces std::map IndirectDataReductionTab::getInstrumentDetails() { std::map instDetails; - + QString pyInput = "from IndirectEnergyConversion import getReflectionDetails\n" "instrument = '" + m_uiForm.cbInst->currentText() + "'\n" @@ -186,7 +186,7 @@ namespace CustomInterfaces * a specturm index. * * This method uses the analysis data service to retrieve the workspace. - * + * * @param workspace :: The name of the workspace * @param index :: The spectrum index of the workspace * @param plotID :: String index of the plot in the m_plots map @@ -213,7 +213,7 @@ namespace CustomInterfaces /** * Plot a workspace to the miniplot given a workspace pointer and * a specturm index. - * + * * @param workspace :: Pointer to the workspace * @param wsIndex :: The spectrum index of the workspace * @param plotID :: String index of the plot in the m_plots map @@ -262,7 +262,7 @@ namespace CustomInterfaces /** * Sets the edge bounds of plot to prevent the user inputting invalid values * Also sets limits for range selector movement - * + * * @param rsID :: The string index of the range selector in the map m_rangeSelectors * @param min :: The lower bound property in the property browser * @param max :: The upper bound property in the property browser @@ -280,7 +280,7 @@ namespace CustomInterfaces /** * Set the position of the guides on the mini plot - * + * * @param rsID :: The string index of the range selector in the map m_rangeSelectors * @param lower :: The lower bound property in the property browser * @param upper :: The upper bound property in the property browser diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 87bb582bbe83..f606ff057549 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -1,6 +1,7 @@ #include "MantidQtCustomInterfaces/IndirectSymmetrise.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/ITableWorkspace.h" #include "MantidKernel/Logger.h" #include "MantidQtCustomInterfaces/UserInputValidator.h" @@ -11,6 +12,8 @@ namespace Mantid::Kernel::Logger g_log("IndirectSymmetrise"); } +using namespace Mantid::API; + namespace MantidQt { namespace CustomInterfaces @@ -21,15 +24,18 @@ namespace CustomInterfaces IndirectSymmetrise::IndirectSymmetrise(Ui::IndirectDataReduction& uiForm, QWidget * parent) : IndirectDataReductionTab(uiForm, parent) { - // Property Tree + // Property Trees m_propTrees["SymmPropTree"] = new QtTreePropertyBrowser(); m_uiForm.symm_properties->addWidget(m_propTrees["SymmPropTree"]); + m_propTrees["SymmPVPropTree"] = new QtTreePropertyBrowser(); + m_uiForm.symm_previewProperties->addWidget(m_propTrees["SymmPVPropTree"]); + // Editor Factories DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(); m_propTrees["SymmPropTree"]->setFactoryForManager(m_dblManager, doubleEditorFactory); - // Create Properties + // Raw Properties m_properties["XCut"] = m_dblManager->addProperty("X Cut"); m_propTrees["SymmPropTree"]->addProperty(m_properties["XCut"]); @@ -43,25 +49,68 @@ namespace CustomInterfaces m_properties["PreviewRange"] = m_dblManager->addProperty("X Range"); rawPlotProps->addSubProperty(m_properties["PreviewRange"]); + // Preview Properties + // Mainly used for display rather than getting user input + m_properties["NegativeYValue"] = m_dblManager->addProperty("Negative Y"); + m_propTrees["SymmPVPropTree"]->addProperty(m_properties["NegativeYValue"]); + + m_properties["PositiveYValue"] = m_dblManager->addProperty("Positive Y"); + m_propTrees["SymmPVPropTree"]->addProperty(m_properties["PositiveYValue"]); + + m_properties["DeltaY"] = m_dblManager->addProperty("Delta Y"); + m_propTrees["SymmPVPropTree"]->addProperty(m_properties["DeltaY"]); + // Raw plot m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmRawPlot"] = new QwtPlotCurve(); - m_rangeSelectors["NegativeXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["PositiveXCut"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["NegativeXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["PositiveXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, false); + + m_rangeSelectors["NegativeXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::YSINGLE, true, false); + m_rangeSelectors["PositiveXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::YSINGLE, true, false); - m_rangeSelectors["CentreMark"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + m_rangeSelectors["NegativeXCutYPos"]->setColour(Qt::red); + m_rangeSelectors["PositiveXCutYPos"]->setColour(Qt::red); + m_rangeSelectors["NegativeXCutYPos"]->setMinimum(0); + m_rangeSelectors["PositiveXCutYPos"]->setMinimum(0); + + m_rangeSelectors["CentreMark_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["CentreMark"]->setColour(Qt::cyan); - m_rangeSelectors["CentreMark"]->setMinimum(0.0); + m_rangeSelectors["CentreMark_Raw"]->setColour(Qt::cyan); + m_rangeSelectors["CentreMark_Raw"]->setMinimum(0.0); m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); m_plots["SymmRawPlot"]->setCanvasBackground(Qt::white); m_uiForm.symm_plot->addWidget(m_plots["SymmRawPlot"]); + // Preview plot + m_plots["SymmPreviewPlot"] = new QwtPlot(m_parentWidget); + m_curves["SymmPreviewPlot"] = new QwtPlotCurve(); + + m_rangeSelectors["NegativeXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["PositiveXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + + m_rangeSelectors["CentreMark_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["CentreMark_PV"]->setColour(Qt::cyan); + m_rangeSelectors["CentreMark_PV"]->setMinimum(0.0); + + m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); + m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); + m_plots["SymmPreviewPlot"]->setCanvasBackground(Qt::white); + m_uiForm.symm_previewPlot->addWidget(m_plots["SymmPreviewPlot"]); + // Refresh the plot windows m_plots["SymmRawPlot"]->replot(); + m_plots["SymmPreviewPlot"]->replot(); // SIGNAL/SLOT CONNECTIONS // Update range selctors when a property is changed @@ -70,6 +119,8 @@ namespace CustomInterfaces connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(replotNewSpectrum(QtProperty*, double))); // Plot miniplot when file has finished loading connect(m_uiForm.symm_dsInput, SIGNAL(dataReady(const QString&)), this, SLOT(plotRawInput(const QString&))); + // Preview symmetrise + connect(m_uiForm.symm_previewButton, SIGNAL(clicked()), this, SLOT(preview())); // Set default XCut value m_dblManager->setValue(m_properties["XCut"], 0.3); @@ -77,6 +128,7 @@ namespace CustomInterfaces // Set default x axis range std::pair defaultRange(-1.0, 1.0); setAxisRange("SymmRawPlot", QwtPlot::xBottom, defaultRange); + setAxisRange("SymmPreviewPlot", QwtPlot::xBottom, defaultRange); } //---------------------------------------------------------------------------------------------- @@ -105,8 +157,6 @@ namespace CustomInterfaces void IndirectSymmetrise::run() { - using namespace Mantid::API; - QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); QString outputWorkspaceName = workspaceName.left(workspaceName.length() - 4) + "_Symmetrise"; @@ -160,6 +210,10 @@ namespace CustomInterfaces setAxisRange("SymmRawPlot", QwtPlot::xBottom, range); plotMiniPlot(input, spectrumNumber, "SymmRawPlot"); + + // Match X axis range on preview plot + setAxisRange("SymmPreviewPlot", QwtPlot::xBottom, range); + m_plots["SymmPreviewPlot"]->replot(); } void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) @@ -174,10 +228,67 @@ namespace CustomInterfaces { if(prop == m_properties["XCut"]) { - m_rangeSelectors["NegativeXCut"]->setMinimum(-value); - m_rangeSelectors["PositiveXCut"]->setMinimum(value); + m_rangeSelectors["NegativeXCut_Raw"]->setMinimum(-value); + m_rangeSelectors["PositiveXCut_Raw"]->setMinimum(value); + + m_rangeSelectors["NegativeXCut_PV"]->setMinimum(-value); + m_rangeSelectors["PositiveXCut_PV"]->setMinimum(value); } } + void IndirectSymmetrise::preview() + { + connect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + + QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); + + if(workspaceName.isEmpty()) + return; + + double x_cut = m_dblManager->value(m_properties["XCut"]); + + IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); + symmetriseAlg->initialize(); + symmetriseAlg->setProperty("Sample", workspaceName.toStdString()); + symmetriseAlg->setProperty("XCut", x_cut); + symmetriseAlg->setProperty("Plot", false); + symmetriseAlg->setProperty("Verbose", false); + symmetriseAlg->setProperty("Save", false); + symmetriseAlg->setProperty("OutputWorkspace", "__Symmetrise_temp"); + symmetriseAlg->setProperty("OutputPropertiesTable", "__SymmetriseProps_temp"); + + runAlgorithm(symmetriseAlg); + } + + void IndirectSymmetrise::previewAlgDone(bool error) + { + if(error) + return; + + QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); + int spectrumNumber = static_cast(m_dblManager->value(m_properties["PreviewSpec"])); + + MatrixWorkspace_sptr sampleWS = AnalysisDataService::Instance().retrieveWS(workspaceName.toStdString()); + ITableWorkspace_sptr propsTable = AnalysisDataService::Instance().retrieveWS("__SymmetriseProps_temp"); + + int negativeIndex = propsTable->getColumn("NegativeCutIndex")->cell(0); + int positiveIndex = propsTable->getColumn("PositiveCutIndex")->cell(0); + + double negativeY = sampleWS->dataY(0)[negativeIndex]; + double positiveY = sampleWS->dataY(0)[positiveIndex]; + double deltaY = fabs(negativeY - positiveY); + + m_dblManager->setValue(m_properties["NegativeYValue"], negativeY); + m_dblManager->setValue(m_properties["PositiveYValue"], positiveY); + m_dblManager->setValue(m_properties["DeltaY"], deltaY); + + m_rangeSelectors["NegativeXCutYPos"]->setMinimum(negativeY); + m_rangeSelectors["PositiveXCutYPos"]->setMinimum(positiveY); + + plotMiniPlot("__Symmetrise_temp", spectrumNumber, "SymmPreviewPlot"); + + disconnect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + } + } // namespace CustomInterfaces } // namespace Mantid From 829ff5b887055cea0049f921f10315abe78051c9 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 4 Sep 2014 15:41:45 +0100 Subject: [PATCH 19/46] Added spectra range option, updated UI Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 76 ++++++++++++++----- .../IndirectSymmetrise.h | 2 +- .../src/IndirectSymmetrise.cpp | 76 ++++++++++++++++--- 3 files changed, 123 insertions(+), 31 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 1f7bc06b6951..b915fc158f38 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -1,6 +1,6 @@ from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty, PropertyMode -from mantid.kernel import Direction +from mantid.kernel import Direction, IntArrayProperty, IntArrayMandatoryValidator from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed, CreateEmptyTableWorkspace import math @@ -28,6 +28,9 @@ def PyInit(self): self.declareProperty('Save', defaultValue=False, doc='Switch saving result to nxs file Off/On') + self.declareProperty(IntArrayProperty(name='SpectraRange'), + doc='Range of spectra to symmetrise (defaults to entire range if not set)') + self.declareProperty(WorkspaceProperty('OutputWorkspace', '', Direction.Output), doc='Name to call the output workspace.') @@ -35,15 +38,13 @@ def PyInit(self): Direction.Output, PropertyMode.Optional), doc='Name to call the properties output table workspace.') def PyExec(self): - from IndirectCommon import CheckHistZero, StartTime, EndTime + from IndirectCommon import StartTime, EndTime StartTime('Symmetrise') self._setup() - num_spectra, _ = CheckHistZero(self._sample) - sample_x = mtd[self._sample].readX(0) - if math.fabs(self._x_cut) < 1e-5: - raise ValueError('XCut point is Zero') + # The number of spectra that will actually be changed + num_symm_spectra = self._spectra_range[1] - self._spectra_range[0] + 1 # Find the smallest data array in the first spectra len_x = len(mtd[self._sample].readX(0)) @@ -51,6 +52,7 @@ def PyExec(self): len_e = len(mtd[self._sample].readE(0)) sample_array_len = min(len_x, len_y, len_e) - 1 + sample_x = mtd[self._sample].readX(0) delta_x = sample_x[1] - sample_x[0] # Find array index of negative XCut @@ -58,12 +60,12 @@ def PyExec(self): self._negative_index = np.where(negative_diff < delta_x)[0][-1] self._check_bounds(self._negative_index, sample_array_len, label='Negative') - # FInd array index of positive XCut + # Find array index of positive XCut positive_diff = np.absolute(sample_x + sample_x[self._negative_index]) self._positive_index = np.where(positive_diff < delta_x)[0][-1] self._check_bounds(self._positive_index, sample_array_len, label='Positive') - # Calculate number of elements neede dfor new array (per spectra) + # Calculate number of elements needed for new array (per spectra) new_array_len = 2 * sample_array_len - (self._positive_index + self._negative_index) + 1 if self._verbose: @@ -74,11 +76,14 @@ def PyExec(self): % (self._positive_index, sample_x[self._positive_index])) logger.notice('New array size = %d' % new_array_len) + x_unit = mtd[self._sample].getXDimension().getUnits() + # Create an empty workspace with enough storage for the new data - zeros = np.zeros(new_array_len * num_spectra) + zeros = np.zeros(new_array_len * num_symm_spectra) CreateWorkspace(OutputWorkspace=self._output_workspace, DataX=zeros, DataY=zeros, DataE=zeros, - NSpec=num_spectra) + NSpec=num_symm_spectra, + UnitX=x_unit) # Copy logs and properties from sample workspace CopyLogs(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) @@ -86,11 +91,15 @@ def PyExec(self): # CopySample(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) # For each spectrum copy positive values to the negative - for index in xrange(num_spectra): + output_spectrum_index = 0 + for spectrum_no in range(self._spectra_range[0], self._spectra_range[1] + 1): + # Get index of original spectra + spectrum_index = mtd[self._sample].getIndexFromSpectrumNumber(spectrum_no) + # Strip any additional array cells - x_in = mtd[self._sample].readX(index)[:sample_array_len + 1] - y_in = mtd[self._sample].readY(index)[:sample_array_len + 1] - e_in = mtd[self._sample].readE(index)[:sample_array_len + 1] + x_in = mtd[self._sample].readX(spectrum_index)[:sample_array_len + 1] + y_in = mtd[self._sample].readY(spectrum_index)[:sample_array_len + 1] + e_in = mtd[self._sample].readE(spectrum_index)[:sample_array_len + 1] # Get some zeroed data to overwrite with copies from sample x_out = np.zeros(new_array_len) @@ -107,12 +116,17 @@ def PyExec(self): y_out[sample_array_len - self._positive_index:] = y_in[self._negative_index:] e_out[sample_array_len - self._positive_index:] = e_in[self._negative_index:] - mtd[self._output_workspace].setX(index, x_out) - mtd[self._output_workspace].setY(index, y_out) - mtd[self._output_workspace].setE(index, e_out) + # Set output spectrum data + mtd[self._output_workspace].setX(output_spectrum_index, x_out) + mtd[self._output_workspace].setY(output_spectrum_index, y_out) + mtd[self._output_workspace].setE(output_spectrum_index, e_out) + + # Set output spectrum number + mtd[self._output_workspace].getSpectrum(output_spectrum_index).setSpectrumNo(spectrum_no) - logger.information('Spectra %d out of %d done' - % (index + 1, num_spectra)) + output_spectrum_index += 1 + + logger.information('Symmetrise spectra %d' % spectrum_no) if self._save: self._save_output() @@ -129,15 +143,36 @@ def PyExec(self): def _setup(self): """ - Get the algorithm properties. + Get the algorithm properties and validate them. """ + from IndirectCommon import CheckHistZero + self._sample = self.getPropertyValue('Sample') + + num_sample_spectra, _ = CheckHistZero(self._sample) + min_spectra_number = mtd[self._sample].getSpectrum(0).getSpectrumNo() + max_spectra_number = mtd[self._sample].getSpectrum(num_sample_spectra - 1).getSpectrumNo() + self._x_cut = self.getProperty('XCut').value + if math.fabs(self._x_cut) < 1e-5: + raise ValueError('XCut point is Zero') + self._verbose = self.getProperty('Verbose').value self._plot = self.getProperty('Plot').value self._save = self.getProperty('Save').value + self._spectra_range = self.getProperty('SpectraRange').value + + if len(self._spectra_range) < 2: + self._spectra_range = [min_spectra_number, max_spectra_number] + else: + if self._spectra_range[0] > self._spectra_range[1]: + raise ValueError('Invalid spectra range') + + if self._spectra_range[1] > max_spectra_number: + raise ValueError('Max spectrum number out of range') + self._output_workspace = self.getPropertyValue('OutputWorkspace') self._props_output_workspace = self.getPropertyValue('OutputPropertiesTable') @@ -187,6 +222,7 @@ def _plot_output(self): """ from IndirectImport import import_mantidplot mtd_plot = import_mantidplot() + mtd_plot.plotSpectrum([self._sample, self._output_workspace], 0) # Register algorithm with Mantid diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h index a6b88d632e70..3eb019206bef 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -67,7 +67,7 @@ namespace CustomInterfaces private slots: void plotRawInput(const QString &workspaceName); - void updateRawPlot(); + void updateMiniPlots(); void replotNewSpectrum(QtProperty *prop, double value); void updateRangeSelectors(QtProperty *prop, double value); void preview(); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index f606ff057549..c8d1ce0d1380 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -64,21 +64,27 @@ namespace CustomInterfaces m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmRawPlot"] = new QwtPlotCurve(); + // Indicators for negative and positive XCut values on X axis m_rangeSelectors["NegativeXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); m_rangeSelectors["PositiveXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["NegativeXCut_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveXCut_Raw"]->setColour(Qt::darkGreen); + + // Indicators for Y value at each XCut position m_rangeSelectors["NegativeXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::YSINGLE, true, false); m_rangeSelectors["PositiveXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::YSINGLE, true, false); m_rangeSelectors["NegativeXCutYPos"]->setColour(Qt::red); - m_rangeSelectors["PositiveXCutYPos"]->setColour(Qt::red); + m_rangeSelectors["PositiveXCutYPos"]->setColour(Qt::blue); m_rangeSelectors["NegativeXCutYPos"]->setMinimum(0); m_rangeSelectors["PositiveXCutYPos"]->setMinimum(0); + // Indicator for centre of symmetry (x=0) m_rangeSelectors["CentreMark_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); m_rangeSelectors["CentreMark_Raw"]->setColour(Qt::cyan); @@ -93,11 +99,16 @@ namespace CustomInterfaces m_plots["SymmPreviewPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmPreviewPlot"] = new QwtPlotCurve(); + // Indicators for negative and positive XCut values on X axis m_rangeSelectors["NegativeXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); m_rangeSelectors["PositiveXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["NegativeXCut_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveXCut_PV"]->setColour(Qt::darkGreen); + + // Indicator for centre of symmetry (x=0) m_rangeSelectors["CentreMark_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); m_rangeSelectors["CentreMark_PV"]->setColour(Qt::cyan); @@ -179,21 +190,33 @@ namespace CustomInterfaces runAlgorithm(symmetriseAlg); } + /** + * Plots a new workspace in the mini plot when it is loaded form the data selector. + * + * @param workspaceName Name of the workspace that has been laoded + */ void IndirectSymmetrise::plotRawInput(const QString &workspaceName) { - UNUSED_ARG(workspaceName); + // Set the preview spectrum number to the first spectrum in the workspace + MatrixWorkspace_sptr sampleWS = AnalysisDataService::Instance().retrieveWS(workspaceName.toStdString()); + int minSpectrumRange = sampleWS->getSpectrum(0)->getSpectrumNo(); + m_dblManager->setValue(m_properties["PreviewSpec"], static_cast(minSpectrumRange)); - updateRawPlot(); + updateMiniPlots(); + // Set the preview range to the maximum absolute X value auto axisRange = getCurveRange("SymmRawPlot"); double symmRange = std::max(fabs(axisRange.first), fabs(axisRange.second)); g_log.information() << "Symmetrise x axis range +/- " << symmRange << std::endl; m_dblManager->setValue(m_properties["PreviewRange"], symmRange); - updateRawPlot(); + updateMiniPlots(); } - void IndirectSymmetrise::updateRawPlot() + /** + * Updates the mini plots. + */ + void IndirectSymmetrise::updateMiniPlots() { if(!m_uiForm.symm_dsInput->isValid()) return; @@ -204,26 +227,35 @@ namespace CustomInterfaces Mantid::API::MatrixWorkspace_sptr input = boost::dynamic_pointer_cast( Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName.toStdString())); + // Set the X axis range based on the range specified by the user std::pairrange; range.first = -m_dblManager->value(m_properties["PreviewRange"]); range.second = m_dblManager->value(m_properties["PreviewRange"]); setAxisRange("SymmRawPlot", QwtPlot::xBottom, range); - plotMiniPlot(input, spectrumNumber, "SymmRawPlot"); + // Plot the spectrum chosen by the user + size_t spectrumIndex = input->getIndexFromSpectrumNumber(spectrumNumber); + plotMiniPlot(input, spectrumIndex, "SymmRawPlot"); // Match X axis range on preview plot setAxisRange("SymmPreviewPlot", QwtPlot::xBottom, range); m_plots["SymmPreviewPlot"]->replot(); } + /** + * Redraws mini plots when user changes previw range or spectrum. + */ void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) { UNUSED_ARG(value); if((prop == m_properties["PreviewSpec"]) || (prop == m_properties["PreviewRange"])) - updateRawPlot(); + updateMiniPlots(); } + /** + * Updates position of XCut range selectors when used changed value of XCut. + */ void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) { if(prop == m_properties["XCut"]) @@ -236,30 +268,46 @@ namespace CustomInterfaces } } + /** + * Handles a request to preview the symmetrise. + * + * Runs Symmetrise on the current spectrum and plots in preview mini plot. + * + * @see IndirectSymmetrise::previewAlgDone() + */ void IndirectSymmetrise::preview() { + // Handle algorithm completion signal connect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + // Do nothing if no data has been laoded QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); - if(workspaceName.isEmpty()) return; + bool verbose = m_uiForm.symm_ckVerbose->isChecked(); double x_cut = m_dblManager->value(m_properties["XCut"]); + long spectrumNumber = static_cast(m_dblManager->value(m_properties["PreviewSpec"])); + std::vector spectraRange(2, spectrumNumber); + // Run the algorithm on the preview spectrum only IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); symmetriseAlg->initialize(); symmetriseAlg->setProperty("Sample", workspaceName.toStdString()); symmetriseAlg->setProperty("XCut", x_cut); symmetriseAlg->setProperty("Plot", false); - symmetriseAlg->setProperty("Verbose", false); + symmetriseAlg->setProperty("Verbose", verbose); symmetriseAlg->setProperty("Save", false); + symmetriseAlg->setProperty("SpectraRange", spectraRange); symmetriseAlg->setProperty("OutputWorkspace", "__Symmetrise_temp"); symmetriseAlg->setProperty("OutputPropertiesTable", "__SymmetriseProps_temp"); runAlgorithm(symmetriseAlg); } + /** + * Handles completion of the preview algorithm. + */ void IndirectSymmetrise::previewAlgDone(bool error) { if(error) @@ -270,23 +318,31 @@ namespace CustomInterfaces MatrixWorkspace_sptr sampleWS = AnalysisDataService::Instance().retrieveWS(workspaceName.toStdString()); ITableWorkspace_sptr propsTable = AnalysisDataService::Instance().retrieveWS("__SymmetriseProps_temp"); + MatrixWorkspace_sptr symmWS = AnalysisDataService::Instance().retrieveWS("__Symmetrise_temp"); + // Get the index of XCut on each side of zero int negativeIndex = propsTable->getColumn("NegativeCutIndex")->cell(0); int positiveIndex = propsTable->getColumn("PositiveCutIndex")->cell(0); + // Get the Y values for each XCut and the difference between them double negativeY = sampleWS->dataY(0)[negativeIndex]; double positiveY = sampleWS->dataY(0)[positiveIndex]; double deltaY = fabs(negativeY - positiveY); + // Show values in property tree m_dblManager->setValue(m_properties["NegativeYValue"], negativeY); m_dblManager->setValue(m_properties["PositiveYValue"], positiveY); m_dblManager->setValue(m_properties["DeltaY"], deltaY); + // Set indicator positions m_rangeSelectors["NegativeXCutYPos"]->setMinimum(negativeY); m_rangeSelectors["PositiveXCutYPos"]->setMinimum(positiveY); - plotMiniPlot("__Symmetrise_temp", spectrumNumber, "SymmPreviewPlot"); + // Plot preview plot + size_t spectrumIndex = symmWS->getIndexFromSpectrumNumber(spectrumNumber); + plotMiniPlot("__Symmetrise_temp", spectrumIndex, "SymmPreviewPlot"); + // Don't want this to trigger when the algorithm is run for all spectra disconnect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); } From 58fffdb3b1f8f31cd5b7477a636f501dc5637f86 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 4 Sep 2014 16:15:01 +0100 Subject: [PATCH 20/46] Fix compile issue with algorithm runner Refs #7860 --- .../inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h | 4 ++-- .../CustomInterfaces/src/IndirectDataReductionTab.cpp | 6 +++--- .../MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h index 816d12016471..07b5210d5f81 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReductionTab.h @@ -135,8 +135,8 @@ namespace CustomInterfaces /// Double editor facotry for the properties browser DoubleEditorFactory* m_dblEdFac; - /// Algorithm runner object to execute algorithms on a seperate thread from the gui - MantidQt::API::AlgorithmRunner* m_algRunner; + /// Algorithm runner object to execute algorithms on a seperate thread from the GUI + MantidQt::API::AlgorithmRunner m_algRunner; /// Use a Python runner for when we need the output of a script MantidQt::API::PythonRunner m_pythonRunner; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp index 830928f6edc1..51b32e730922 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp @@ -19,11 +19,11 @@ namespace CustomInterfaces m_properties(), m_dblManager(new QtDoublePropertyManager()), m_blnManager(new QtBoolPropertyManager()), m_grpManager(new QtGroupPropertyManager()), m_dblEdFac(new DoubleEditorFactory()), + m_algRunner(NULL), m_uiForm(uiForm) { m_parentWidget = dynamic_cast(parent); - m_algRunner = new MantidQt::API::AlgorithmRunner(m_parentWidget); m_valInt = new QIntValidator(m_parentWidget); m_valDbl = new QDoubleValidator(m_parentWidget); m_valPosDbl = new QDoubleValidator(m_parentWidget); @@ -31,7 +31,7 @@ namespace CustomInterfaces const double tolerance = 0.00001; m_valPosDbl->setBottom(tolerance); - QObject::connect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(algorithmFinished(bool))); + connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(algorithmFinished(bool))); connect(&m_pythonRunner, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); } @@ -303,7 +303,7 @@ namespace CustomInterfaces void IndirectDataReductionTab::runAlgorithm(const Mantid::API::IAlgorithm_sptr algorithm) { algorithm->setRethrows(true); - m_algRunner->startAlgorithm(algorithm); + m_algRunner.startAlgorithm(algorithm); } /** diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index c8d1ce0d1380..7797a92de31b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -278,7 +278,7 @@ namespace CustomInterfaces void IndirectSymmetrise::preview() { // Handle algorithm completion signal - connect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); // Do nothing if no data has been laoded QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); @@ -343,7 +343,7 @@ namespace CustomInterfaces plotMiniPlot("__Symmetrise_temp", spectrumIndex, "SymmPreviewPlot"); // Don't want this to trigger when the algorithm is run for all spectra - disconnect(m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); } } // namespace CustomInterfaces From 7e2752fd43fa43aa2263d6abcb3be6aebe852860 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 9 Sep 2014 11:26:59 +0100 Subject: [PATCH 21/46] Remove need for algorithm runner for now Refs #7860 --- .../MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 7797a92de31b..4f88573c5f21 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -278,7 +278,8 @@ namespace CustomInterfaces void IndirectSymmetrise::preview() { // Handle algorithm completion signal - connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + // TODO: Temp. removal to checkbuild #10092 + /* connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); */ // Do nothing if no data has been laoded QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); @@ -343,7 +344,8 @@ namespace CustomInterfaces plotMiniPlot("__Symmetrise_temp", spectrumIndex, "SymmPreviewPlot"); // Don't want this to trigger when the algorithm is run for all spectra - disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + // TODO: Temp. removal to checkbuild #10092 + /* disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); */ } } // namespace CustomInterfaces From f273d2357428d5b7e219fb873468d3a1c46ef01e Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 09:58:16 +0100 Subject: [PATCH 22/46] Added X min and max values to algorithm Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 127 ++++++++++++------ .../src/IndirectSymmetrise.cpp | 33 +++-- 2 files changed, 109 insertions(+), 51 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index b915fc158f38..44e000f5f4a7 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -1,7 +1,7 @@ from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty, PropertyMode from mantid.kernel import Direction, IntArrayProperty, IntArrayMandatoryValidator -from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed, CreateEmptyTableWorkspace +from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed, CreateEmptyTableWorkspace, RenameWorkspace import math import os.path @@ -19,7 +19,12 @@ def summary(self): def PyInit(self): self.declareProperty(WorkspaceProperty('Sample', '', Direction.Input), doc='Sample to run with') - self.declareProperty('XCut', 0.0, doc='X cut off value') + + self.declareProperty(IntArrayProperty(name='SpectraRange'), + doc='Range of spectra to symmetrise (defaults to entire range if not set)') + + self.declareProperty('XMin', 0.0, doc='X value marking lower limit of curve to copy') + self.declareProperty('XMax', 0.0, doc='X value marking upper limit of curve to copy') self.declareProperty('Verbose', defaultValue=False, doc='Switch verbose output Off/On') @@ -28,9 +33,6 @@ def PyInit(self): self.declareProperty('Save', defaultValue=False, doc='Switch saving result to nxs file Off/On') - self.declareProperty(IntArrayProperty(name='SpectraRange'), - doc='Range of spectra to symmetrise (defaults to entire range if not set)') - self.declareProperty(WorkspaceProperty('OutputWorkspace', '', Direction.Output), doc='Name to call the output workspace.') @@ -42,6 +44,7 @@ def PyExec(self): StartTime('Symmetrise') self._setup() + temp_ws_name = '__Symmetrise_temp' # The number of spectra that will actually be changed num_symm_spectra = self._spectra_range[1] - self._spectra_range[0] + 1 @@ -53,42 +56,42 @@ def PyExec(self): sample_array_len = min(len_x, len_y, len_e) - 1 sample_x = mtd[self._sample].readX(0) - delta_x = sample_x[1] - sample_x[0] - - # Find array index of negative XCut - negative_diff = np.absolute(sample_x + self._x_cut) - self._negative_index = np.where(negative_diff < delta_x)[0][-1] - self._check_bounds(self._negative_index, sample_array_len, label='Negative') - - # Find array index of positive XCut - positive_diff = np.absolute(sample_x + sample_x[self._negative_index]) - self._positive_index = np.where(positive_diff < delta_x)[0][-1] - self._check_bounds(self._positive_index, sample_array_len, label='Positive') + self._calculate_array_points(sample_x, sample_array_len) # Calculate number of elements needed for new array (per spectra) - new_array_len = 2 * sample_array_len - (self._positive_index + self._negative_index) + 1 + new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) + 1 if self._verbose: logger.notice('No. points = %d' % sample_array_len) - logger.notice('Negative at i=%d, x=%f' - % (self._negative_index, sample_x[self._negative_index])) - logger.notice('Positive at i=%d, x=%f' - % (self._positive_index, sample_x[self._positive_index])) logger.notice('New array size = %d' % new_array_len) + logger.notice('Negative X min at i=%d, x=%f' + % (self._negative_min_index, sample_x[self._negative_min_index])) + logger.notice('Positive X min at i=%d, x=%f' + % (self._positive_min_index, sample_x[self._positive_min_index])) + + if self._negative_max_index is None: + logger.notice('No negative X max found') + else: + logger.notice('Negative X max at i=%d, x=%f' + % (self._negative_max_index, sample_x[self._negative_max_index])) + + logger.notice('Positive X max at i=%d, x=%f' + % (self._positive_max_index, sample_x[self._positive_max_index])) + x_unit = mtd[self._sample].getXDimension().getUnits() # Create an empty workspace with enough storage for the new data zeros = np.zeros(new_array_len * num_symm_spectra) - CreateWorkspace(OutputWorkspace=self._output_workspace, + CreateWorkspace(OutputWorkspace=temp_ws_name, DataX=zeros, DataY=zeros, DataE=zeros, NSpec=num_symm_spectra, UnitX=x_unit) # Copy logs and properties from sample workspace - CopyLogs(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) - # CopySample(InputWorkspace=self._sample, OutputWorkspace=self._output_workspace) + CopyLogs(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) + CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) + # CopySample(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) # For each spectrum copy positive values to the negative output_spectrum_index = 0 @@ -107,27 +110,29 @@ def PyExec(self): e_out = np.zeros(new_array_len) # Left hand side of cut - x_out[:sample_array_len - self._positive_index] = -x_in[sample_array_len:self._positive_index:-1] - y_out[:sample_array_len - self._positive_index] = y_in[sample_array_len:self._positive_index:-1] - e_out[:sample_array_len - self._positive_index] = e_in[sample_array_len:self._positive_index:-1] + x_out[:sample_array_len - self._positive_min_index] = -x_in[sample_array_len:self._positive_min_index:-1] + y_out[:sample_array_len - self._positive_min_index] = y_in[sample_array_len:self._positive_min_index:-1] + e_out[:sample_array_len - self._positive_min_index] = e_in[sample_array_len:self._positive_min_index:-1] # Right hand side of cut - x_out[sample_array_len - self._positive_index:] = x_in[self._negative_index:] - y_out[sample_array_len - self._positive_index:] = y_in[self._negative_index:] - e_out[sample_array_len - self._positive_index:] = e_in[self._negative_index:] + x_out[sample_array_len - self._positive_min_index:] = x_in[self._negative_min_index:] + y_out[sample_array_len - self._positive_min_index:] = y_in[self._negative_min_index:] + e_out[sample_array_len - self._positive_min_index:] = e_in[self._negative_min_index:] # Set output spectrum data - mtd[self._output_workspace].setX(output_spectrum_index, x_out) - mtd[self._output_workspace].setY(output_spectrum_index, y_out) - mtd[self._output_workspace].setE(output_spectrum_index, e_out) + mtd[temp_ws_name].setX(output_spectrum_index, x_out) + mtd[temp_ws_name].setY(output_spectrum_index, y_out) + mtd[temp_ws_name].setE(output_spectrum_index, e_out) # Set output spectrum number - mtd[self._output_workspace].getSpectrum(output_spectrum_index).setSpectrumNo(spectrum_no) + mtd[temp_ws_name].getSpectrum(output_spectrum_index).setSpectrumNo(spectrum_no) output_spectrum_index += 1 logger.information('Symmetrise spectra %d' % spectrum_no) + RenameWorkspace(InputWorkspace=temp_ws_name, OutputWorkspace=self._output_workspace) + if self._save: self._save_output() @@ -153,10 +158,16 @@ def _setup(self): min_spectra_number = mtd[self._sample].getSpectrum(0).getSpectrumNo() max_spectra_number = mtd[self._sample].getSpectrum(num_sample_spectra - 1).getSpectrumNo() - self._x_cut = self.getProperty('XCut').value + self._x_min = math.fabs(self.getProperty('XMin').value) + self._x_max = math.fabs(self.getProperty('XMax').value) + + if self._x_min < 1e-5: + raise ValueError('XMin point is Zero') + if self._x_max < 1e-5: + raise ValueError('XMax point is Zero') - if math.fabs(self._x_cut) < 1e-5: - raise ValueError('XCut point is Zero') + if math.fabs(self._x_max - self._x_min) < 1e-5: + raise ValueError('X range is Zero') self._verbose = self.getProperty('Verbose').value self._plot = self.getProperty('Plot').value @@ -176,6 +187,35 @@ def _setup(self): self._output_workspace = self.getPropertyValue('OutputWorkspace') self._props_output_workspace = self.getPropertyValue('OutputPropertiesTable') + def _calculate_array_points(self, sample_x, sample_array_len): + """ + Finds the points in the array that match the cut points. + """ + delta_x = sample_x[1] - sample_x[0] + + # Find array index of negative XMin + negative_min_diff = np.absolute(sample_x + self._x_min) + self._negative_min_index = np.where(negative_min_diff < delta_x)[0][-1] + self._check_bounds(self._negative_min_index, sample_array_len, label='Negative') + + # Find array index of positive XMin + positive_min_diff = np.absolute(sample_x + sample_x[self._negative_min_index]) + self._positive_min_index = np.where(positive_min_diff < delta_x)[0][-1] + self._check_bounds(self._positive_min_index, sample_array_len, label='Positive') + + # Find array index of positive XMax + positive_max_diff = np.absolute(sample_x - self._x_max) + self._positive_max_index = np.where(positive_max_diff < delta_x)[0][-1] + self._check_bounds(self._positive_max_index, sample_array_len, label='Positive') + + # Find array index of negative XMax + if -self._x_max < sample_x[0]: + self._negative_max_index = None; + else: + negative_max_diff = np.absolute(sample_x + sample_x[self._positive_max_index]) + self._negative_max_index = np.where(negative_max_diff < delta_x)[0][-1] + self._check_bounds(self._negative_max_index, sample_array_len, label='Negative') + def _check_bounds(self, index, num_pts, label=''): """ Check if the index falls within the bounds of the x range. @@ -196,10 +236,15 @@ def _generate_props_table(self): """ props_table = CreateEmptyTableWorkspace(OutputWorkspace=self._props_output_workspace) - props_table.addColumn('int', 'NegativeCutIndex') - props_table.addColumn('int', 'PositiveCutIndex') + props_table.addColumn('int', 'NegativeXMinIndex') + props_table.addColumn('int', 'PositiveXMinIndex') + props_table.addColumn('int', 'NegativeXMaxIndex') + props_table.addColumn('int', 'PositiveXMaxIndex') - props_table.addRow([self._negative_index, self._positive_index]) + if self._negative_max_index is None: + props_table.addRow([self._negative_min_index, self._positive_min_index, -1, self._positive_max_index]) + else: + props_table.addRow([self._negative_min_index, self._positive_min_index, self._negative_max_index, self._positive_max_index]) self.setProperty('OutputPropertiesTable', self._props_output_workspace) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 4f88573c5f21..74f435f26f6c 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -36,8 +36,10 @@ namespace CustomInterfaces m_propTrees["SymmPropTree"]->setFactoryForManager(m_dblManager, doubleEditorFactory); // Raw Properties - m_properties["XCut"] = m_dblManager->addProperty("X Cut"); - m_propTrees["SymmPropTree"]->addProperty(m_properties["XCut"]); + m_properties["EMin"] = m_dblManager->addProperty("EMin"); + m_propTrees["SymmPropTree"]->addProperty(m_properties["EMin"]); + m_properties["EMax"] = m_dblManager->addProperty("EMax"); + m_propTrees["SymmPropTree"]->addProperty(m_properties["EMax"]); QtProperty* rawPlotProps = m_grpManager->addProperty("Raw Plot"); m_propTrees["SymmPropTree"]->addProperty(rawPlotProps); @@ -134,7 +136,8 @@ namespace CustomInterfaces connect(m_uiForm.symm_previewButton, SIGNAL(clicked()), this, SLOT(preview())); // Set default XCut value - m_dblManager->setValue(m_properties["XCut"], 0.3); + m_dblManager->setValue(m_properties["EMin"], 0.1); + m_dblManager->setValue(m_properties["EMax"], 0.5); // Set default x axis range std::pair defaultRange(-1.0, 1.0); @@ -159,8 +162,10 @@ namespace CustomInterfaces if(!m_uiForm.symm_dsInput->isValid()) return false; - // Check for a valid XCut value - if(m_dblManager->value(m_properties["XCut"]) <= 0.0) + // EMin and EMax must be positive + if(m_dblManager->value(m_properties["EMin"]) <= 0.0) + return false; + if(m_dblManager->value(m_properties["EMax"]) <= 0.0) return false; return true; @@ -175,12 +180,14 @@ namespace CustomInterfaces bool verbose = m_uiForm.symm_ckVerbose->isChecked(); bool save = m_uiForm.symm_ckSave->isChecked(); - double x_cut = m_dblManager->value(m_properties["XCut"]); + double e_min = m_dblManager->value(m_properties["XEMin"]); + double e_max = m_dblManager->value(m_properties["XEMax"]); IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); symmetriseAlg->initialize(); symmetriseAlg->setProperty("Sample", workspaceName.toStdString()); - symmetriseAlg->setProperty("XCut", x_cut); + symmetriseAlg->setProperty("XMin", e_min); + symmetriseAlg->setProperty("XMax", e_max); symmetriseAlg->setProperty("Plot", plot); symmetriseAlg->setProperty("Verbose", verbose); symmetriseAlg->setProperty("Save", save); @@ -258,7 +265,7 @@ namespace CustomInterfaces */ void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) { - if(prop == m_properties["XCut"]) + if(prop == m_properties["EMin"]) { m_rangeSelectors["NegativeXCut_Raw"]->setMinimum(-value); m_rangeSelectors["PositiveXCut_Raw"]->setMinimum(value); @@ -266,6 +273,10 @@ namespace CustomInterfaces m_rangeSelectors["NegativeXCut_PV"]->setMinimum(-value); m_rangeSelectors["PositiveXCut_PV"]->setMinimum(value); } + + if(prop == m_properties["EMax"]) + { + } } /** @@ -287,7 +298,8 @@ namespace CustomInterfaces return; bool verbose = m_uiForm.symm_ckVerbose->isChecked(); - double x_cut = m_dblManager->value(m_properties["XCut"]); + double e_min = m_dblManager->value(m_properties["EMin"]); + double e_max = m_dblManager->value(m_properties["EMax"]); long spectrumNumber = static_cast(m_dblManager->value(m_properties["PreviewSpec"])); std::vector spectraRange(2, spectrumNumber); @@ -295,7 +307,8 @@ namespace CustomInterfaces IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); symmetriseAlg->initialize(); symmetriseAlg->setProperty("Sample", workspaceName.toStdString()); - symmetriseAlg->setProperty("XCut", x_cut); + symmetriseAlg->setProperty("XMin", e_min); + symmetriseAlg->setProperty("XMax", e_max); symmetriseAlg->setProperty("Plot", false); symmetriseAlg->setProperty("Verbose", verbose); symmetriseAlg->setProperty("Save", false); From 199578322228d8ba60f369ed2e2f2d16316a7cba Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 10:26:24 +0100 Subject: [PATCH 23/46] Implemented X range selection, updated docs Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 29 ++++++++++++------- .../docs/source/algorithms/Symmetrise-v1.rst | 11 +++++-- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 44e000f5f4a7..3538d9a740b8 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -59,11 +59,15 @@ def PyExec(self): self._calculate_array_points(sample_x, sample_array_len) # Calculate number of elements needed for new array (per spectra) - new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) + 1 + # TODO: This can be simplified a lot + new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - 2 * (sample_array_len - self._positive_max_index) + 1 + + # Calculate the position in the output array to split between the LHS reflected betwen +XMin and +XMax and + # the LHS copied frim -XMin and +XMax + output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) if self._verbose: - logger.notice('No. points = %d' % sample_array_len) - logger.notice('New array size = %d' % new_array_len) + logger.notice('Sample array length = %d' % sample_array_len) logger.notice('Negative X min at i=%d, x=%f' % (self._negative_min_index, sample_x[self._negative_min_index])) @@ -79,6 +83,9 @@ def PyExec(self): logger.notice('Positive X max at i=%d, x=%f' % (self._positive_max_index, sample_x[self._positive_max_index])) + logger.notice('New array length = %d' % new_array_len) + logger.notice('Output array LR split index = %d' % output_cut_index) + x_unit = mtd[self._sample].getXDimension().getUnits() # Create an empty workspace with enough storage for the new data @@ -109,15 +116,15 @@ def PyExec(self): y_out = np.zeros(new_array_len) e_out = np.zeros(new_array_len) - # Left hand side of cut - x_out[:sample_array_len - self._positive_min_index] = -x_in[sample_array_len:self._positive_min_index:-1] - y_out[:sample_array_len - self._positive_min_index] = y_in[sample_array_len:self._positive_min_index:-1] - e_out[:sample_array_len - self._positive_min_index] = e_in[sample_array_len:self._positive_min_index:-1] + # Left hand side + x_out[:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] + y_out[:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] + e_out[:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] - # Right hand side of cut - x_out[sample_array_len - self._positive_min_index:] = x_in[self._negative_min_index:] - y_out[sample_array_len - self._positive_min_index:] = y_in[self._negative_min_index:] - e_out[sample_array_len - self._positive_min_index:] = e_in[self._negative_min_index:] + # Right hand side + x_out[output_cut_index:] = x_in[self._negative_min_index:self._positive_max_index] + y_out[output_cut_index:] = y_in[self._negative_min_index:self._positive_max_index] + e_out[output_cut_index:] = e_in[self._negative_min_index:self._positive_max_index] # Set output spectrum data mtd[temp_ws_name].setX(output_spectrum_index, x_out) diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index 3c5704b229f6..9c799dbf8247 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -10,9 +10,14 @@ Description ----------- Symmetrise takes an asymmetric :math:`S(Q,w)` - i.e. one in which the -moduli of xmin & xmax are different. Typically xmax is > mod(xmin). A -negative value of x is chosen (Xcut) so that the curve for mod(Xcut) to -xmax is reflected and inserted for x less than the Xcut. +moduli of xmin & xmax are different. Typically xmax is > mod(xmin). + +Two values, XMin and XMax, are chosen to specify the section of the positive +side of the curve to be reflected onto the negative side. + +The output curve between negative XMin and XMax is unchnaged from the sample +curve, between negative XMax and negative XMin the curve is reflected from +the sample curve between XMin and XMax. Usage ----- From 754fdafff4c339b834c4e2bdf3b8b54e4bcf6c72 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 12:16:07 +0100 Subject: [PATCH 24/46] Made symmetrise work as intended, updated docs Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 54 +++++++++----- .../src/IndirectSymmetrise.cpp | 73 ++++++++++++------- .../docs/source/algorithms/Symmetrise-v1.rst | 19 ++++- 3 files changed, 97 insertions(+), 49 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 3538d9a740b8..178740b3e1ee 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -58,13 +58,14 @@ def PyExec(self): sample_x = mtd[self._sample].readX(0) self._calculate_array_points(sample_x, sample_array_len) - # Calculate number of elements needed for new array (per spectra) - # TODO: This can be simplified a lot - new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - 2 * (sample_array_len - self._positive_max_index) + 1 - - # Calculate the position in the output array to split between the LHS reflected betwen +XMin and +XMax and - # the LHS copied frim -XMin and +XMax - output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) + copy_lhs = sample_x[0] < -sample_x[self._positive_max_index] + if copy_lhs: + lhs_cut_index = self._negative_max_index + output_cut_index = lhs_cut_index + (self._positive_max_index - self._positive_min_index) + new_array_len = output_cut_index + (sample_array_len - self._negative_min_index) + 1 + else: + new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - (sample_array_len - self._positive_max_index) + 1 + output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) if self._verbose: logger.notice('Sample array length = %d' % sample_array_len) @@ -78,12 +79,18 @@ def PyExec(self): logger.notice('No negative X max found') else: logger.notice('Negative X max at i=%d, x=%f' - % (self._negative_max_index, sample_x[self._negative_max_index])) - + % (self._negative_max_index, sample_x[self._negative_max_index])) logger.notice('Positive X max at i=%d, x=%f' % (self._positive_max_index, sample_x[self._positive_max_index])) logger.notice('New array length = %d' % new_array_len) + + if copy_lhs: + logger.notice('LHS: Copy + Reflect') + logger.notice('LHS cut index = %d' % lhs_cut_index) + else: + logger.notice('LHS: Reflect Only') + logger.notice('Output array LR split index = %d' % output_cut_index) x_unit = mtd[self._sample].getXDimension().getUnits() @@ -116,15 +123,26 @@ def PyExec(self): y_out = np.zeros(new_array_len) e_out = np.zeros(new_array_len) - # Left hand side - x_out[:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] - y_out[:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] - e_out[:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] + if copy_lhs: + # Left hand side (reflected) + x_out[lhs_cut_index:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] + y_out[lhs_cut_index:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] + e_out[lhs_cut_index:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] + + # Left hand side (copied) + x_out[:lhs_cut_index] = x_in[:self._negative_max_index] + y_out[:lhs_cut_index] = y_in[:self._negative_max_index] + e_out[:lhs_cut_index] = e_in[:self._negative_max_index] + else: + # Left hand side (reflected) + x_out[:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] + y_out[:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] + e_out[:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] - # Right hand side - x_out[output_cut_index:] = x_in[self._negative_min_index:self._positive_max_index] - y_out[output_cut_index:] = y_in[self._negative_min_index:self._positive_max_index] - e_out[output_cut_index:] = e_in[self._negative_min_index:self._positive_max_index] + # Right hand side (copied) + x_out[output_cut_index:] = x_in[self._negative_min_index:] + y_out[output_cut_index:] = y_in[self._negative_min_index:] + e_out[output_cut_index:] = e_in[self._negative_min_index:] # Set output spectrum data mtd[temp_ws_name].setX(output_spectrum_index, x_out) @@ -232,7 +250,7 @@ def _check_bounds(self, index, num_pts, label=''): @param num_pts - total number of points in the range. @param label - label to call the point if an error is thrown. """ - if index <= 0: + if index < 0: raise ValueError('%s point %d < 0' % (label, index)) elif index >= num_pts: raise ValueError('%s point %d > %d' % (label, index, num_pts)) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 74f435f26f6c..ff43d3d54aec 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -66,25 +66,31 @@ namespace CustomInterfaces m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmRawPlot"] = new QwtPlotCurve(); - // Indicators for negative and positive XCut values on X axis - m_rangeSelectors["NegativeXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + // Indicators for negative and positive X range values on X axis + m_rangeSelectors["NegativeEMin_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["PositiveXCut_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + m_rangeSelectors["PositiveEMin_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["NegativeEMax_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, false); + m_rangeSelectors["PositiveEMax_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["NegativeXCut_Raw"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveXCut_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["NegativeEMin_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveEMin_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["NegativeEMax_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveEMax_Raw"]->setColour(Qt::darkGreen); - // Indicators for Y value at each XCut position - m_rangeSelectors["NegativeXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + // Indicators for Y value at each EMin position + m_rangeSelectors["NegativeEMinYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::YSINGLE, true, false); - m_rangeSelectors["PositiveXCutYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], + m_rangeSelectors["PositiveEMinYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], MantidWidgets::RangeSelector::YSINGLE, true, false); - m_rangeSelectors["NegativeXCutYPos"]->setColour(Qt::red); - m_rangeSelectors["PositiveXCutYPos"]->setColour(Qt::blue); - m_rangeSelectors["NegativeXCutYPos"]->setMinimum(0); - m_rangeSelectors["PositiveXCutYPos"]->setMinimum(0); + m_rangeSelectors["NegativeEMinYPos"]->setColour(Qt::red); + m_rangeSelectors["PositiveEMinYPos"]->setColour(Qt::blue); + m_rangeSelectors["NegativeEMinYPos"]->setMinimum(0); + m_rangeSelectors["PositiveEMinYPos"]->setMinimum(0); // Indicator for centre of symmetry (x=0) m_rangeSelectors["CentreMark_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], @@ -101,14 +107,20 @@ namespace CustomInterfaces m_plots["SymmPreviewPlot"] = new QwtPlot(m_parentWidget); m_curves["SymmPreviewPlot"] = new QwtPlotCurve(); - // Indicators for negative and positive XCut values on X axis - m_rangeSelectors["NegativeXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + // Indicators for negative and positive X range values on X axis + m_rangeSelectors["NegativeEMin_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["PositiveEMin_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["NegativeEMax_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["PositiveXCut_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + m_rangeSelectors["PositiveEMax_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["NegativeXCut_PV"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveXCut_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["NegativeEMin_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveEMin_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["NegativeEMax_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveEMax_PV"]->setColour(Qt::darkGreen); // Indicator for centre of symmetry (x=0) m_rangeSelectors["CentreMark_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], @@ -135,7 +147,7 @@ namespace CustomInterfaces // Preview symmetrise connect(m_uiForm.symm_previewButton, SIGNAL(clicked()), this, SLOT(preview())); - // Set default XCut value + // Set default X range values m_dblManager->setValue(m_properties["EMin"], 0.1); m_dblManager->setValue(m_properties["EMax"], 0.5); @@ -180,8 +192,8 @@ namespace CustomInterfaces bool verbose = m_uiForm.symm_ckVerbose->isChecked(); bool save = m_uiForm.symm_ckSave->isChecked(); - double e_min = m_dblManager->value(m_properties["XEMin"]); - double e_max = m_dblManager->value(m_properties["XEMax"]); + double e_min = m_dblManager->value(m_properties["EMin"]); + double e_max = m_dblManager->value(m_properties["EMax"]); IAlgorithm_sptr symmetriseAlg = AlgorithmManager::Instance().create("Symmetrise", -1); symmetriseAlg->initialize(); @@ -267,15 +279,20 @@ namespace CustomInterfaces { if(prop == m_properties["EMin"]) { - m_rangeSelectors["NegativeXCut_Raw"]->setMinimum(-value); - m_rangeSelectors["PositiveXCut_Raw"]->setMinimum(value); + m_rangeSelectors["NegativeEMin_Raw"]->setMinimum(-value); + m_rangeSelectors["PositiveEMin_Raw"]->setMinimum(value); - m_rangeSelectors["NegativeXCut_PV"]->setMinimum(-value); - m_rangeSelectors["PositiveXCut_PV"]->setMinimum(value); + m_rangeSelectors["NegativeEMin_PV"]->setMinimum(-value); + m_rangeSelectors["PositiveEMin_PV"]->setMinimum(value); } if(prop == m_properties["EMax"]) { + m_rangeSelectors["NegativeEMax_Raw"]->setMinimum(-value); + m_rangeSelectors["PositiveEMax_Raw"]->setMinimum(value); + + m_rangeSelectors["NegativeEMax_PV"]->setMinimum(-value); + m_rangeSelectors["PositiveEMax_PV"]->setMinimum(value); } } @@ -290,7 +307,7 @@ namespace CustomInterfaces { // Handle algorithm completion signal // TODO: Temp. removal to checkbuild #10092 - /* connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); */ + connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); // Do nothing if no data has been laoded QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); @@ -349,8 +366,8 @@ namespace CustomInterfaces m_dblManager->setValue(m_properties["DeltaY"], deltaY); // Set indicator positions - m_rangeSelectors["NegativeXCutYPos"]->setMinimum(negativeY); - m_rangeSelectors["PositiveXCutYPos"]->setMinimum(positiveY); + m_rangeSelectors["NegativeEMinYPos"]->setMinimum(negativeY); + m_rangeSelectors["PositiveEMinYPos"]->setMinimum(positiveY); // Plot preview plot size_t spectrumIndex = symmWS->getIndexFromSpectrumNumber(spectrumNumber); @@ -358,7 +375,7 @@ namespace CustomInterfaces // Don't want this to trigger when the algorithm is run for all spectra // TODO: Temp. removal to checkbuild #10092 - /* disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); */ + disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); } } // namespace CustomInterfaces diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index 9c799dbf8247..f256f0dfdabb 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -15,9 +15,22 @@ moduli of xmin & xmax are different. Typically xmax is > mod(xmin). Two values, XMin and XMax, are chosen to specify the section of the positive side of the curve to be reflected onto the negative side. -The output curve between negative XMin and XMax is unchnaged from the sample -curve, between negative XMax and negative XMin the curve is reflected from -the sample curve between XMin and XMax. +Depending on the input curve and EMax parameter the algorithm can behave in +two ways: + +Reflect Left Hand Side +^^^^^^^^^^^^^^^^^^^^^^ + +If negative XMax is less than the lowest X value on the curve then the positive +section of the curve between XMin and XMax will be reflected to the negative side, +appending the curve to the left hand side. + +Copy and Reflect Left Hand Side +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If negative XMax is greater than the lowest value on the curve then the positive +section of the curve between XMin and XMax is reflected on to the negative side, +the curve between negative XMax and the loest X value will remain unchanged. Usage ----- From aabc0c0189575328005e47a711eb86c8850577b0 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 12:27:14 +0100 Subject: [PATCH 25/46] Small refactoring, small docs change Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 23 ++++++++----------- .../docs/source/algorithms/Symmetrise-v1.rst | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 178740b3e1ee..02a4e28019e8 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -58,39 +58,36 @@ def PyExec(self): sample_x = mtd[self._sample].readX(0) self._calculate_array_points(sample_x, sample_array_len) - copy_lhs = sample_x[0] < -sample_x[self._positive_max_index] - if copy_lhs: + if self._negative_max_index is not None: lhs_cut_index = self._negative_max_index output_cut_index = lhs_cut_index + (self._positive_max_index - self._positive_min_index) new_array_len = output_cut_index + (sample_array_len - self._negative_min_index) + 1 else: - new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - (sample_array_len - self._positive_max_index) + 1 output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) + new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - (sample_array_len - self._positive_max_index) + 1 if self._verbose: logger.notice('Sample array length = %d' % sample_array_len) - logger.notice('Negative X min at i=%d, x=%f' - % (self._negative_min_index, sample_x[self._negative_min_index])) logger.notice('Positive X min at i=%d, x=%f' % (self._positive_min_index, sample_x[self._positive_min_index])) + logger.notice('Negative X min at i=%d, x=%f' + % (self._negative_min_index, sample_x[self._negative_min_index])) - if self._negative_max_index is None: - logger.notice('No negative X max found') - else: - logger.notice('Negative X max at i=%d, x=%f' - % (self._negative_max_index, sample_x[self._negative_max_index])) logger.notice('Positive X max at i=%d, x=%f' % (self._positive_max_index, sample_x[self._positive_max_index])) - logger.notice('New array length = %d' % new_array_len) + if self._negative_max_index is not None: + logger.notice('Negative X max at i=%d, x=%f' + % (self._negative_max_index, sample_x[self._negative_max_index])) - if copy_lhs: logger.notice('LHS: Copy + Reflect') logger.notice('LHS cut index = %d' % lhs_cut_index) else: + logger.notice('No negative X max found') logger.notice('LHS: Reflect Only') + logger.notice('New array length = %d' % new_array_len) logger.notice('Output array LR split index = %d' % output_cut_index) x_unit = mtd[self._sample].getXDimension().getUnits() @@ -123,7 +120,7 @@ def PyExec(self): y_out = np.zeros(new_array_len) e_out = np.zeros(new_array_len) - if copy_lhs: + if self._negative_max_index is not None: # Left hand side (reflected) x_out[lhs_cut_index:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] y_out[lhs_cut_index:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index f256f0dfdabb..19e496055dfc 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -15,7 +15,7 @@ moduli of xmin & xmax are different. Typically xmax is > mod(xmin). Two values, XMin and XMax, are chosen to specify the section of the positive side of the curve to be reflected onto the negative side. -Depending on the input curve and EMax parameter the algorithm can behave in +Depending on the input curve and XMax parameter the algorithm can behave in two ways: Reflect Left Hand Side From 35b8bec01d70839c04261d341e8350fce4f74788 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 15:17:23 +0100 Subject: [PATCH 26/46] Made range selectors select X range, couple of fixes in alg Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 8 +- .../IndirectSymmetrise.h | 2 + .../src/IndirectSymmetrise.cpp | 168 +++++++++++------- 3 files changed, 107 insertions(+), 71 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 02a4e28019e8..97a8e78e0af7 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -44,7 +44,7 @@ def PyExec(self): StartTime('Symmetrise') self._setup() - temp_ws_name = '__Symmetrise_temp' + temp_ws_name = '__symm_temp' # The number of spectra that will actually be changed num_symm_spectra = self._spectra_range[1] - self._spectra_range[0] + 1 @@ -148,10 +148,9 @@ def PyExec(self): # Set output spectrum number mtd[temp_ws_name].getSpectrum(output_spectrum_index).setSpectrumNo(spectrum_no) - output_spectrum_index += 1 - logger.information('Symmetrise spectra %d' % spectrum_no) + logger.information('Symmetrise spectrum %d' % spectrum_no) RenameWorkspace(InputWorkspace=temp_ws_name, OutputWorkspace=self._output_workspace) @@ -212,6 +211,9 @@ def _setup(self): def _calculate_array_points(self, sample_x, sample_array_len): """ Finds the points in the array that match the cut points. + + @param sample_x - Sample X axis data + @param sample_array_len - Lengh of data array for sample data """ delta_x = sample_x[1] - sample_x[0] diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h index 3eb019206bef..0deb19860033 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -72,6 +72,8 @@ namespace CustomInterfaces void updateRangeSelectors(QtProperty *prop, double value); void preview(); void previewAlgDone(bool error); + void xRangeMaxChanged(double value); + void xRangeMinChanged(double value); }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index ff43d3d54aec..3a7db78735f4 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -64,28 +64,16 @@ namespace CustomInterfaces // Raw plot m_plots["SymmRawPlot"] = new QwtPlot(m_parentWidget); - m_curves["SymmRawPlot"] = new QwtPlotCurve(); - - // Indicators for negative and positive X range values on X axis - m_rangeSelectors["NegativeEMin_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["PositiveEMin_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["NegativeEMax_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, false); - m_rangeSelectors["PositiveEMax_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, false); - - m_rangeSelectors["NegativeEMin_Raw"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveEMin_Raw"]->setColour(Qt::darkGreen); - m_rangeSelectors["NegativeEMax_Raw"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveEMax_Raw"]->setColour(Qt::darkGreen); + m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); + m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); + m_plots["SymmRawPlot"]->setCanvasBackground(Qt::white); + m_uiForm.symm_plot->addWidget(m_plots["SymmRawPlot"]); // Indicators for Y value at each EMin position m_rangeSelectors["NegativeEMinYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::YSINGLE, true, false); + MantidWidgets::RangeSelector::YSINGLE, true, true); m_rangeSelectors["PositiveEMinYPos"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"], - MantidWidgets::RangeSelector::YSINGLE, true, false); + MantidWidgets::RangeSelector::YSINGLE, true, true); m_rangeSelectors["NegativeEMinYPos"]->setColour(Qt::red); m_rangeSelectors["PositiveEMinYPos"]->setColour(Qt::blue); @@ -98,29 +86,31 @@ namespace CustomInterfaces m_rangeSelectors["CentreMark_Raw"]->setColour(Qt::cyan); m_rangeSelectors["CentreMark_Raw"]->setMinimum(0.0); - m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); - m_plots["SymmRawPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); - m_plots["SymmRawPlot"]->setCanvasBackground(Qt::white); - m_uiForm.symm_plot->addWidget(m_plots["SymmRawPlot"]); + // Indicators for negative and positive X range values on X axis + // The user can use these to move the X range + // Note that the max and min of the negative range selector corespond to the opposit X value + // i.e. RS min is X max + m_rangeSelectors["NegativeE_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); + m_rangeSelectors["PositiveE_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); + + m_rangeSelectors["NegativeE_Raw"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveE_Raw"]->setColour(Qt::darkGreen); // Preview plot m_plots["SymmPreviewPlot"] = new QwtPlot(m_parentWidget); - m_curves["SymmPreviewPlot"] = new QwtPlotCurve(); + m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); + m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); + m_plots["SymmPreviewPlot"]->setCanvasBackground(Qt::white); + m_uiForm.symm_previewPlot->addWidget(m_plots["SymmPreviewPlot"]); // Indicators for negative and positive X range values on X axis - m_rangeSelectors["NegativeEMin_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["PositiveEMin_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["NegativeEMax_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, true); - m_rangeSelectors["PositiveEMax_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], - MantidWidgets::RangeSelector::XSINGLE, true, true); + m_rangeSelectors["NegativeE_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XMINMAX, true, true); + m_rangeSelectors["PositiveE_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], + MantidWidgets::RangeSelector::XMINMAX, true, true); - m_rangeSelectors["NegativeEMin_PV"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveEMin_PV"]->setColour(Qt::darkGreen); - m_rangeSelectors["NegativeEMax_PV"]->setColour(Qt::darkGreen); - m_rangeSelectors["PositiveEMax_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["NegativeE_PV"]->setColour(Qt::darkGreen); + m_rangeSelectors["PositiveE_PV"]->setColour(Qt::darkGreen); // Indicator for centre of symmetry (x=0) m_rangeSelectors["CentreMark_PV"] = new MantidWidgets::RangeSelector(m_plots["SymmPreviewPlot"], @@ -128,11 +118,6 @@ namespace CustomInterfaces m_rangeSelectors["CentreMark_PV"]->setColour(Qt::cyan); m_rangeSelectors["CentreMark_PV"]->setMinimum(0.0); - m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::xBottom, parent->font()); - m_plots["SymmPreviewPlot"]->setAxisFont(QwtPlot::yLeft, parent->font()); - m_plots["SymmPreviewPlot"]->setCanvasBackground(Qt::white); - m_uiForm.symm_previewPlot->addWidget(m_plots["SymmPreviewPlot"]); - // Refresh the plot windows m_plots["SymmRawPlot"]->replot(); m_plots["SymmPreviewPlot"]->replot(); @@ -146,6 +131,11 @@ namespace CustomInterfaces connect(m_uiForm.symm_dsInput, SIGNAL(dataReady(const QString&)), this, SLOT(plotRawInput(const QString&))); // Preview symmetrise connect(m_uiForm.symm_previewButton, SIGNAL(clicked()), this, SLOT(preview())); + // X range selectors + connect(m_rangeSelectors["PositiveE_Raw"], SIGNAL(minValueChanged(double)), this, SLOT(xRangeMinChanged(double))); + connect(m_rangeSelectors["PositiveE_Raw"], SIGNAL(maxValueChanged(double)), this, SLOT(xRangeMaxChanged(double))); + connect(m_rangeSelectors["NegativeE_Raw"], SIGNAL(minValueChanged(double)), this, SLOT(xRangeMinChanged(double))); + connect(m_rangeSelectors["NegativeE_Raw"], SIGNAL(maxValueChanged(double)), this, SLOT(xRangeMaxChanged(double))); // Set default X range values m_dblManager->setValue(m_properties["EMin"], 0.1); @@ -229,6 +219,10 @@ namespace CustomInterfaces g_log.information() << "Symmetrise x axis range +/- " << symmRange << std::endl; m_dblManager->setValue(m_properties["PreviewRange"], symmRange); + // Set valid range for range selectors + m_rangeSelectors["NegativeE_Raw"]->setRange(-symmRange, 0); + m_rangeSelectors["PositiveE_Raw"]->setRange(0, symmRange); + updateMiniPlots(); } @@ -272,30 +266,6 @@ namespace CustomInterfaces updateMiniPlots(); } - /** - * Updates position of XCut range selectors when used changed value of XCut. - */ - void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) - { - if(prop == m_properties["EMin"]) - { - m_rangeSelectors["NegativeEMin_Raw"]->setMinimum(-value); - m_rangeSelectors["PositiveEMin_Raw"]->setMinimum(value); - - m_rangeSelectors["NegativeEMin_PV"]->setMinimum(-value); - m_rangeSelectors["PositiveEMin_PV"]->setMinimum(value); - } - - if(prop == m_properties["EMax"]) - { - m_rangeSelectors["NegativeEMax_Raw"]->setMinimum(-value); - m_rangeSelectors["PositiveEMax_Raw"]->setMinimum(value); - - m_rangeSelectors["NegativeEMax_PV"]->setMinimum(-value); - m_rangeSelectors["PositiveEMax_PV"]->setMinimum(value); - } - } - /** * Handles a request to preview the symmetrise. * @@ -306,7 +276,6 @@ namespace CustomInterfaces void IndirectSymmetrise::preview() { // Handle algorithm completion signal - // TODO: Temp. removal to checkbuild #10092 connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); // Do nothing if no data has been laoded @@ -338,6 +307,8 @@ namespace CustomInterfaces /** * Handles completion of the preview algorithm. + * + * @param error If the algorithm failed */ void IndirectSymmetrise::previewAlgDone(bool error) { @@ -352,8 +323,8 @@ namespace CustomInterfaces MatrixWorkspace_sptr symmWS = AnalysisDataService::Instance().retrieveWS("__Symmetrise_temp"); // Get the index of XCut on each side of zero - int negativeIndex = propsTable->getColumn("NegativeCutIndex")->cell(0); - int positiveIndex = propsTable->getColumn("PositiveCutIndex")->cell(0); + int negativeIndex = propsTable->getColumn("NegativeXMinIndex")->cell(0); + int positiveIndex = propsTable->getColumn("PositiveXMinIndex")->cell(0); // Get the Y values for each XCut and the difference between them double negativeY = sampleWS->dataY(0)[negativeIndex]; @@ -374,9 +345,70 @@ namespace CustomInterfaces plotMiniPlot("__Symmetrise_temp", spectrumIndex, "SymmPreviewPlot"); // Don't want this to trigger when the algorithm is run for all spectra - // TODO: Temp. removal to checkbuild #10092 disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); } + /** + * Updates position of XCut range selectors when used changed value of XCut. + */ + void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) + { + if(prop == m_properties["EMin"]) + { + m_rangeSelectors["NegativeE_Raw"]->setMaximum(-value); + m_rangeSelectors["PositiveE_Raw"]->setMinimum(value); + + m_rangeSelectors["NegativeE_PV"]->setMinimum(-value); + m_rangeSelectors["PositiveE_PV"]->setMinimum(value); + } + + if(prop == m_properties["EMax"]) + { + m_rangeSelectors["NegativeE_Raw"]->setMinimum(-value); + m_rangeSelectors["PositiveE_Raw"]->setMaximum(value); + + m_rangeSelectors["NegativeE_PV"]->setMaximum(-value); + m_rangeSelectors["PositiveE_PV"]->setMaximum(value); + } + } + + /** + * Handles the X minimum value being changed from a range selector. + * + * @param value New range selector value + */ + void IndirectSymmetrise::xRangeMinChanged(double value) + { + MantidWidgets::RangeSelector *from = qobject_cast(sender()); + + if(from == m_rangeSelectors["PositiveE_Raw"]) + { + m_dblManager->setValue(m_properties["EMin"], std::abs(value)); + } + else if(from == m_rangeSelectors["NegativeE_Raw"]) + { + m_dblManager->setValue(m_properties["EMax"], std::abs(value)); + } + } + + /** + * Handles the X maximum value being changed from a range selector. + * + * @param value New range selector value + */ + void IndirectSymmetrise::xRangeMaxChanged(double value) + { + MantidWidgets::RangeSelector *from = qobject_cast(sender()); + + if(from == m_rangeSelectors["PositiveE_Raw"]) + { + m_dblManager->setValue(m_properties["EMax"], std::abs(value)); + } + else if(from == m_rangeSelectors["NegativeE_Raw"]) + { + m_dblManager->setValue(m_properties["EMin"], std::abs(value)); + } + } + } // namespace CustomInterfaces } // namespace Mantid From 5411426668626000502c9996db7921ef661a1ca3 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 11 Sep 2014 16:59:57 +0100 Subject: [PATCH 27/46] Small change to naming convention for symmetrise output Refs #7860 --- .../Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 3a7db78735f4..cf5d98f31f40 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -176,7 +176,7 @@ namespace CustomInterfaces void IndirectSymmetrise::run() { QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); - QString outputWorkspaceName = workspaceName.left(workspaceName.length() - 4) + "_Symmetrise"; + QString outputWorkspaceName = workspaceName.left(workspaceName.length() - 4) + "_sym" + workspaceName.right(4); bool plot = m_uiForm.symm_ckPlot->isChecked(); bool verbose = m_uiForm.symm_ckVerbose->isChecked(); From 88a06061c69d27422b3ceefdb3f48985d84fe39b Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 17 Sep 2014 15:28:55 +0100 Subject: [PATCH 28/46] Switch Symmetrise to the batch algorithm runner Refs #7860 --- .../CustomInterfaces/src/IndirectDataReductionTab.cpp | 2 +- .../MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp index 162b1e445be1..5957a09db11a 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectDataReductionTab.cpp @@ -19,7 +19,7 @@ namespace CustomInterfaces m_properties(), m_dblManager(new QtDoublePropertyManager()), m_blnManager(new QtBoolPropertyManager()), m_grpManager(new QtGroupPropertyManager()), m_dblEdFac(new DoubleEditorFactory()), - m_algRunner(NULL), + m_batchAlgoRunner(NULL), m_uiForm(uiForm) { m_parentWidget = dynamic_cast(parent); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index cf5d98f31f40..ad74329e3ad5 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -276,7 +276,7 @@ namespace CustomInterfaces void IndirectSymmetrise::preview() { // Handle algorithm completion signal - connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(previewAlgDone(bool))); // Do nothing if no data has been laoded QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); @@ -345,7 +345,7 @@ namespace CustomInterfaces plotMiniPlot("__Symmetrise_temp", spectrumIndex, "SymmPreviewPlot"); // Don't want this to trigger when the algorithm is run for all spectra - disconnect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(previewAlgDone(bool))); + disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(previewAlgDone(bool))); } /** From 11ead26b73690d8cf3af2d51b1f3ad660d244c90 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 17 Sep 2014 15:49:11 +0100 Subject: [PATCH 29/46] Update unit test for last Symmetrise property change Refs #7860 --- .../test/python/plugins/algorithms/SymmetriseTest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py index 713c9edfa7da..81771a81f8ac 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py @@ -10,7 +10,7 @@ def setUp(self): self._sample_ws = self._generate_sample_ws('symm_test_sample_ws') def test_basic(self): - symm_test_out_ws= Symmetrise(Sample=self._sample_ws, XCut=0.05) + symm_test_out_ws= Symmetrise(Sample=self._sample_ws, XMin=0.05, XMax=0.2) def _rayleigh(self, x, sigma): return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) From 4171d9ece618d0b59fe02e46c65443e640624186 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 17 Sep 2014 16:34:14 +0100 Subject: [PATCH 30/46] FIx usage example for Symmetrise Refs #7860 --- Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index 19e496055dfc..fc13717db13f 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -51,6 +51,6 @@ Usage sample_ws = CreateWorkspace(data_x, data_y) sample_ws = ScaleX(sample_ws, -1, "Add") # centre the peak over 0 - symm_ws = Symmetrise(Sample=sample_ws, XCut=0.05) + symm_ws = Symmetrise(Sample=sample_ws, XMin=0.05, XMax=8.0) .. categories:: From 7efc8f600cbac7c69f1b860979a8268edbb5be0f Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 18 Sep 2014 10:05:46 +0100 Subject: [PATCH 31/46] Made Symmetrise crop to XMax Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 54 ++++--------------- .../docs/source/algorithms/Symmetrise-v1.rst | 20 ++----- 2 files changed, 13 insertions(+), 61 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 97a8e78e0af7..e3cbd71f9428 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -1,6 +1,6 @@ from mantid import logger, mtd from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty, PropertyMode -from mantid.kernel import Direction, IntArrayProperty, IntArrayMandatoryValidator +from mantid.kernel import Direction, IntArrayProperty from mantid.simpleapi import CreateWorkspace, CopyLogs, CopySample, CopyInstrumentParameters, SaveNexusProcessed, CreateEmptyTableWorkspace, RenameWorkspace import math @@ -58,13 +58,8 @@ def PyExec(self): sample_x = mtd[self._sample].readX(0) self._calculate_array_points(sample_x, sample_array_len) - if self._negative_max_index is not None: - lhs_cut_index = self._negative_max_index - output_cut_index = lhs_cut_index + (self._positive_max_index - self._positive_min_index) - new_array_len = output_cut_index + (sample_array_len - self._negative_min_index) + 1 - else: - output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) - new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - (sample_array_len - self._positive_max_index) + 1 + output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) + new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - 2 * (sample_array_len - self._positive_max_index) if self._verbose: logger.notice('Sample array length = %d' % sample_array_len) @@ -77,16 +72,6 @@ def PyExec(self): logger.notice('Positive X max at i=%d, x=%f' % (self._positive_max_index, sample_x[self._positive_max_index])) - if self._negative_max_index is not None: - logger.notice('Negative X max at i=%d, x=%f' - % (self._negative_max_index, sample_x[self._negative_max_index])) - - logger.notice('LHS: Copy + Reflect') - logger.notice('LHS cut index = %d' % lhs_cut_index) - else: - logger.notice('No negative X max found') - logger.notice('LHS: Reflect Only') - logger.notice('New array length = %d' % new_array_len) logger.notice('Output array LR split index = %d' % output_cut_index) @@ -120,26 +105,15 @@ def PyExec(self): y_out = np.zeros(new_array_len) e_out = np.zeros(new_array_len) - if self._negative_max_index is not None: - # Left hand side (reflected) - x_out[lhs_cut_index:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] - y_out[lhs_cut_index:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] - e_out[lhs_cut_index:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] - - # Left hand side (copied) - x_out[:lhs_cut_index] = x_in[:self._negative_max_index] - y_out[:lhs_cut_index] = y_in[:self._negative_max_index] - e_out[:lhs_cut_index] = e_in[:self._negative_max_index] - else: - # Left hand side (reflected) - x_out[:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] - y_out[:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] - e_out[:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] + # Left hand side (reflected) + x_out[:output_cut_index] = -x_in[self._positive_max_index:self._positive_min_index:-1] + y_out[:output_cut_index] = y_in[self._positive_max_index:self._positive_min_index:-1] + e_out[:output_cut_index] = e_in[self._positive_max_index:self._positive_min_index:-1] # Right hand side (copied) - x_out[output_cut_index:] = x_in[self._negative_min_index:] - y_out[output_cut_index:] = y_in[self._negative_min_index:] - e_out[output_cut_index:] = e_in[self._negative_min_index:] + x_out[output_cut_index:] = x_in[self._negative_min_index:self._positive_max_index] + y_out[output_cut_index:] = y_in[self._negative_min_index:self._positive_max_index] + e_out[output_cut_index:] = e_in[self._negative_min_index:self._positive_max_index] # Set output spectrum data mtd[temp_ws_name].setX(output_spectrum_index, x_out) @@ -232,14 +206,6 @@ def _calculate_array_points(self, sample_x, sample_array_len): self._positive_max_index = np.where(positive_max_diff < delta_x)[0][-1] self._check_bounds(self._positive_max_index, sample_array_len, label='Positive') - # Find array index of negative XMax - if -self._x_max < sample_x[0]: - self._negative_max_index = None; - else: - negative_max_diff = np.absolute(sample_x + sample_x[self._positive_max_index]) - self._negative_max_index = np.where(negative_max_diff < delta_x)[0][-1] - self._check_bounds(self._negative_max_index, sample_array_len, label='Negative') - def _check_bounds(self, index, num_pts, label=''): """ Check if the index falls within the bounds of the x range. diff --git a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst index fc13717db13f..58b6fafe03fc 100644 --- a/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst +++ b/Code/Mantid/docs/source/algorithms/Symmetrise-v1.rst @@ -13,24 +13,10 @@ Symmetrise takes an asymmetric :math:`S(Q,w)` - i.e. one in which the moduli of xmin & xmax are different. Typically xmax is > mod(xmin). Two values, XMin and XMax, are chosen to specify the section of the positive -side of the curve to be reflected onto the negative side. +side of the curve to be reflected onto the negative side, the sample curve +is cropped at XMax ensuring that the symmetrised curve has a symmetrical X +range. -Depending on the input curve and XMax parameter the algorithm can behave in -two ways: - -Reflect Left Hand Side -^^^^^^^^^^^^^^^^^^^^^^ - -If negative XMax is less than the lowest X value on the curve then the positive -section of the curve between XMin and XMax will be reflected to the negative side, -appending the curve to the left hand side. - -Copy and Reflect Left Hand Side -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If negative XMax is greater than the lowest value on the curve then the positive -section of the curve between XMin and XMax is reflected on to the negative side, -the curve between negative XMax and the loest X value will remain unchanged. Usage ----- From 79a58fb91fa1e3372d0786c466080142ca8375e3 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 22 Sep 2014 14:22:28 +0100 Subject: [PATCH 32/46] Small Symmetrise improvements, added validation checks to unit test Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 34 ++++++++++++------- .../plugins/algorithms/SymmetriseTest.py | 14 +++++++- .../src/IndirectSymmetrise.cpp | 7 ++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index e3cbd71f9428..bfefa32f6ac5 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -53,13 +53,26 @@ def PyExec(self): len_x = len(mtd[self._sample].readX(0)) len_y = len(mtd[self._sample].readY(0)) len_e = len(mtd[self._sample].readE(0)) - sample_array_len = min(len_x, len_y, len_e) - 1 + sample_array_len = min(len_x, len_y, len_e) sample_x = mtd[self._sample].readX(0) + + if self._x_max > sample_x[len(sample_x) - 1]: + raise ValueError('XMax value (%f) is greater than largest X value (%f)' % + (self._x_max, sample_x[len(sample_x) - 1])) + + if self._x_min < sample_x[0]: + raise ValueError('XMin value (%f) is less than smallest X value (%f)' % + (self._x_min, sample_x[0])) + self._calculate_array_points(sample_x, sample_array_len) - output_cut_index = sample_array_len - self._positive_min_index - (sample_array_len - self._positive_max_index) - new_array_len = 2 * sample_array_len - (self._positive_min_index + self._negative_min_index) - 2 * (sample_array_len - self._positive_max_index) + max_sample_index = sample_array_len - 1 + centre_range_len = self._positive_min_index + self._negative_min_index + posiive_diff_range_len = max_sample_index - self._positive_max_index + + output_cut_index = max_sample_index - self._positive_min_index - posiive_diff_range_len + new_array_len = 2 * max_sample_index - centre_range_len - 2 * posiive_diff_range_len if self._verbose: logger.notice('Sample array length = %d' % sample_array_len) @@ -96,9 +109,9 @@ def PyExec(self): spectrum_index = mtd[self._sample].getIndexFromSpectrumNumber(spectrum_no) # Strip any additional array cells - x_in = mtd[self._sample].readX(spectrum_index)[:sample_array_len + 1] - y_in = mtd[self._sample].readY(spectrum_index)[:sample_array_len + 1] - e_in = mtd[self._sample].readE(spectrum_index)[:sample_array_len + 1] + x_in = mtd[self._sample].readX(spectrum_index)[:sample_array_len] + y_in = mtd[self._sample].readY(spectrum_index)[:sample_array_len] + e_in = mtd[self._sample].readE(spectrum_index)[:sample_array_len] # Get some zeroed data to overwrite with copies from sample x_out = np.zeros(new_array_len) @@ -203,7 +216,8 @@ def _calculate_array_points(self, sample_x, sample_array_len): # Find array index of positive XMax positive_max_diff = np.absolute(sample_x - self._x_max) - self._positive_max_index = np.where(positive_max_diff < delta_x)[0][-1] + indicies = np.where(positive_max_diff < delta_x)[0] + self._positive_max_index = indicies[-1] self._check_bounds(self._positive_max_index, sample_array_len, label='Positive') def _check_bounds(self, index, num_pts, label=''): @@ -228,13 +242,9 @@ def _generate_props_table(self): props_table.addColumn('int', 'NegativeXMinIndex') props_table.addColumn('int', 'PositiveXMinIndex') - props_table.addColumn('int', 'NegativeXMaxIndex') props_table.addColumn('int', 'PositiveXMaxIndex') - if self._negative_max_index is None: - props_table.addRow([self._negative_min_index, self._positive_min_index, -1, self._positive_max_index]) - else: - props_table.addRow([self._negative_min_index, self._positive_min_index, self._negative_max_index, self._positive_max_index]) + props_table.addRow([self._negative_min_index, self._positive_min_index, self._positive_max_index]) self.setProperty('OutputPropertiesTable', self._props_output_workspace) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py index 81771a81f8ac..73a5f9316157 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py @@ -10,7 +10,19 @@ def setUp(self): self._sample_ws = self._generate_sample_ws('symm_test_sample_ws') def test_basic(self): - symm_test_out_ws= Symmetrise(Sample=self._sample_ws, XMin=0.05, XMax=0.2) + symm_test_out_ws = Symmetrise(Sample=self._sample_ws, XMin=0.05, XMax=0.2) + + def test_failure_lower_range(self): + """ + Tests validation on entering an XMin value lower than the smallest value in the X range. + """ + self.assertRaises(RuntimeError, Symmetrise, Sample=self._sample_ws, OutputWOrkspace='__Symmetrise_TestWS', XMin=-5, XMax=0.2) + + def test_failure_upper_range(self): + """ + Tests validation on entering an XMax value greater than the largest value in the X range. + """ + self.assertRaises(RuntimeError, Symmetrise, Sample=self._sample_ws, OutputWOrkspace='__Symmetrise_TestWS', XMin=0.05, XMax=15) def _rayleigh(self, x, sigma): return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index ad74329e3ad5..ac87c7b96931 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -24,6 +24,8 @@ namespace CustomInterfaces IndirectSymmetrise::IndirectSymmetrise(Ui::IndirectDataReduction& uiForm, QWidget * parent) : IndirectDataReductionTab(uiForm, parent) { + int numDecimals = 6; + // Property Trees m_propTrees["SymmPropTree"] = new QtTreePropertyBrowser(); m_uiForm.symm_properties->addWidget(m_propTrees["SymmPropTree"]); @@ -37,8 +39,10 @@ namespace CustomInterfaces // Raw Properties m_properties["EMin"] = m_dblManager->addProperty("EMin"); + m_dblManager->setDecimals(m_properties["EMin"], numDecimals); m_propTrees["SymmPropTree"]->addProperty(m_properties["EMin"]); m_properties["EMax"] = m_dblManager->addProperty("EMax"); + m_dblManager->setDecimals(m_properties["EMax"], numDecimals); m_propTrees["SymmPropTree"]->addProperty(m_properties["EMax"]); QtProperty* rawPlotProps = m_grpManager->addProperty("Raw Plot"); @@ -54,12 +58,15 @@ namespace CustomInterfaces // Preview Properties // Mainly used for display rather than getting user input m_properties["NegativeYValue"] = m_dblManager->addProperty("Negative Y"); + m_dblManager->setDecimals(m_properties["NegativeYValue"], numDecimals); m_propTrees["SymmPVPropTree"]->addProperty(m_properties["NegativeYValue"]); m_properties["PositiveYValue"] = m_dblManager->addProperty("Positive Y"); + m_dblManager->setDecimals(m_properties["PositiveYValue"], numDecimals); m_propTrees["SymmPVPropTree"]->addProperty(m_properties["PositiveYValue"]); m_properties["DeltaY"] = m_dblManager->addProperty("Delta Y"); + m_dblManager->setDecimals(m_properties["DeltaY"], numDecimals); m_propTrees["SymmPVPropTree"]->addProperty(m_properties["DeltaY"]); // Raw plot From 650c0d4dc8545f3a6833f83bc63037abfe6f9191 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 23 Sep 2014 11:55:47 +0100 Subject: [PATCH 33/46] Give a more useful default E range Refs #7860 --- .../PythonInterface/plugins/algorithms/Symmetrise.py | 5 +++-- .../MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index bfefa32f6ac5..43a813af9cbe 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -216,8 +216,9 @@ def _calculate_array_points(self, sample_x, sample_array_len): # Find array index of positive XMax positive_max_diff = np.absolute(sample_x - self._x_max) - indicies = np.where(positive_max_diff < delta_x)[0] - self._positive_max_index = indicies[-1] + self._positive_max_index = np.where(positive_max_diff < delta_x)[0][-1] + if self._positive_max_index == sample_array_len: + self._positive_max_index -= 1 self._check_bounds(self._positive_max_index, sample_array_len, label='Positive') def _check_bounds(self, index, num_pts, label=''): diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index ac87c7b96931..9795d593c893 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -230,6 +230,10 @@ namespace CustomInterfaces m_rangeSelectors["NegativeE_Raw"]->setRange(-symmRange, 0); m_rangeSelectors["PositiveE_Raw"]->setRange(0, symmRange); + // Set some default (and valid) values for E range + m_dblManager->setValue(m_properties["EMax"], axisRange.second); + m_dblManager->setValue(m_properties["EMin"], axisRange.second/10); + updateMiniPlots(); } From e7499732a0bfb6dc4cadb7a031ac484f6cadcee3 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 23 Sep 2014 12:20:27 +0100 Subject: [PATCH 34/46] Fix a problem with Numpy types Refs #7860 --- .../Framework/PythonInterface/plugins/algorithms/Symmetrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 43a813af9cbe..bef5634a2647 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -94,7 +94,7 @@ def PyExec(self): zeros = np.zeros(new_array_len * num_symm_spectra) CreateWorkspace(OutputWorkspace=temp_ws_name, DataX=zeros, DataY=zeros, DataE=zeros, - NSpec=num_symm_spectra, + NSpec=np.int64(num_symm_spectra), UnitX=x_unit) # Copy logs and properties from sample workspace From 5cf3dd682feb1123defa486d27dc81b226a2633f Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Tue, 23 Sep 2014 13:33:21 +0100 Subject: [PATCH 35/46] Fia failing unit tets Refs #7860 --- .../Framework/PythonInterface/plugins/algorithms/Symmetrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index bef5634a2647..43a813af9cbe 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -94,7 +94,7 @@ def PyExec(self): zeros = np.zeros(new_array_len * num_symm_spectra) CreateWorkspace(OutputWorkspace=temp_ws_name, DataX=zeros, DataY=zeros, DataE=zeros, - NSpec=np.int64(num_symm_spectra), + NSpec=num_symm_spectra, UnitX=x_unit) # Copy logs and properties from sample workspace From 9becaa9b34ee4ab52bf5d8a97812dd7d6181ab44 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 24 Sep 2014 11:51:23 +0100 Subject: [PATCH 36/46] Second attempt at fixing the numpy type issue Refs #7860 --- .../Framework/PythonInterface/plugins/algorithms/Symmetrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 43a813af9cbe..317045adba1b 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -94,7 +94,7 @@ def PyExec(self): zeros = np.zeros(new_array_len * num_symm_spectra) CreateWorkspace(OutputWorkspace=temp_ws_name, DataX=zeros, DataY=zeros, DataE=zeros, - NSpec=num_symm_spectra, + NSpec=int(num_symm_spectra), UnitX=x_unit) # Copy logs and properties from sample workspace From bbfab11a3701c931c5fc7046a8100d471f7a8754 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 24 Sep 2014 15:59:55 +0100 Subject: [PATCH 37/46] Corrected another numpy type issue Refs #7860 --- .../Framework/PythonInterface/plugins/algorithms/Symmetrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 317045adba1b..346d3d08a388 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -245,7 +245,7 @@ def _generate_props_table(self): props_table.addColumn('int', 'PositiveXMinIndex') props_table.addColumn('int', 'PositiveXMaxIndex') - props_table.addRow([self._negative_min_index, self._positive_min_index, self._positive_max_index]) + props_table.addRow([int(self._negative_min_index), int(self._positive_min_index), int(self._positive_max_index)]) self.setProperty('OutputPropertiesTable', self._props_output_workspace) From 5666d5af1bafafcd21cabe162973c36a38908982 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 10:17:06 +0100 Subject: [PATCH 38/46] Improved validation on Symmetrise algorithm Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 84 ++++++++++++++----- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 346d3d08a388..0cb5b9f05c99 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -13,9 +13,11 @@ class Symmetrise(PythonAlgorithm): def category(self): return 'Workflow\\MIDAS;PythonAlgorithms' + def summary(self): return 'Takes an asymmetric S(Q,w) and makes it symmetric' + def PyInit(self): self.declareProperty(WorkspaceProperty('Sample', '', Direction.Input), doc='Sample to run with') @@ -39,6 +41,7 @@ def PyInit(self): self.declareProperty(WorkspaceProperty('OutputPropertiesTable', '', Direction.Output, PropertyMode.Optional), doc='Name to call the properties output table workspace.') + def PyExec(self): from IndirectCommon import StartTime, EndTime @@ -154,28 +157,66 @@ def PyExec(self): EndTime('Symmetrise') - def _setup(self): + + def validateInputs(self): """ - Get the algorithm properties and validate them. + Checks for invalid input properties. """ from IndirectCommon import CheckHistZero + issues = dict() - self._sample = self.getPropertyValue('Sample') + input_workspace_name = self.getPropertyValue('Sample') - num_sample_spectra, _ = CheckHistZero(self._sample) - min_spectra_number = mtd[self._sample].getSpectrum(0).getSpectrumNo() - max_spectra_number = mtd[self._sample].getSpectrum(num_sample_spectra - 1).getSpectrumNo() + # Validate spectra range + spectra_range = self.getProperty('SpectraRange').value + if len(spectra_range) != 0 and len(spectra_range) != 2: + issues['SpectraRange'] = 'Must be in format "spec_min,spec_max"' - self._x_min = math.fabs(self.getProperty('XMin').value) - self._x_max = math.fabs(self.getProperty('XMax').value) + if len(spectra_range) == 2: + spec_min = spectra_range[0] + spec_max = spectra_range[1] + + num_sample_spectra, _ = CheckHistZero(input_workspace_name) + min_spectra_number = mtd[input_workspace_name].getSpectrum(0).getSpectrumNo() + max_spectra_number = mtd[input_workspace_name].getSpectrum(num_sample_spectra - 1).getSpectrumNo() + + if spec_min < min_spectra_number: + issues['SpectraRange'] = 'Minimum spectra must be greater than or equal to %d' % min_spectra_number + + if spec_max > max_spectra_number: + issues['SpectraRange'] = 'Maximum spectra must be less than or equal to %d' % max_spectra_number + + if spec_max < spec_min: + issues['SpectraRange'] = 'Minimum spectra must be smaller than maximum spectra' + + # Validate X range + x_min = self.getProperty('XMin').value + if x_min < 1e-5: + issues['XMin'] = 'XMin must be greater than zero' + + x_max = self.getProperty('XMax').value + if x_max < 1e-5: + issues['XMax'] = 'XMax must be greater than zero' + + if math.fabs(x_max - x_min) < 1e-5: + issues['XMin'] = 'X range is close to zero' + issues['XMax'] = 'X range is close to zero' + + if x_max < x_min: + issues['XMin'] = 'XMin must be less than XMax' + issues['XMax'] = 'XMax must be greater than XMin' - if self._x_min < 1e-5: - raise ValueError('XMin point is Zero') - if self._x_max < 1e-5: - raise ValueError('XMax point is Zero') + return issues - if math.fabs(self._x_max - self._x_min) < 1e-5: - raise ValueError('X range is Zero') + + def _setup(self): + """ + Get the algorithm properties and validate them. + """ + self._sample = self.getPropertyValue('Sample') + + self._x_min = math.fabs(self.getProperty('XMin').value) + self._x_max = math.fabs(self.getProperty('XMax').value) self._verbose = self.getProperty('Verbose').value self._plot = self.getProperty('Plot').value @@ -183,18 +224,10 @@ def _setup(self): self._spectra_range = self.getProperty('SpectraRange').value - if len(self._spectra_range) < 2: - self._spectra_range = [min_spectra_number, max_spectra_number] - else: - if self._spectra_range[0] > self._spectra_range[1]: - raise ValueError('Invalid spectra range') - - if self._spectra_range[1] > max_spectra_number: - raise ValueError('Max spectrum number out of range') - self._output_workspace = self.getPropertyValue('OutputWorkspace') self._props_output_workspace = self.getPropertyValue('OutputPropertiesTable') + def _calculate_array_points(self, sample_x, sample_array_len): """ Finds the points in the array that match the cut points. @@ -221,6 +254,7 @@ def _calculate_array_points(self, sample_x, sample_array_len): self._positive_max_index -= 1 self._check_bounds(self._positive_max_index, sample_array_len, label='Positive') + def _check_bounds(self, index, num_pts, label=''): """ Check if the index falls within the bounds of the x range. @@ -235,6 +269,7 @@ def _check_bounds(self, index, num_pts, label=''): elif index >= num_pts: raise ValueError('%s point %d > %d' % (label, index, num_pts)) + def _generate_props_table(self): """ Creates a table workspace with values calculated in algorithm. @@ -249,6 +284,7 @@ def _generate_props_table(self): self.setProperty('OutputPropertiesTable', self._props_output_workspace) + def _save_output(self): """ Save the output workspace to the user's default working directory @@ -262,6 +298,7 @@ def _save_output(self): if self._verbose: logger.notice('Output file : ' + file_path) + def _plot_output(self): """ Plot the first spectrum of the input and output workspace together. @@ -271,5 +308,6 @@ def _plot_output(self): mtd_plot.plotSpectrum([self._sample, self._output_workspace], 0) + # Register algorithm with Mantid AlgorithmFactory.subscribe(Symmetrise) From e7d99d3e44392bbaf0359bc7cfb8d3055dc4c135 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 10:36:58 +0100 Subject: [PATCH 39/46] Added verification to manual ERange adjustment Refs #7860 --- .../IndirectSymmetrise.h | 1 + .../src/IndirectSymmetrise.cpp | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h index 0deb19860033..10a9ad3b6c62 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSymmetrise.h @@ -69,6 +69,7 @@ namespace CustomInterfaces void plotRawInput(const QString &workspaceName); void updateMiniPlots(); void replotNewSpectrum(QtProperty *prop, double value); + void verifyERange(QtProperty *prop, double value); void updateRangeSelectors(QtProperty *prop, double value); void preview(); void previewAlgDone(bool error); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 9795d593c893..2d741e12f40b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -132,6 +132,8 @@ namespace CustomInterfaces // SIGNAL/SLOT CONNECTIONS // Update range selctors when a property is changed connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updateRangeSelectors(QtProperty*, double))); + // Verify an energy range when it is updated + connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(verifyERange(QtProperty*, double))); // Plot a new spectrum when the user changes the value of the preview spectrum connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(replotNewSpectrum(QtProperty*, double))); // Plot miniplot when file has finished loading @@ -277,6 +279,42 @@ namespace CustomInterfaces updateMiniPlots(); } + /** + * Verifies that the E Range is valid. + * + * Resets the last property changed to it's default if not. + * + * @param prop QtProperty changed + * @param value Value it was changed to (unused) + */ + void IndirectSymmetrise::verifyERange(QtProperty *prop, double value) + { + UNUSED_ARG(value); + + double eMin = m_dblManager->value(m_properties["EMin"]); + double eMax = m_dblManager->value(m_properties["EMax"]); + + // First check that the raw curve has been plotted + if(!m_curves["SymmRawPlot"]) + return; + + // Get the range of the plotted raw curve + auto axisRange = getCurveRange("SymmRawPlot"); + + if(prop == m_properties["EMin"]) + { + // If range is invalid reset EMin to range/10 + if(eMin > eMax) + m_dblManager->setValue(m_properties["EMin"], axisRange.second/10); + } + else if(prop == m_properties["EMax"]) + { + // If range is invalid reset EMax to range + if(eMin > eMax) + m_dblManager->setValue(m_properties["EMax"], axisRange.second); + } + } + /** * Handles a request to preview the symmetrise. * From 184069aad8f63c5d1f530e52ce0df61c0b0fb854 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 10:41:29 +0100 Subject: [PATCH 40/46] Restrict XRange to be a positive value Refs #7860 --- .../CustomInterfaces/src/IndirectSymmetrise.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 2d741e12f40b..15beded33f59 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -270,10 +270,18 @@ namespace CustomInterfaces /** * Redraws mini plots when user changes previw range or spectrum. + * + * @param prop QtProperty that was changed + * @param value Value it was changed to */ void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) { - UNUSED_ARG(value); + if(prop == m_properties["PreviewRange"]) + { + // If preview range was set negative then set it to the absolute value of the value it was set to + if(value < 0) + m_dblManager->setValue(m_properties["PreviewRange"], fabs(value)); + } if((prop == m_properties["PreviewSpec"]) || (prop == m_properties["PreviewRange"])) updateMiniPlots(); From 0ea7c4f2c2b09075c5654225e1ad5f64036916b3 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 11:34:20 +0100 Subject: [PATCH 41/46] Added better validation of EMin and EMax Refs #7860 --- .../src/IndirectSymmetrise.cpp | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 15beded33f59..69a7bb6ffdfa 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -130,9 +130,7 @@ namespace CustomInterfaces m_plots["SymmPreviewPlot"]->replot(); // SIGNAL/SLOT CONNECTIONS - // Update range selctors when a property is changed - connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updateRangeSelectors(QtProperty*, double))); - // Verify an energy range when it is updated + // Validate the E range when it is changed connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(verifyERange(QtProperty*, double))); // Plot a new spectrum when the user changes the value of the preview spectrum connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(replotNewSpectrum(QtProperty*, double))); @@ -290,8 +288,6 @@ namespace CustomInterfaces /** * Verifies that the E Range is valid. * - * Resets the last property changed to it's default if not. - * * @param prop QtProperty changed * @param value Value it was changed to (unused) */ @@ -302,25 +298,44 @@ namespace CustomInterfaces double eMin = m_dblManager->value(m_properties["EMin"]); double eMax = m_dblManager->value(m_properties["EMax"]); - // First check that the raw curve has been plotted - if(!m_curves["SymmRawPlot"]) - return; - - // Get the range of the plotted raw curve - auto axisRange = getCurveRange("SymmRawPlot"); - if(prop == m_properties["EMin"]) { - // If range is invalid reset EMin to range/10 + // If the value of EMin is negative try negating it to get a valid range + if(eMin < 0) + { + eMin = -eMin; + m_dblManager->setValue(m_properties["EMin"], eMin); + return; + } + + // If range is still invalid reset EMin to half EMax if(eMin > eMax) - m_dblManager->setValue(m_properties["EMin"], axisRange.second/10); + { + m_dblManager->setValue(m_properties["EMin"], eMax/2); + return; + } } else if(prop == m_properties["EMax"]) { - // If range is invalid reset EMax to range + // If the value of EMax is negative try negating it to get a valid range + if(eMax < 0) + { + eMax = -eMax; + m_dblManager->setValue(m_properties["EMax"], eMax); + return; + } + + // If range is invalid reset EMax to double EMin if(eMin > eMax) - m_dblManager->setValue(m_properties["EMax"], axisRange.second); + { + m_dblManager->setValue(m_properties["EMax"], eMin*2); + return; + } } + + // If we get this far then the E range is valid + // Update the range selectors with the new values. + updateRangeSelectors(prop, value); } /** @@ -407,9 +422,14 @@ namespace CustomInterfaces /** * Updates position of XCut range selectors when used changed value of XCut. + * + * @param prop QtProperty changed + * @param value Value it was changed to (unused) */ void IndirectSymmetrise::updateRangeSelectors(QtProperty *prop, double value) { + value = fabs(value); + if(prop == m_properties["EMin"]) { m_rangeSelectors["NegativeE_Raw"]->setMaximum(-value); From dedb36ae4b17d6a1d2f8ae7f815da7292f0e0192 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 11:51:52 +0100 Subject: [PATCH 42/46] Add preview spectra validation Refs #7860 --- .../src/IndirectSymmetrise.cpp | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp index 69a7bb6ffdfa..6caef16805e2 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSymmetrise.cpp @@ -95,7 +95,7 @@ namespace CustomInterfaces // Indicators for negative and positive X range values on X axis // The user can use these to move the X range - // Note that the max and min of the negative range selector corespond to the opposit X value + // Note that the max and min of the negative range selector corespond to the opposite X value // i.e. RS min is X max m_rangeSelectors["NegativeE_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); m_rangeSelectors["PositiveE_Raw"] = new MantidWidgets::RangeSelector(m_plots["SymmRawPlot"]); @@ -274,13 +274,42 @@ namespace CustomInterfaces */ void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) { + // Validate the preview range if(prop == m_properties["PreviewRange"]) { // If preview range was set negative then set it to the absolute value of the value it was set to if(value < 0) + { m_dblManager->setValue(m_properties["PreviewRange"], fabs(value)); + return; + } + } + + // Validate the preview spectra + if(prop == m_properties["PreviewSpec"]) + { + // Get the range of possible spectra numbers + QString workspaceName = m_uiForm.symm_dsInput->getCurrentDataName(); + MatrixWorkspace_sptr sampleWS = AnalysisDataService::Instance().retrieveWS(workspaceName.toStdString()); + int minSpectrumRange = sampleWS->getSpectrum(0)->getSpectrumNo(); + int maxSpectrumRange = sampleWS->getSpectrum(sampleWS->getNumberHistograms()-1)->getSpectrumNo(); + + // If entered value is lower then set spectra number to lowest valid value + if(value < minSpectrumRange) + { + m_dblManager->setValue(m_properties["PreviewSpec"], minSpectrumRange); + return; + } + + // If entered value is higer then set spectra number to highest valid value + if(value > maxSpectrumRange) + { + m_dblManager->setValue(m_properties["PreviewSpec"], maxSpectrumRange); + return; + } } + // If we get this far then properties are valid so update mini plots if((prop == m_properties["PreviewSpec"]) || (prop == m_properties["PreviewRange"])) updateMiniPlots(); } From bdecbc8f291bf5d99080117c514be2548aa7fbad Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 6 Oct 2014 12:08:47 +0100 Subject: [PATCH 43/46] Fixed default spectra range issue, added more unit tests Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 8 ++ .../plugins/algorithms/SymmetriseTest.py | 79 +++++++++++++++---- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 0cb5b9f05c99..47fb46f2afb0 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -213,6 +213,8 @@ def _setup(self): """ Get the algorithm properties and validate them. """ + from IndirectCommon import CheckHistZero + self._sample = self.getPropertyValue('Sample') self._x_min = math.fabs(self.getProperty('XMin').value) @@ -223,6 +225,12 @@ def _setup(self): self._save = self.getProperty('Save').value self._spectra_range = self.getProperty('SpectraRange').value + # If the user did not enter a spectra range, use the spectra range of the workspace + if len(self._spectra_range) == 0: + num_sample_spectra, _ = CheckHistZero(self._sample) + min_spectra_number = mtd[self._sample].getSpectrum(0).getSpectrumNo() + max_spectra_number = mtd[self._sample].getSpectrum(num_sample_spectra - 1).getSpectrumNo() + self._spectra_range = [min_spectra_number, max_spectra_number] self._output_workspace = self.getPropertyValue('OutputWorkspace') self._props_output_workspace = self.getPropertyValue('OutputPropertiesTable') diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py index 73a5f9316157..fb1d14c7db12 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/SymmetriseTest.py @@ -4,37 +4,86 @@ from mantid.api import * +def _rayleigh(x, sigma): + return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) + + +def _generate_sample_ws(ws_name): + data_x = np.arange(0, 10, 0.01) + data_y = _rayleigh(data_x, 1) + + CreateWorkspace(DataX=data_x, DataY=data_y, OutputWorkspace=ws_name) + ScaleX(InputWorkspace=ws_name, Factor=-1, Operation="Add", OutputWorkspace=ws_name) # centre the peak over 0 + + return mtd[ws_name] + + class SymmetriseTest(unittest.TestCase): def setUp(self): - self._sample_ws = self._generate_sample_ws('symm_test_sample_ws') + self._sample_ws = _generate_sample_ws('symm_test_sample_ws') def test_basic(self): - symm_test_out_ws = Symmetrise(Sample=self._sample_ws, XMin=0.05, XMax=0.2) + """ + Tests a very minimal execution. + """ + symm_test_out_ws = Symmetrise(Sample=self._sample_ws, + XMin=0.05, XMax=0.2) + + def test_with_spectra_range(self): + """ + Tests running with a given spectra range. + """ + symm_test_out_ws = Symmetrise(Sample=self._sample_ws, + XMin=0.05, XMax=0.2, + SpectraRange=[1, 1]) - def test_failure_lower_range(self): + def test_failure_xmin_out_of_range(self): """ Tests validation on entering an XMin value lower than the smallest value in the X range. """ - self.assertRaises(RuntimeError, Symmetrise, Sample=self._sample_ws, OutputWOrkspace='__Symmetrise_TestWS', XMin=-5, XMax=0.2) + self.assertRaises(RuntimeError, Symmetrise, + Sample=self._sample_ws, + OutputWOrkspace='__Symmetrise_TestWS', + XMin=-5, XMax=0.2) - def test_failure_upper_range(self): + def test_failure_xmax_out_of_range(self): """ Tests validation on entering an XMax value greater than the largest value in the X range. """ - self.assertRaises(RuntimeError, Symmetrise, Sample=self._sample_ws, OutputWOrkspace='__Symmetrise_TestWS', XMin=0.05, XMax=15) - - def _rayleigh(self, x, sigma): - return (x / sigma ** 2) * np.exp(-x ** 2 / (2 * sigma ** 2)) + self.assertRaises(RuntimeError, Symmetrise, + Sample=self._sample_ws, + OutputWOrkspace='__Symmetrise_TestWS', + XMin=0.05, XMax=15) - def _generate_sample_ws(self, ws_name): - data_x = np.arange(0, 10, 0.01) - data_y = self._rayleigh(data_x, 1) + def test_failure_invalid_x_range(self): + """ + Tests validation on entering an XMax value lower then XMin. + """ + self.assertRaises(RuntimeError, Symmetrise, + Sample=self._sample_ws, + OutputWOrkspace='__Symmetrise_TestWS', + XMin=0.2, XMax=0.1) - CreateWorkspace(DataX=data_x, DataY=data_y, OutputWorkspace=ws_name) - ScaleX(InputWorkspace=ws_name, Factor=-1, Operation="Add", OutputWorkspace=ws_name) # centre the peak over 0 + def test_failure_spectra_range_lower(self): + """ + Tests validation on entering a minimum spectra number lower then that of the workspace. + """ + self.assertRaises(RuntimeError, Symmetrise, + Sample=self._sample_ws, + OutputWOrkspace='__Symmetrise_TestWS', + XMin=0.05, XMax=0.2, + SpectraRange=[0, 1]) - return mtd[ws_name] + def test_failure_spectra_range_upper(self): + """ + Tests validation on entering a maximum spectra number higher then that of the workspace. + """ + self.assertRaises(RuntimeError, Symmetrise, + Sample=self._sample_ws, + OutputWOrkspace='__Symmetrise_TestWS', + XMin=0.05, XMax=0.2, + SpectraRange=[1, 2]) if __name__ == '__main__': From f7b5dc47002e8ced4790ca023482072b38640295 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 16 Oct 2014 09:02:37 +0100 Subject: [PATCH 44/46] Allow XMin to be zero Refs #7860 --- .../PythonInterface/plugins/algorithms/Symmetrise.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 47fb46f2afb0..efa84b95cac1 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -191,8 +191,8 @@ def validateInputs(self): # Validate X range x_min = self.getProperty('XMin').value - if x_min < 1e-5: - issues['XMin'] = 'XMin must be greater than zero' + if x_min < -1e-5: + issues['XMin'] = 'XMin must be greater than or equal to zero' x_max = self.getProperty('XMax').value if x_max < 1e-5: From 6a3bd52e77a41774dd999c44e438ffb5a6b0601f Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Fri, 17 Oct 2014 15:14:45 +0100 Subject: [PATCH 45/46] Copy X unit properly Refs #7860 --- .../Framework/PythonInterface/plugins/algorithms/Symmetrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index efa84b95cac1..6787d7e1cdb1 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -91,7 +91,7 @@ def PyExec(self): logger.notice('New array length = %d' % new_array_len) logger.notice('Output array LR split index = %d' % output_cut_index) - x_unit = mtd[self._sample].getXDimension().getUnits() + x_unit = mtd[self._sample].getAxis(0).getUnit().unitID() # Create an empty workspace with enough storage for the new data zeros = np.zeros(new_array_len * num_symm_spectra) From bdeb6a25f216082747c2c70ccdae8e8bb1b09524 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Mon, 27 Oct 2014 08:57:42 +0000 Subject: [PATCH 46/46] Better X range checking Refs #7860 --- .../plugins/algorithms/Symmetrise.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py index 6787d7e1cdb1..c8a761f780ef 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Symmetrise.py @@ -60,15 +60,11 @@ def PyExec(self): sample_x = mtd[self._sample].readX(0) - if self._x_max > sample_x[len(sample_x) - 1]: - raise ValueError('XMax value (%f) is greater than largest X value (%f)' % - (self._x_max, sample_x[len(sample_x) - 1])) - - if self._x_min < sample_x[0]: - raise ValueError('XMin value (%f) is less than smallest X value (%f)' % - (self._x_min, sample_x[0])) - - self._calculate_array_points(sample_x, sample_array_len) + # Get slice bounds of array + try: + self._calculate_array_points(sample_x, sample_array_len) + except Exception as e: + raise RuntimeError('Failed to calculate array slice boundaries: %s' % e.message) max_sample_index = sample_array_len - 1 centre_range_len = self._positive_min_index + self._negative_min_index @@ -103,7 +99,6 @@ def PyExec(self): # Copy logs and properties from sample workspace CopyLogs(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) CopyInstrumentParameters(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) - # CopySample(InputWorkspace=self._sample, OutputWorkspace=temp_ws_name) # For each spectrum copy positive values to the negative output_spectrum_index = 0 @@ -206,6 +201,15 @@ def validateInputs(self): issues['XMin'] = 'XMin must be less than XMax' issues['XMax'] = 'XMax must be greater than XMin' + # Valudate X range against workspace X range + sample_x = mtd[input_workspace_name].readX(0) + + if x_max > sample_x[len(sample_x) - 1]: + issues['XMax'] = 'XMax value (%f) is greater than largest X value (%f)' % (self._x_max, sample_x[len(sample_x) - 1]) + + if -x_min < sample_x[0]: + issues['XMin'] = 'Negative XMin value (%f) is less than smallest X value (%f)' % (-x_min, sample_x[0]) + return issues