From 0abe0e457cca1acdefcafb9c8f62d485be221302 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Fri, 8 Nov 2013 10:26:08 +0000 Subject: [PATCH 01/18] re #8395: creation of Larmor Instrument This commit introduces the Larmor instrument that is required to allow reducing Larmor data. It was not possible to check with the user the system coordinates that he wants to use and other things. But, this commit is necessary to allow the user start interacting with the reduction to allow us to address all the particularities of the reduction for LARMOR. --- Code/Mantid/instrument/LARMOR_Parameters.xml | 55 +++++++++++++++++++ .../scripts/SANS/ISISCommandInterface.py | 15 +++++ Code/Mantid/scripts/SANS/isis_instrument.py | 52 ++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 Code/Mantid/instrument/LARMOR_Parameters.xml diff --git a/Code/Mantid/instrument/LARMOR_Parameters.xml b/Code/Mantid/instrument/LARMOR_Parameters.xml new file mode 100644 index 000000000000..7d8452b19e2c --- /dev/null +++ b/Code/Mantid/instrument/LARMOR_Parameters.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Mantid/scripts/SANS/ISISCommandInterface.py b/Code/Mantid/scripts/SANS/ISISCommandInterface.py index 0e81f008d571..6bfb7fa03981 100644 --- a/Code/Mantid/scripts/SANS/ISISCommandInterface.py +++ b/Code/Mantid/scripts/SANS/ISISCommandInterface.py @@ -100,6 +100,21 @@ def LOQ(): except: return False return True + +def LARMOR(): + """ + Initialises the instrument settings for LARMOR + @return True on success + """ + _printMessage('LARMOR()') + try: + instrument = isis_instrument.LARMOR() + + ReductionSingleton().set_instrument(instrument) + config['default.instrument']='LARMOR' + except: + return False + return True def Detector(det_name): """ diff --git a/Code/Mantid/scripts/SANS/isis_instrument.py b/Code/Mantid/scripts/SANS/isis_instrument.py index ea1c1cfb5693..7efcdd615fc1 100644 --- a/Code/Mantid/scripts/SANS/isis_instrument.py +++ b/Code/Mantid/scripts/SANS/isis_instrument.py @@ -975,6 +975,58 @@ def cur_detector_position(self, ws_name): return [-pos.getX(), -pos.getY()] +class LARMOR(ISISInstrument): + _NAME = 'LARMOR' + WAV_RANGE_MIN = 2.2 + WAV_RANGE_MAX = 10.0 + def __init__(self): + super(LARMOR,self).__init__('LARMOR_Definition.xml') + self.monitor_names = dict() + + for i in range(1,6): + self.monitor_names[i] = 'monitor'+str(i) + + def set_up_for_run(self, base_runno): + """ + Needs to run whenever a sample is loaded + """ + first = self.DETECTORS['low-angle'] + second = self.DETECTORS['high-angle'] + + first.set_orien('Horizontal') + first.set_first_spec_num(10) + second.set_orien('Horizontal') + second.place_after(first) + + def move_components(self, ws, xbeam, ybeam): + super(LARMOR,self).move_components(ws) + + detBanch = self.getDetector('rear') + + xshift = -xbeam + yshift = -ybeam + #zshift = ( detBanch.z_corr)/1000. + #zshift -= self.REAR_DET_DEFAULT_SD_M + zshift = 0 + sanslog.notice("Setup move " + str(xshift*1000) + " " + str(yshift*1000) + " " + str(zshift*1000)) + MoveInstrumentComponent(ws, ComponentName=detBanch.name(), X=xshift, + Y=yshift, Z=zshift) + # beam centre, translation + return [0.0, 0.0], [-xbeam, -ybeam] + + def load_transmission_inst(self, workspace): + """ + Not required for SANS2D + """ + pass + + def cur_detector_position(self, ws_name): + """Return the position of the center of the detector bank""" + ws = mtd[ws_name] + pos = ws.getInstrument().getComponentByName(self.cur_detector().name()).getPos() + + return [-pos.getX(), -pos.getY()] + if __name__ == '__main__': From c0806787f2ccedfd6d1af9a2a77508bab2dd7a19 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Fri, 8 Nov 2013 11:21:56 +0000 Subject: [PATCH 02/18] re #8395: correct Larmor zero padding By the files current available inside the archiver. It seems that the user plans to use 8 zero-padding. --- Code/Mantid/instrument/Facilities.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Mantid/instrument/Facilities.xml b/Code/Mantid/instrument/Facilities.xml index 51a255047545..8bee7a11e9ec 100644 --- a/Code/Mantid/instrument/Facilities.xml +++ b/Code/Mantid/instrument/Facilities.xml @@ -76,6 +76,7 @@ Small Angle Scattering + From 075342c8782a9176f7d39cceca9dfe58106fbd61 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Fri, 8 Nov 2013 12:08:42 +0000 Subject: [PATCH 03/18] re #8395: Correct SaveCanSAS support for LARMOR instrument --- Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp | 2 ++ Code/Mantid/scripts/SANS/SANSBatchMode.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp index e1b51d2069d3..4cdc103f4eaf 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp @@ -2601,6 +2601,8 @@ void SANSRunWindow::handleDefSaveClick() saveCommand += "'front-detector, rear-detector'"; if ( matrix_workspace->getInstrument()->getName() == "LOQ" ) saveCommand += "'HAB, main-detector-bank'"; + if ( matrix_workspace->getInstrument()->getName() == "LARMOR") + saveCommand += "'" + m_uiForm.detbank_sel->currentText()+"'"; /* From v2, SaveCanSAS1D is able to save the Transmission workspaces related to the reduced data. The name of workspaces of the Transmission are available at the diff --git a/Code/Mantid/scripts/SANS/SANSBatchMode.py b/Code/Mantid/scripts/SANS/SANSBatchMode.py index 9cca1c9cf6f5..2db440553cab 100644 --- a/Code/Mantid/scripts/SANS/SANSBatchMode.py +++ b/Code/Mantid/scripts/SANS/SANSBatchMode.py @@ -127,6 +127,11 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'}, ins_name = ReductionSingleton().instrument.name() # is used for SaveCanSAS1D go give the detectors names detnames = ', '.join(ReductionSingleton().instrument.listDetectors()) + + # LARMOR has just one detector, but, it defines two because ISISInstrument is defined as two banks! #8395 + if ins_name == 'LARMOR': + detnames = ReductionSingleton().instrument.cur_detector().name() + scale_shift = {'scale':1.0000, 'shift':0.0000} #first copy the user settings in case running the reductionsteps can change it settings = copy.deepcopy(ReductionSingleton().reference()) From d348aea1a99f6e5ca8b5ced1288da8265e27078d Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Wed, 13 Nov 2013 12:34:57 +0000 Subject: [PATCH 04/18] re #8438: Make SANS GUI and SANS Batch independent from logs The Sans GUI interface does not depend any more of returning the logs from AssignSample or AssignCan. These two method should not return such 'obscure' information, but, being the ISISCmdInterface we can not change now. --- .../MantidQtCustomInterfaces/SANSRunWindow.h | 6 +- .../CustomInterfaces/src/SANSRunWindow.cpp | 91 +++++++------------ Code/Mantid/scripts/SANS/SANSBatchMode.py | 6 +- Code/Mantid/scripts/SANS/isis_instrument.py | 4 +- 4 files changed, 44 insertions(+), 63 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h index e298d51c6e32..b001069e3949 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h @@ -156,9 +156,9 @@ class SANSRunWindow : public MantidQt::API::UserSubWindow /// Create a mask string void addUserMaskStrings(QString & exec_script,const QString& importCommand,enum MaskType mType); /// Set geometry details - void setGeometryDetails(const QString & sample_logs, const QString & can_logs); + void setGeometryDetails(); /// Set the SANS2D geometry - void setSANS2DGeometry(boost::shared_ptr workspace, const QString & logs, int wscode); + void setSANS2DGeometry(boost::shared_ptr workspace, int wscode); /// Set LOQ geometry void setLOQGeometry(boost::shared_ptr workspace, int wscode); /// Mark an error on a label @@ -168,7 +168,7 @@ class SANSRunWindow : public MantidQt::API::UserSubWindow /// Run an assign command bool runAssign(int key, QString & logs); /// Load a scatter sample file or can run via Python objects using the passed Python command - bool assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const QString & assignFn, QString & logs); + bool assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const QString & assignFn); /// runs that contain only monitor counts can be direct or transmission runs bool assignMonitorRun(MantidWidgets::MWRunFiles & trans, MantidWidgets::MWRunFiles & direct, const QString & assignFn); /// Get the detectors' names diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp index 4cdc103f4eaf..7ccd5f3ecd8b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp @@ -1422,7 +1422,7 @@ void SANSRunWindow::applyMask(const QString& wsName,bool time_pixel) /** * Set the information about component distances on the geometry tab */ -void SANSRunWindow::setGeometryDetails(const QString & sample_logs, const QString & can_logs) +void SANSRunWindow::setGeometryDetails() { resetGeometryDetailsBox(); @@ -1506,7 +1506,7 @@ void SANSRunWindow::setGeometryDetails(const QString & sample_logs, const QStrin } //SANS2D - Sample - setSANS2DGeometry(sample_workspace, sample_logs, 0); + setSANS2DGeometry(sample_workspace, 0); //Get the can workspace if there is one QString can = m_experCan; if( can.isEmpty() ) @@ -1530,7 +1530,7 @@ void SANSRunWindow::setGeometryDetails(const QString & sample_logs, const QStrin can_workspace = getGroupMember(workspace_ptr, 1); } - setSANS2DGeometry(can_workspace, can_logs, 1); + setSANS2DGeometry(can_workspace, 1); //Check for discrepancies bool warn_user(false); @@ -1569,10 +1569,9 @@ void SANSRunWindow::setGeometryDetails(const QString & sample_logs, const QStrin /** * Set SANS2D geometry info * @param workspace :: The workspace - * @param logs :: The log information - * @param wscode :: ????? + * @param wscode :: 0 for sample, 1 for can, others not defined */ -void SANSRunWindow::setSANS2DGeometry(boost::shared_ptr workspace, const QString & logs, int wscode) +void SANSRunWindow::setSANS2DGeometry(boost::shared_ptr workspace, int wscode) { double unitconv = 1000.; @@ -1596,33 +1595,30 @@ void SANSRunWindow::setSANS2DGeometry(boost::shared_ptrsetText(formatDouble(distance, "black", 'f', 1)); + + // get the tuple of log values and convert to a list of + QString code_to_run = QString("print ','.join([str(a) for a in i.ReductionSingleton().instrument.getDetValues('%1')])").arg(QString::fromStdString(workspace->name())); - // Detectors - QStringList det_info = logs.split(","); - QStringListIterator itr(det_info); - while( itr.hasNext() ) - { - QString line = itr.next(); - QStringList values = line.split(":"); - QString detname = values[0].trimmed(); - QString distance = values[1].trimmed(); - trimPyMarkers(detname); - - // instrument scientists wants distances printed - // out with just one digit - try - { - double d = distance.toDouble(); - distance = QString::number(d, 'f', 1); - } - catch(...) - { - // if distance is not a double for some reason - // for now just proceed - } + QStringList logvalues = runReduceScriptFunction(code_to_run).split(","); - QLabel *lbl = m_s2d_detlabels[wscode].value(detname); - if( lbl ) lbl->setText(distance); + QStringList dets_names; + dets_names << "Front_Det_Z" + << "Front_Det_X" + << "Front_Det_Rot" + << "Rear_Det_Z" + << "Rear_Det_X"; + int index = 0; + foreach(QString detname, dets_names){ + QString distance = logvalues[index]; + try{ + double d = distance.toDouble(); + distance = QString::number(d, 'f', 1); + }catch(...){ + // if distance is not a double, for now just proceed + } + QLabel * lbl = m_s2d_detlabels[wscode].value(detname); + if (lbl) lbl->setText(distance); + index += 1; } } @@ -1818,11 +1814,10 @@ bool SANSRunWindow::handleLoadButtonClick() // set the detector just before loading so to correctly move the instrument runReduceScriptFunction("\ni.ReductionSingleton().instrument.setDetector('" + m_uiForm.detbank_sel->currentText() + "')"); - QString sample_logs, can_logs; QString sample = m_uiForm.scatterSample->getFirstFilename(); try {//preliminarly error checking is over try to load that data - is_loaded &= assignDetBankRun(*(m_uiForm.scatterSample), "AssignSample", sample_logs); + is_loaded &= assignDetBankRun(*(m_uiForm.scatterSample), "AssignSample"); readNumberOfEntries("get_sample().loader", m_uiForm.scatterSample); if (m_uiForm.scatCan->isEmpty()) { @@ -1830,7 +1825,7 @@ bool SANSRunWindow::handleLoadButtonClick() } else { - is_loaded &= assignDetBankRun(*(m_uiForm.scatCan), "AssignCan", can_logs); + is_loaded &= assignDetBankRun(*(m_uiForm.scatCan), "AssignCan"); readNumberOfEntries("background_subtracter", m_uiForm.scatCan); } if ( ( ! m_uiForm.transmis->isEmpty() ) && ( ! m_uiForm.direct->isEmpty() ) ) @@ -1858,28 +1853,15 @@ bool SANSRunWindow::handleLoadButtonClick() g_log.error() << "Problem loading file\n"; is_loaded = false; } - if( m_uiForm.inst_opt->currentText() == "SANS2D" && sample_logs.isEmpty() ) - { - is_loaded = false; - showInformationBox("Error: Cannot find log file for sample run, cannot continue."); - } if (!is_loaded) { setProcessingState(NoSample); m_uiForm.load_dataBtn->setText("Load Data"); return false; } - if( m_uiForm.inst_opt->currentText() == "SANS2D" && can_logs.isEmpty() ) - { - if ( ! m_uiForm.scatCan->isEmpty() ) - { - can_logs = sample_logs; - showInformationBox("Warning: Cannot find log file for can run, using sample values."); - } - } // Sort out the log information - setGeometryDetails(sample_logs, can_logs); + setGeometryDetails(); Mantid::API::Workspace_sptr baseWS = Mantid::API::AnalysisDataService::Instance().retrieve(m_experWksp.toStdString()); @@ -3100,10 +3082,9 @@ bool SANSRunWindow::assignMonitorRun(MantidWidgets::MWRunFiles & trans, MantidWi * Load a scatter sample file or can run via Python objects using the passed Python command * @param[in] runFile name of file to load * @param[in] assignFn the Python command to run - * @param[out] logs information loaded from the file * @return true if there were no Python errors, false otherwise */ -bool SANSRunWindow::assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const QString & assignFn, QString & logs) +bool SANSRunWindow::assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const QString & assignFn) { //need something to place between names printed by Python that won't be intepreted as the names or removed as white space const static QString PYTHON_SEP("C++assignDetBankRunC++"); @@ -3127,7 +3108,9 @@ bool SANSRunWindow::assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const .arg( m_uiForm.rear_beam_y->text()) .arg( m_uiForm.front_beam_x->text()) .arg( m_uiForm.front_beam_y->text()); - run_info += "SCATTER_SAMPLE, logvalues = " + assignCom+";print '"+PYTHON_SEP+"',SCATTER_SAMPLE,'"+PYTHON_SEP+"',logvalues"; + run_info += "SCATTER_SAMPLE = " + assignCom; + run_info += ";ws_name = SCATTER_SAMPLE if not isinstance(SCATTER_SAMPLE, tuple) else SCATTER_SAMPLE[0]"; + run_info += ";print '"+PYTHON_SEP+"',ws_name"; run_info = runReduceScriptFunction(run_info); if (run_info.startsWith("error", Qt::CaseInsensitive)) { @@ -3136,12 +3119,6 @@ bool SANSRunWindow::assignDetBankRun(MantidWidgets::MWRunFiles & runFile, const //read the informtion returned from Python QString base_workspace = run_info.section(PYTHON_SEP, 1, 1).trimmed(); - logs = run_info.section(PYTHON_SEP, 2); - if( !logs.isEmpty() ) - { - trimPyMarkers(logs); - } - if ( assignFn.contains("can", Qt::CaseInsensitive) ) { m_experCan = base_workspace; diff --git a/Code/Mantid/scripts/SANS/SANSBatchMode.py b/Code/Mantid/scripts/SANS/SANSBatchMode.py index 2db440553cab..cd0962887faa 100644 --- a/Code/Mantid/scripts/SANS/SANSBatchMode.py +++ b/Code/Mantid/scripts/SANS/SANSBatchMode.py @@ -294,9 +294,13 @@ def read_run(runs, run_role, format): return run_file, period = parse_run(run_file, format) - run_ws = eval(COMMAND[run_role] + 'run_file, period=period)[0]') + run_ws = eval(COMMAND[run_role] + 'run_file, period=period)') if not run_ws: raise SkipReduction('Cannot load ' + run_role + ' run "' + run_file + '"') + + #AssignCan and AssignSample will change signature for: ws_name = AssignCan + if isinstance(run_ws, tuple): + return run_ws[0] return run_ws def read_trans_runs(runs, sample_or_can, format): diff --git a/Code/Mantid/scripts/SANS/isis_instrument.py b/Code/Mantid/scripts/SANS/isis_instrument.py index 7efcdd615fc1..360ebb41bf34 100644 --- a/Code/Mantid/scripts/SANS/isis_instrument.py +++ b/Code/Mantid/scripts/SANS/isis_instrument.py @@ -720,7 +720,7 @@ def set_up_for_run(self, base_runno): #as spectrum numbers of the first detector have changed we'll move those in the second too second.place_after(first) - def _getDetValues(self, ws_name): + def getDetValues(self, ws_name): """ Retrive the values of Front_Det_Z, Front_Det_X, Front_Det_Rot, Rear_Det_Z and Rear_Det_X from the workspace. If it does not find the value at the run info, it takes as default value the @@ -761,7 +761,7 @@ def move_components(self, ws, xbeam, ybeam): frontDet = self.getDetector('front') rearDet = self.getDetector('rear') - FRONT_DET_Z, FRONT_DET_X, FRONT_DET_ROT, REAR_DET_Z, REAR_DET_X = self._getDetValues(ws) + FRONT_DET_Z, FRONT_DET_X, FRONT_DET_ROT, REAR_DET_Z, REAR_DET_X = self.getDetValues(ws) # Deal with front detector # 9/1/2 this all dates to Richard Heenan & Russell Taylor's original python development for SANS2d From 6d4b49d2e2e0d9f33accfe39698c6860e29191a9 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Wed, 13 Nov 2013 16:21:05 +0000 Subject: [PATCH 05/18] re #8438: Deal with the logs inside isis_instrument for SANS2D It now uses the log only where it is important, inside the SANS2D instrument. --- .../scripts/SANS/ISISCommandInterface.py | 22 ++++- Code/Mantid/scripts/SANS/isis_instrument.py | 86 +++++++++++++++---- Code/Mantid/scripts/SANS/isis_reducer.py | 4 +- .../scripts/SANS/isis_reduction_steps.py | 83 ++++-------------- 4 files changed, 105 insertions(+), 90 deletions(-) diff --git a/Code/Mantid/scripts/SANS/ISISCommandInterface.py b/Code/Mantid/scripts/SANS/ISISCommandInterface.py index 6bfb7fa03981..637a8ab8254f 100644 --- a/Code/Mantid/scripts/SANS/ISISCommandInterface.py +++ b/Code/Mantid/scripts/SANS/ISISCommandInterface.py @@ -223,6 +223,20 @@ def TransWorkspace(sample, can = None): ReductionSingleton().transmission_calculator.calculated_samp = sample ReductionSingleton().transmission_calculator.calculated_can = can +def _return_old_compatibility_assign_methods(ws_name): + """For backward compatibility, AssignCan and AssignSample returns a tuple + with workspace name and the log entry if available. + + In the future, those methods should return just workspace name + """ + logs = "" + if isinstance(ReductionSingleton().instrument, isis_instrument.SANS2D): + try: + logs = ReductionSingleton().instrument.get_detector_log(ws_name) + except: + pass + return ws_name, logs + def AssignCan(can_run, reload = True, period = isis_reduction_steps.LoadRun.UNSET_PERIOD): """ The can is a scattering run under the same conditions as the experimental run but the @@ -249,9 +263,10 @@ def AssignCan(can_run, reload = True, period = isis_reduction_steps.LoadRun.UNSE isis_reduction_steps.CanSubtraction( can_run, reload=reload, period=period) #ideally this code should live in a separate load can object - logs = ReductionSingleton().background_subtracter.assign_can( + ReductionSingleton().background_subtracter.assign_can( ReductionSingleton()) - return ReductionSingleton().background_subtracter.workspace.wksp_name, logs + return _return_old_compatibility_assign_methods( + ReductionSingleton().background_subtracter.workspace.wksp_name) def TransmissionSample(sample, direct, reload = True, period_t = -1, period_d = -1): """ @@ -300,8 +315,7 @@ def AssignSample(sample_run, reload = True, period = isis_reduction_steps.LoadRu global LAST_SAMPLE LAST_SAMPLE = ReductionSingleton().get_sample().wksp_name - return ReductionSingleton().get_sample().wksp_name, \ - ReductionSingleton().get_sample().log + return _return_old_compatibility_assign_methods(LAST_SAMPLE) def SetCentre(xcoord, ycoord, bank = 'rear'): """ diff --git a/Code/Mantid/scripts/SANS/isis_instrument.py b/Code/Mantid/scripts/SANS/isis_instrument.py index 360ebb41bf34..891c92807f25 100644 --- a/Code/Mantid/scripts/SANS/isis_instrument.py +++ b/Code/Mantid/scripts/SANS/isis_instrument.py @@ -3,6 +3,7 @@ from mantid.simpleapi import * from mantid.api import WorkspaceGroup from mantid.kernel import Logger +import re sanslog = Logger.get("SANS") import sys @@ -555,7 +556,7 @@ def reset_TOFs(self, monitor=None): self._back_start = None self._back_end = None - def move_components(self, ws): + def move_all_components(self, ws): """ Move the sample object to the location set in the logs or user settings file @param ws: the workspace containing the sample to move @@ -573,10 +574,38 @@ def move_components(self, ws): MoveInstrumentComponent(Workspace=ws,ComponentName= component, Z = offset, RelativePosition=True) + def move_components(self, ws, beamX, beamY): + """Define how to move the bank to position beamX and beamY must be implemented""" + raise RuntimeError("Not Implemented") + def cur_detector_position(self, ws_name): """Return the position of the center of the detector bank""" raise RuntimeError("Not Implemented") + def on_load_sample(self, ws_name, beamcentre, isSample): + """It will be called just after loading the workspace for sample and can + + It configures the instrument for the specific run of the workspace for handle historical changes in the instrument. + + It centralizes the detector bank to teh beamcentre (tuple of two values) + """ + ws_ref = mtd[str(ws_name)] + try: + run_num = ws_ref.getRun().getLogData('run_number').value + except: + run_num = int(re.findall(r'\d+',run_string)[-1]) + + if isSample: + self.set_up_for_run(run_num) + + # centralize the bank to the centre + self.move_components(ws_name, beamcentre[0], beamcentre[1]) + + def load_transmission_inst(self, ws_trans, ws_direct, beamcentre): + """ + Called on loading of transmissions + """ + pass class LOQ(ISISInstrument): @@ -608,7 +637,7 @@ def move_components(self, ws, xbeam, ybeam): @param ybeam: y-position of the beam @return: the locations of (in the new coordinates) beam center, center of detector bank """ - super(LOQ, self).move_components(ws) + self.move_all_components(ws) xshift = (317.5/1000.) - xbeam yshift = (317.5/1000.) - ybeam @@ -640,13 +669,14 @@ def set_up_for_run(self, base_runno): second.set_orien('Horizontal') second.place_after(first) - def load_transmission_inst(self, workspace): + def load_transmission_inst(self, ws_trans, ws_direct, beamcentre): """ Loads information about the setup used for LOQ transmission runs """ trans_definition_file = config.getString('instrumentDefinition.directory') trans_definition_file += '/'+self._NAME+'_trans_Definition.xml' - LoadInstrument(Workspace=workspace,Filename= trans_definition_file, RewriteSpectraMap=False) + LoadInstrument(Workspace=ws_trans,Filename= trans_definition_file, RewriteSpectraMap=False) + LoadInstrument(Workspace=ws_direct, Filename = trans_definition_file, RewriteSpectraMap=False) def check_can_logs(self): """ @@ -801,7 +831,7 @@ def move_components(self, ws, xbeam, ybeam): MoveInstrumentComponent(Workspace=ws,ComponentName= rearDet.name(), X = xshift, Y = yshift, Z = zshift, RelativePosition="1") - super(SANS2D, self).move_components(ws) + self.move_all_components(ws) #this implements the TRANS/TRANSPEC=4/SHIFT=... line, this overrides any other monitor move if self.monitor_4_offset: @@ -962,11 +992,15 @@ def append_marked(self, detNames): def get_marked_dets(self): return self._marked_dets - def load_transmission_inst(self, workspace): + def load_transmission_inst(self, ws_trans, ws_direct, beamcentre): """ - Not required for SANS2D + SANS2D requires the centralize the detectors of the transmission + as well as the sample and can. """ - pass + self.move_components(ws_trans, beamcentre[0], beamcentre[1]) + if ws_trans != ws_direct: + self.move_components(ws_direct, beamcentre[0], beamcentre[1]) + def cur_detector_position(self, ws_name): """Return the position of the center of the detector bank""" @@ -975,6 +1009,32 @@ def cur_detector_position(self, ws_name): return [-pos.getX(), -pos.getY()] + def on_load_sample(self, ws_name, beamcentre, isSample): + """For SANS2D in addition of the operations defines in on_load_sample of ISISInstrument + it has to deal with the log, which defines some offsets for the movement of the + detector bank. + """ + ws_ref = mtd[str(ws_name)] + try: + log = self.get_detector_log(ws_ref) + if log == "": + raise "Invalid log" + except: + if isSample: + raise RuntimeError('Sample logs cannot be loaded, cannot continue') + else: + logger.warning("Can logs could not be loaded, using sample values.") + + + if isSample: + self.apply_detector_logs(log) + else: + self.check_can_logs(log) + + + ISISInstrument.on_load_sample(self, ws_name, beamcentre, isSample) + + class LARMOR(ISISInstrument): _NAME = 'LARMOR' WAV_RANGE_MIN = 2.2 @@ -999,8 +1059,8 @@ def set_up_for_run(self, base_runno): second.place_after(first) def move_components(self, ws, xbeam, ybeam): - super(LARMOR,self).move_components(ws) - + self.move_all_components(ws) + detBanch = self.getDetector('rear') xshift = -xbeam @@ -1014,12 +1074,6 @@ def move_components(self, ws, xbeam, ybeam): # beam centre, translation return [0.0, 0.0], [-xbeam, -ybeam] - def load_transmission_inst(self, workspace): - """ - Not required for SANS2D - """ - pass - def cur_detector_position(self, ws_name): """Return the position of the center of the detector bank""" ws = mtd[ws_name] diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index cc9dc707ab2e..0edc7c102468 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -33,8 +33,6 @@ class Sample(object): def __init__(self): #will contain a LoadSample() object that converts the run number into a file name and loads that file self.loader = None - #the logs from the run file - self.log = None #geometry that comes from the run and can be overridden by user settings self.geometry = sans_reduction_steps.GetSampleGeom() #record options for the set_run @@ -64,7 +62,7 @@ def set_run(self, run, reload, period, reducer): self.period_option = period self.loader = isis_reduction_steps.LoadSample(run, reload, period) - self.log = self.loader.execute(reducer, None) + self.loader.execute(reducer, None) self.geometry.execute(None, self.get_wksp_name()) diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index b6d115fd77f7..e7fc9e661e34 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -69,7 +69,7 @@ def _load(self, inst = None, is_can=False, extra_options=dict()): @param inst: a reference to the current instrument @param iscan: set this to True for can runs @param extra_options: arguments to pass on to the Load Algorithm. - @return: log values, number of periods in the workspace + @return: number of periods in the workspace """ if self._period > 1: workspace = self._get_workspace_name(self._period) @@ -95,8 +95,6 @@ def _load(self, inst = None, is_can=False, extra_options=dict()): OutputWorkspace=workspace, **extra_options) - SANS2D_log_file = mtd[workspace] - numPeriods = self._find_workspace_num_periods(workspace) #deal with the difficult situation of not reporting the period of single period files if numPeriods > 1: @@ -106,22 +104,9 @@ def _load(self, inst = None, is_can=False, extra_options=dict()): RenameWorkspace(InputWorkspace=workspace,OutputWorkspace= period_definitely_inc) workspace = period_definitely_inc - log = self._extract_log_info(SANS2D_log_file, inst) - self.wksp_name = workspace - return numPeriods, log + self.periods_in_file = numPeriods - def _extract_log_info(self,wksp_pointer, inst): - log = None - if (not inst is None) and inst.name() == 'SANS2D': - #this instrument has logs to be loaded - try: - log = inst.get_detector_log(wksp_pointer) - except: - #transmission workspaces, don't have logs - if not self._is_trans: - raise - return log def _get_workspace_name(self, entry_num=None): """ @@ -163,7 +148,7 @@ def _loadFromWorkspace(self, reducer): self._data_file = _file_path if self._reload: # give to _assignHelper the responsibility of loading this data. - return False, None + return False #test if the sample details are already loaded: if not ws_pointer.sample().getGeometryFlag(): @@ -182,15 +167,15 @@ def _loadFromWorkspace(self, reducer): if isEventWorkspace(ws_pointer): ws_pointer = fromEvent2Histogram(ws_pointer) - return True, self._extract_log_info(ws_pointer, reducer.instrument) + return True # Helper function def _assignHelper(self, reducer): if isinstance(self._data_file, Workspace): - loaded_flag, logs = self._loadFromWorkspace(reducer) + loaded_flag= self._loadFromWorkspace(reducer) if loaded_flag: - return logs + return if self._data_file == '' or self._data_file.startswith('.'): raise RuntimeError('Sample needs to be assigned as run_number.file_type') @@ -215,13 +200,13 @@ def _assignHelper(self, reducer): try: # the spectrum_limits is not the default only for transmission data - self.periods_in_file, logs = self._load(reducer.instrument, extra_options=spectrum_limits) + self._load(reducer.instrument, extra_options=spectrum_limits) except RuntimeError, details: sanslog.warning(str(details)) self.wksp_name = '' - return '', -1 + return - return logs + return def _leaveSinglePeriod(self, workspace, period): groupW = mtd[workspace] @@ -380,14 +365,7 @@ def execute(self, reducer, workspace): raise RuntimeError('Transmission run set without direct run error') #transmission workspaces sometimes have monitor locations, depending on the instrument, load these locations - reducer.instrument.load_transmission_inst(self.trans.wksp_name) - reducer.instrument.load_transmission_inst(self.direct.wksp_name) - - if reducer.instrument.name() == 'SANS2D': - beamcoords = reducer.get_beam_center() - reducer.instrument.move_components(self.trans.wksp_name, beamcoords[0], beamcoords[1]) - if self.trans.wksp_name != self.direct.wksp_name: - reducer.instrument.move_components(self.direct.wksp_name, beamcoords[0], beamcoords[1]) + reducer.instrument.load_transmission_inst(self.trans.wksp_name, self.direct.wksp_name, reducer.get_beam_center()) return self.trans.wksp_name, self.direct.wksp_name @@ -415,24 +393,15 @@ def assign_can(self, reducer): if not reducer.user_settings.executed: raise RuntimeError('User settings must be loaded before the can can be loaded, run UserFile() first') - logs = self.workspace._assignHelper(reducer) + self.workspace._assignHelper(reducer) if self.workspace.wksp_name == '': sanslog.warning('Unable to load SANS can run, cannot continue.') return '()' - if logs: - reducer.instrument.check_can_logs(logs) - else: - logs = "" - if reducer.instrument.name() == 'SANS2D': - _issueWarning("Can logs could not be loaded, using sample values.") - return "()" - - beamcoords = reducer.get_beam_center() - reducer.instrument.move_components(self.wksp_name, beamcoords[0], beamcoords[1]) - - return logs + reducer.instrument.on_load_sample(self.workspace.wksp_name, + reducer.get_beam_center(), + isSample=False) def execute(self, reducer, workspace): """ @@ -994,7 +963,7 @@ def execute(self, reducer, workspace): # Code from AssignSample self._clearPrevious(self._scatter_sample) - logs = self._assignHelper(reducer) + self._assignHelper(reducer) if self._period != self.UNSET_PERIOD: self.entries = [self._period] else: @@ -1008,28 +977,8 @@ def execute(self, reducer, workspace): if isinstance(p_run_ws, WorkspaceGroup): p_run_ws = p_run_ws[0] - try: - run_num = p_run_ws.getRun().getLogData('run_number').value - except RuntimeError: - # if the run number is not stored in the workspace, try to take it from the filename - run_num = os.path.basename(self._data_file).split('.')[0].split('-')[0].split('0')[-1] - try: - dummy = int(run_num) - except ValueError: - logger.notice('Could not extract run number from file name ' + self._data_file) - - reducer.instrument.set_up_for_run(run_num) - - if reducer.instrument.name() == 'SANS2D': - if logs == None: - DeleteWorkspace(self.wksp_name) - raise RuntimeError('Sample logs cannot be loaded, cannot continue') - reducer.instrument.apply_detector_logs(logs) - - beamcoords = reducer.get_beam_center() - reducer.instrument.move_components(self.wksp_name, beamcoords[0], beamcoords[1]) + reducer.instrument.on_load_sample(self.wksp_name, reducer.get_beam_center(), True) - return logs def get_group_name(self): return self._get_workspace_name(self._period) From f3bd22cb01ad1fdb40ad455b99e61e62ce3c3706 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Wed, 13 Nov 2013 16:06:26 +0000 Subject: [PATCH 06/18] re #8438: Remove never called method from isis_instrument::LOQ --- Code/Mantid/scripts/SANS/isis_instrument.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_instrument.py b/Code/Mantid/scripts/SANS/isis_instrument.py index 891c92807f25..7d98d0780a0f 100644 --- a/Code/Mantid/scripts/SANS/isis_instrument.py +++ b/Code/Mantid/scripts/SANS/isis_instrument.py @@ -678,12 +678,6 @@ def load_transmission_inst(self, ws_trans, ws_direct, beamcentre): LoadInstrument(Workspace=ws_trans,Filename= trans_definition_file, RewriteSpectraMap=False) LoadInstrument(Workspace=ws_direct, Filename = trans_definition_file, RewriteSpectraMap=False) - def check_can_logs(self): - """ - This function does nothing for LOQ - """ - pass - def cur_detector_position(self, ws_name): """Return the position of the center of the detector bank""" ws = mtd[ws_name] From 8508f1fd13b939e44b86a0163079c057b9376643 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 10:48:02 +0000 Subject: [PATCH 07/18] re #8435: Separate Can and CanSubtraction now, reducer has a _can_run that works similarly to the _sample_run, and CanSubtraction does only reduce the Can if it is present. --- .../scripts/SANS/ISISCommandInterface.py | 23 +++------- Code/Mantid/scripts/SANS/isis_reducer.py | 34 +++++++++++--- .../scripts/SANS/isis_reduction_steps.py | 46 +++---------------- 3 files changed, 42 insertions(+), 61 deletions(-) diff --git a/Code/Mantid/scripts/SANS/ISISCommandInterface.py b/Code/Mantid/scripts/SANS/ISISCommandInterface.py index 637a8ab8254f..78bcff9a9e37 100644 --- a/Code/Mantid/scripts/SANS/ISISCommandInterface.py +++ b/Code/Mantid/scripts/SANS/ISISCommandInterface.py @@ -254,19 +254,10 @@ def AssignCan(can_run, reload = True, period = isis_reduction_steps.LoadRun.UNSE mes += ', ' + str(period) mes += ')' _printMessage(mes) - - if (not can_run) or (isinstance(can_run,str) and can_run.startswith('.')): - ReductionSingleton().background_subtracter = None - return '', None - - ReductionSingleton().background_subtracter = \ - isis_reduction_steps.CanSubtraction( - can_run, reload=reload, period=period) - #ideally this code should live in a separate load can object - ReductionSingleton().background_subtracter.assign_can( - ReductionSingleton()) + + ReductionSingleton().set_can(can_run, reload, period) return _return_old_compatibility_assign_methods( - ReductionSingleton().background_subtracter.workspace.wksp_name) + ReductionSingleton().get_can().wksp_name) def TransmissionSample(sample, direct, reload = True, period_t = -1, period_d = -1): """ @@ -341,12 +332,12 @@ def GetMismatchedDetList(): def _setUpPeriod(i): trans_samp = ReductionSingleton().samp_trans_load - can = ReductionSingleton().background_subtracter + can = ReductionSingleton().get_can() trans_can = ReductionSingleton().can_trans_load new_sample_workspaces = AssignSample(ReductionSingleton().get_sample().loader._data_file, period=i)[0] if can: #replace one thing that gets overwritten - AssignCan(can.workspace._data_file, True, period=can.workspace.getCorrospondingPeriod(i, ReductionSingleton())) + AssignCan(can.loader._data_file, True, period=can.loader.getCorrospondingPeriod(i, ReductionSingleton())) if trans_samp: trans = trans_samp.trans direct = trans_samp.direct @@ -455,8 +446,8 @@ def WavRangeReduction(wav_start=None, wav_end=None, full_trans_wav=None, name_su ReductionSingleton().instrument.setDetector('front') ReductionSingleton()._sample_run.reload(ReductionSingleton()) #reassign can - if ReductionSingleton().background_subtracter: - ReductionSingleton().background_subtracter.assign_can(ReductionSingleton()) + if ReductionSingleton().get_can(): + ReductionSingleton().get_can().reload(ReductionSingleton()) if ReductionSingleton().samp_trans_load: #refresh Transmission ReductionSingleton().samp_trans_load.execute(ReductionSingleton(), None) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 0edc7c102468..2a6e211ee936 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -30,6 +30,7 @@ def _deepcopy_method(x, memo): current_settings = None class Sample(object): + ISSAMPLE = True def __init__(self): #will contain a LoadSample() object that converts the run number into a file name and loads that file self.loader = None @@ -62,14 +63,21 @@ def set_run(self, run, reload, period, reducer): self.period_option = period self.loader = isis_reduction_steps.LoadSample(run, reload, period) - self.loader.execute(reducer, None) - - self.geometry.execute(None, self.get_wksp_name()) + self.loader.execute(reducer, self.ISSAMPLE) + if self.ISSAMPLE: + self.geometry.execute(None, self.get_wksp_name()) def get_wksp_name(self): return self.loader.wksp_name + def get_periods_in_file(self): + return self.loader.periods_in_file + wksp_name = property(get_wksp_name, None, None, None) + periods_in_file = property(get_periods_in_file, None, None, None) + +class Can(Sample): + ISSAMPLE = False class ISISReducer(SANSReducer): """ @@ -110,7 +118,7 @@ def _to_steps(self): proc_wav.append(self._corr_and_scale) proc_wav.append(self.geometry_correcter) - self._can = [self.background_subtracter] + self._can = [self._background_subtracter] # self._tidy = [self._zero_error_flags] self._tidy = [self._rem_nans] @@ -149,7 +157,7 @@ def _init_steps(self): self.to_Q = isis_reduction_steps.ConvertToQISIS( self.prep_normalize) - self.background_subtracter = None + self._background_subtracter = isis_reduction_steps.CanSubtraction() self.geometry_correcter = sans_reduction_steps.SampleGeomCor( self._sample_run.geometry) # self._zero_error_flags=isis_reduction_steps.ReplaceErrors() @@ -161,6 +169,7 @@ def __init__(self): SANSReducer.__init__(self) self._dark_current_subtracter_class = None self._sample_run = Sample() + self._can_run = Can() self.output_wksp = None self.full_trans_wav = False self._monitor_set = False @@ -197,6 +206,9 @@ def set_sample(self, run, reload, period): @param period: the period within the sample to be analysed """ self._sample_run.set_run(run, reload, period, self) + + def set_can(self, run, reload, period): + self._can_run.set_run(run, reload, period, self) def get_sample(self): """ @@ -206,7 +218,17 @@ def get_sample(self): if not self._process_can: return self._sample_run else: - return self.background_subtracter + return self.get_can() + + def get_can(self): + if self._can_run.loader and self._can_run.wksp_name: + return self._can_run + else: + return None + + # for compatibility reason, previously, background_subtracter was used to + # query if the can was provided and for the can reduction. + background_subtracter = property(get_can, None, None, None) def get_out_ws_name(self, show_period=True): """ diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index e7fc9e661e34..1766d757bc3b 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -374,40 +374,17 @@ class CanSubtraction(ReductionStep): Apply the same corrections to the can that were applied to the sample and then subtracts this can from the sample. """ - def __init__(self, can_run, reload = True, period = -1): - """ - @param can_run: the run number followed by dot and the extension - @param reload: if set to true (default) the workspace is replaced if it already exists - @param period: for multiple entry workspaces this is the period number - """ + def __init__(self): super(CanSubtraction, self).__init__() - #contains the workspace with the background (can) data - self.workspace = LoadRun(can_run, reload=reload, entry=period) - - def assign_can(self, reducer): - """ - Loads the can workspace into Mantid and reads any log file - @param reducer: the reduction chain - @return: the logs object - """ - if not reducer.user_settings.executed: - raise RuntimeError('User settings must be loaded before the can can be loaded, run UserFile() first') - - self.workspace._assignHelper(reducer) - - if self.workspace.wksp_name == '': - sanslog.warning('Unable to load SANS can run, cannot continue.') - return '()' - - reducer.instrument.on_load_sample(self.workspace.wksp_name, - reducer.get_beam_center(), - isSample=False) def execute(self, reducer, workspace): """ Apply same corrections as for sample workspace then subtract from data """ - #remain the sample workspace, its name will be restored to the original once the subtraction has been done + if reducer.get_can() is None: + return + + #rename the sample workspace, its name will be restored to the original once the subtraction has been done tmp_smp = workspace+"_sam_tmp" RenameWorkspace(InputWorkspace=workspace,OutputWorkspace= tmp_smp) @@ -956,13 +933,10 @@ def __init__(self, sample=None, reload=True, entry=-1): #is set to the entry (period) number in the sample to be run self.entries = [] - def execute(self, reducer, workspace): + def execute(self, reducer, isSample): if not reducer.user_settings.executed: raise RuntimeError('User settings must be loaded before the sample can be assigned, run UserFile() first') - # Code from AssignSample - self._clearPrevious(self._scatter_sample) - self._assignHelper(reducer) if self._period != self.UNSET_PERIOD: self.entries = [self._period] @@ -972,13 +946,7 @@ def execute(self, reducer, workspace): if self.wksp_name == '': raise RuntimeError('Unable to load SANS sample run, cannot continue.') - p_run_ws = mtd[self.wksp_name] - - if isinstance(p_run_ws, WorkspaceGroup): - p_run_ws = p_run_ws[0] - - reducer.instrument.on_load_sample(self.wksp_name, reducer.get_beam_center(), True) - + reducer.instrument.on_load_sample(self.wksp_name, reducer.get_beam_center(), isSample) def get_group_name(self): return self._get_workspace_name(self._period) From 2c97efdb0045dc76847894a93d4e4ab711770e8c Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 10:49:03 +0000 Subject: [PATCH 08/18] re #8435: Adjust usage of background_subtracter inside Mantid Where it was being used, it is now corrected. --- Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp | 2 +- Code/Mantid/scripts/SANS/centre_finder.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp index 7ccd5f3ecd8b..f9282192ab18 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp @@ -1826,7 +1826,7 @@ bool SANSRunWindow::handleLoadButtonClick() else { is_loaded &= assignDetBankRun(*(m_uiForm.scatCan), "AssignCan"); - readNumberOfEntries("background_subtracter", m_uiForm.scatCan); + readNumberOfEntries("get_can().loader", m_uiForm.scatCan); } if ( ( ! m_uiForm.transmis->isEmpty() ) && ( ! m_uiForm.direct->isEmpty() ) ) { diff --git a/Code/Mantid/scripts/SANS/centre_finder.py b/Code/Mantid/scripts/SANS/centre_finder.py index a605568d23f9..e9a3f61ed20e 100644 --- a/Code/Mantid/scripts/SANS/centre_finder.py +++ b/Code/Mantid/scripts/SANS/centre_finder.py @@ -45,7 +45,7 @@ def SeekCentre(self, setup, trial): self._group_into_quadrants(setup, 'centre', trial[0], trial[1], suffix='_tmp') - if setup.background_subtracter: + if setup.get_can(): #reduce the can here setup.reduce_can('centre_can', run_Q=False) @@ -100,8 +100,8 @@ def move(self, setup, x, y): y = -y MoveInstrumentComponent(Workspace=setup.get_sample().wksp_name, ComponentName=self.detector, X=x, Y=y, RelativePosition=True) - if setup.background_subtracter: - MoveInstrumentComponent(Workspace=setup.background_subtracter.workspace.wksp_name, + if setup.get_can(): + MoveInstrumentComponent(Workspace=setup.get_can().wksp_name, ComponentName=self.detector, X=x, Y=y, RelativePosition=True) # Create a workspace with a quadrant value in it From 1738e5ea133d941a4ec6f28eaf49a1ba9ef341c4 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 11:20:55 +0000 Subject: [PATCH 09/18] re #8435: TransmissionCalc does not use anything from BaseTransmission Remove the non-sense inheritance. --- Code/Mantid/scripts/SANS/isis_reducer.py | 6 ++---- Code/Mantid/scripts/SANS/isis_reduction_steps.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 2a6e211ee936..34e55dbde6ef 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -395,15 +395,13 @@ def set_trans_fit(self, lambda_min=None, lambda_max=None, fit_method="Log", sele self.transmission_calculator.set_trans_fit(fit_method, lambda_min, lambda_max, override=True, selector=selector) def set_trans_sample(self, sample, direct, reload=True, period_t = -1, period_d = -1): - if not issubclass(self.samp_trans_load.__class__, sans_reduction_steps.BaseTransmission): - self.samp_trans_load = isis_reduction_steps.LoadTransmissions(reload=reload) + self.samp_trans_load = isis_reduction_steps.LoadTransmissions(reload=reload) self.samp_trans_load.set_trans(sample, period_t) self.samp_trans_load.set_direc(direct, period_d) self.transmission_calculator.samp_loader = self.samp_trans_load def set_trans_can(self, can, direct, reload = True, period_t = -1, period_d = -1): - if not issubclass(self.can_trans_load.__class__, sans_reduction_steps.BaseTransmission): - self.can_trans_load = isis_reduction_steps.LoadTransmissions(is_can=True, reload=reload) + self.can_trans_load = isis_reduction_steps.LoadTransmissions(is_can=True, reload=reload) self.can_trans_load.set_trans(can, period_t) self.can_trans_load.set_direc(direct, period_d) self.transmission_calculator.can_loader = self.can_trans_load diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 1766d757bc3b..3440d6522461 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -1028,7 +1028,7 @@ def execute(self, reducer, workspace): r_alg = 'Rebin' reducer.to_wavelen.execute(reducer, self.output_wksp, bin_alg=r_alg) -class TransmissionCalc(sans_reduction_steps.BaseTransmission): +class TransmissionCalc(ReductionStep): """ Calculates the proportion of neutrons that are transmitted through the sample as a function of wavelength. The results are stored as a workspace From c72f2fdd0136a136ecd375bf01a49d7cbb46311f Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 13:18:37 +0000 Subject: [PATCH 10/18] re #8435: Separate LoadTransmission and TransmissionCalc One is related to loading data and the other to is a reduction step. --- Code/Mantid/scripts/SANS/isis_reducer.py | 14 +++++++++-- .../scripts/SANS/isis_reduction_steps.py | 23 +------------------ 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 34e55dbde6ef..7dec0413f9d2 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -220,6 +220,18 @@ def get_sample(self): else: return self.get_can() + def get_transmissions(self): + """ Get the transmission and direct workspace if they were given + for the can and for the sample""" + if self._process_can: + loader = self.can_trans_load + else: + loader = self.samp_trans_load + if loader: + return loader.trans.wksp_name, loader.direct.wksp_name + else: + return "", "" + def get_can(self): if self._can_run.loader and self._can_run.wksp_name: return self._can_run @@ -398,13 +410,11 @@ def set_trans_sample(self, sample, direct, reload=True, period_t = -1, period_d self.samp_trans_load = isis_reduction_steps.LoadTransmissions(reload=reload) self.samp_trans_load.set_trans(sample, period_t) self.samp_trans_load.set_direc(direct, period_d) - self.transmission_calculator.samp_loader = self.samp_trans_load def set_trans_can(self, can, direct, reload = True, period_t = -1, period_d = -1): self.can_trans_load = isis_reduction_steps.LoadTransmissions(is_can=True, reload=reload) self.can_trans_load.set_trans(can, period_t) self.can_trans_load.set_direc(direct, period_d) - self.transmission_calculator.can_loader = self.can_trans_load def set_monitor_spectrum(self, specNum, interp=False, override=True): if override: diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 3440d6522461..2cabee925483 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -1061,10 +1061,6 @@ def __init__(self, loader=None): self.fit_settings = dict() for prop in self.fit_props: self.fit_settings['both::'+prop] = None - # An optional LoadTransmissions object that contains the names of the transmission and direct workspaces for the sample - self.samp_loader = None - # An optional LoadTransmissions objects for the can's transmission and direct workspaces - self.can_loader = None # this contains the spectrum number of the monitor that comes after the sample from which the transmission calculation is done self._trans_spec = None # use InterpolatingRebin @@ -1079,19 +1075,6 @@ def __init__(self, loader=None): self.loq_removePromptPeakMax = 20500.0 - def _loader(self, reducer): - """ - Returns the transmission loader objects for either the sample or the can depending - on the reduction object passed - @param reducer: the reduction chain of interest - @return: information on the transmission workspaces if these were loaded - """ - if reducer.is_can(): - return self.can_loader - else: - return self.samp_loader - - def set_trans_fit(self, fit_method, min_=None, max_=None, override=True, selector='both'): """ Set how the transmission fraction fit is calculated, the range of wavelengths @@ -1238,11 +1221,7 @@ def _get_run_wksps(self, reducer): of the transmission @return: post_sample pre_sample workspace names """ - loader = self._loader(reducer) - if (not loader) or (not loader.trans.wksp_name): - return '', '' - else: - return loader.trans.wksp_name, loader.direct.wksp_name + return reducer.get_transmissions() def calculate(self, reducer): LAMBDAMIN = 'lambda_min' From b9afd2e7a3a19ee5ff30ae8d39a3b8e041686436 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 13:20:31 +0000 Subject: [PATCH 11/18] re #8435: Express that loading data is not reduction step --- Code/Mantid/scripts/SANS/isis_reduction_steps.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 2cabee925483..eb0b8ed502d7 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -316,7 +316,7 @@ def getCorrospondingPeriod(self, sample_period, reducer): raise RuntimeError('There is a mismatch in the number of periods (entries) in the file between the sample and another run') -class LoadTransmissions(ReductionStep): +class LoadTransmissions(): """ Loads the file used to apply the transmission correction to the sample or can @@ -330,7 +330,6 @@ def __init__(self, is_can=False, reload=True): @param is_can: if this is to correct the can (default false i.e. it's for the sample) @param reload: setting this to false will mean the workspaces aren't reloaded if they already exist (default True i.e. reload) """ - super(LoadTransmissions, self).__init__() self.trans = None self.direct = None self._reload = reload @@ -918,14 +917,13 @@ def __str__(self): ' front time mask: ', str(self.time_mask_f)+'\n' -class LoadSample(LoadRun, ReductionStep): +class LoadSample(LoadRun): """ Handles loading the sample run, this is the main experimental run with data about the sample of interest """ def __init__(self, sample=None, reload=True, entry=-1): LoadRun.__init__(self, sample, reload=reload, entry=entry) - ReductionStep.__init__(self) self._scatter_sample = None self._SAMPLE_RUN = None From 76e8cf244b0bf15cded5d3553aec7569677aeafb Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 13:34:48 +0000 Subject: [PATCH 12/18] re #8435: Impose that AssignSample will be always the first This commit ensures that the reduction will never use can or transmission from previous time. It will help to the goal of removing the copy and creation of more than one singleton inside the current reduction. --- Code/Mantid/scripts/SANS/isis_reducer.py | 14 ++++++++++---- Code/Mantid/scripts/SANS/isis_reduction_steps.py | 6 ------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 7dec0413f9d2..8e00cdd5e140 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -139,8 +139,6 @@ def _init_steps(self): #except self.prep_normalize all the steps below are used by the reducer self.crop_detector = isis_reduction_steps.CropDetBank(crop_sample=True) - self.samp_trans_load = None - self.can_trans_load = None self.mask =self._mask= isis_reduction_steps.Mask_ISIS() self.to_wavelen = isis_reduction_steps.UnitsConvert('Wavelength') self.norm_mon = isis_reduction_steps.NormalizeToMonitor() @@ -168,8 +166,6 @@ def _init_steps(self): def __init__(self): SANSReducer.__init__(self) self._dark_current_subtracter_class = None - self._sample_run = Sample() - self._can_run = Can() self.output_wksp = None self.full_trans_wav = False self._monitor_set = False @@ -197,6 +193,14 @@ def __init__(self): self.__transmission_sample = "" # register the value of transmission can self.__transmission_can = "" + self.clean_loaded_data() + + + def clean_loaded_data(self): + self._sample_run = Sample() + self._can_run = Can() + self.samp_trans_load = None + self.can_trans_load = None def set_sample(self, run, reload, period): """ @@ -205,6 +209,8 @@ def set_sample(self, run, reload, period): @param reload: if this sample should be reloaded before the first reduction @param period: the period within the sample to be analysed """ + # ensure that when you set sample, you start with no can, transmission previously used. + self._clean_loaded_data() self._sample_run.set_run(run, reload, period, self) def set_can(self, run, reload, period): diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index eb0b8ed502d7..b7777f075004 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -239,12 +239,6 @@ def _leaveSinglePeriod(self, workspace, period): DeleteWorkspace(groupW.getName()) return newName - def _clearPrevious(self, inWS, others = []): - if inWS != None: - if inWs in mtd and (not inWS in others): - DeleteWorkspace(inWs) - - def _extract_run_details(self, run_string): """ Takes a run number and file type and generates the filename, workspace name and log name From 6beb096c9b2e1ca0d92f2022329c99c776f25c64 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 13:36:19 +0000 Subject: [PATCH 13/18] re #8435: SANS Reduction this is a temporary comment to explain why this code still works. It is my intention to get rid of the _setUpPeriod method by applying a better way of ensuring the execution of multiperiod data. --- Code/Mantid/scripts/SANS/ISISCommandInterface.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Code/Mantid/scripts/SANS/ISISCommandInterface.py b/Code/Mantid/scripts/SANS/ISISCommandInterface.py index 78bcff9a9e37..4f106c573fc6 100644 --- a/Code/Mantid/scripts/SANS/ISISCommandInterface.py +++ b/Code/Mantid/scripts/SANS/ISISCommandInterface.py @@ -331,6 +331,11 @@ def GetMismatchedDetList(): return ReductionSingleton().instrument.get_marked_dets() def _setUpPeriod(i): + # it first get the reference to the loaders, then it calls the AssignSample + # (which get rid of the reducer objects (see clean_loaded_data()) + # but because we still get the reference, we can use it to query the data file and method. + # ideally, we should not use this _setUpPeriod in the future. + trans_samp = ReductionSingleton().samp_trans_load can = ReductionSingleton().get_can() trans_can = ReductionSingleton().can_trans_load From 4ead550ab3a4d8a59d1aa0594660e3216eb1608c Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 14:47:03 +0000 Subject: [PATCH 14/18] re #8435: Fixing UnitTest SansIsisGuiSettings --- Code/Mantid/scripts/SANS/isis_reducer.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 8e00cdd5e140..99fc493d83bf 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -163,6 +163,12 @@ def _init_steps(self): self.set_Q_output_type(self.to_Q.output_type) + def _clean_loaded_data(self): + self._sample_run = Sample() + self._can_run = Can() + self.samp_trans_load = None + self.can_trans_load = None + def __init__(self): SANSReducer.__init__(self) self._dark_current_subtracter_class = None @@ -176,6 +182,7 @@ def __init__(self): #all workspaces created by this reducer self._workspace = [self._temporys, self._outputs] + self._clean_loaded_data() self._init_steps() #process the background (can) run instead of the sample @@ -193,15 +200,8 @@ def __init__(self): self.__transmission_sample = "" # register the value of transmission can self.__transmission_can = "" - self.clean_loaded_data() - def clean_loaded_data(self): - self._sample_run = Sample() - self._can_run = Can() - self.samp_trans_load = None - self.can_trans_load = None - def set_sample(self, run, reload, period): """ Assigns and load the run that this reduction chain will analysis From eb0beb186d1436938cdce23440c2b9e7ff19872e Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Thu, 14 Nov 2013 16:16:24 +0000 Subject: [PATCH 15/18] re #8435: Ensure geometry correction gets the correct information --- Code/Mantid/scripts/SANS/isis_reducer.py | 3 +-- .../instruments/sans/sans_reduction_steps.py | 15 ++------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 99fc493d83bf..56a1c31d7042 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -156,8 +156,7 @@ def _init_steps(self): self.to_Q = isis_reduction_steps.ConvertToQISIS( self.prep_normalize) self._background_subtracter = isis_reduction_steps.CanSubtraction() - self.geometry_correcter = sans_reduction_steps.SampleGeomCor( - self._sample_run.geometry) + self.geometry_correcter = sans_reduction_steps.SampleGeomCor() # self._zero_error_flags=isis_reduction_steps.ReplaceErrors() self._rem_nans = sans_reduction_steps.StripEndNans() diff --git a/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py b/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py index c24203a62666..260bdd3d3dea 100644 --- a/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py +++ b/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py @@ -750,23 +750,12 @@ class SampleGeomCor(ReductionStep): ORNL only divides by thickness, in the absolute scaling step """ - def __init__(self, geometry): - """ - Takes a reference to the sample geometry - @param geometry: A GetSampleGeom object to load the sample dimensions from - @raise TypeError: if an object of the wrong type is passed to it - """ - super(SampleGeomCor, self).__init__() - - if issubclass(geometry.__class__, GetSampleGeom): - self.geo = geometry - else: - raise TypeError, 'Sample geometry correction requires a GetSampleGeom object' - def execute(self, reducer, workspace): """ Divide the counts by the volume of the sample """ + self.geo = reducer._sample_run.geometry + assert( issubclass(self.geo.__class__, GetSampleGeom)) try: if self.geo.shape == 'cylinder-axis-up': From 52975a3c701d64c5be88802a206f7df9e313cabb Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Mon, 18 Nov 2013 09:45:27 +0000 Subject: [PATCH 16/18] re #8443: SANS reduce CAN does not create new singleton --- Code/Mantid/scripts/SANS/isis_reducer.py | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index 56a1c31d7042..d6a286386bbf 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -330,24 +330,28 @@ def reduce_can(self, new_wksp=None, run_Q=True): @param new_wksp: the name of the workspace that will store the result @param run_Q: set to false to stop just before converting to Q, default is convert to Q """ - # copy all the run settings from the sample, these settings can come from the user file, Python scripting or the GUI - new_reducer = self.deep_copy() - - new_reducer._process_can = True - #set the workspace that we've been setting up as the one to be processed - new_reducer.output_wksp = new_wksp + # copy settings + sample_wksp_name = self.output_wksp + sample_trans_name = self.transmission_calculator.output_wksp + + # configure can + self._process_can = True + # set the workspace that we've been setting up as the one to be processed + self.output_wksp = new_wksp - can_steps = new_reducer._conv_Q + can_steps = self._conv_Q if not run_Q: #the last step in the list must be ConvertToQ or this wont work can_steps = can_steps[0:len(can_steps)-1] #the reducer is completely setup, run it - new_reducer._reduce(init=False, post=False, steps=can_steps) - ## after the reduction of can, the new_reducer will be discarded - ## so, we will keep the information of the transmission and save it - ## inside the __transmission_can attribute. - self.__transmission_can = new_reducer.transmission_calculator.output_wksp + self._reduce(init=False, post=False, steps=can_steps) + + # restore settings + self._process_can = False + self.output_wksp = sample_wksp_name + self.__transmission_can = self.transmission_calculator.output_wksp + self.__transmission_sample = sample_trans_name def run_from_raw(self): """ From 4c93a275685e90d3bbf6fb10bf86bf1ad7aa79c2 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Mon, 18 Nov 2013 13:01:06 +0000 Subject: [PATCH 17/18] re #8443: Correct dealing with transmission names --- Code/Mantid/scripts/SANS/isis_reducer.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/scripts/SANS/isis_reducer.py b/Code/Mantid/scripts/SANS/isis_reducer.py index d6a286386bbf..3541a5ee16ae 100644 --- a/Code/Mantid/scripts/SANS/isis_reducer.py +++ b/Code/Mantid/scripts/SANS/isis_reducer.py @@ -333,7 +333,6 @@ def reduce_can(self, new_wksp=None, run_Q=True): # copy settings sample_wksp_name = self.output_wksp sample_trans_name = self.transmission_calculator.output_wksp - # configure can self._process_can = True # set the workspace that we've been setting up as the one to be processed @@ -379,8 +378,11 @@ def post_process(self): AddSampleLog(Workspace=self.output_wksp,LogName="UserFile", LogText=user_file) # get the value of __transmission_sample from the transmission_calculator if it has - if self.transmission_calculator and self.transmission_calculator.output_wksp: + if (not self.get_can()) and self.transmission_calculator.output_wksp: + # it updates only if there was not can, because, when there is can, the __transmission_sample + # is already correct and transmission_calculator.output_wksp points to the can transmission self.__transmission_sample = self.transmission_calculator.output_wksp + # The reducer itself sometimes will be reset, and the users of the singleton # not always will have access to its settings. So, we will add the transmission workspaces # to the SampleLog, to be connected to the workspace, and be available outside. These values @@ -390,6 +392,10 @@ def post_process(self): if self.__transmission_can: AddSampleLog(Workspace=self.output_wksp,LogName= "TransmissionCan", LogText=self.__transmission_can + str('_unfitted')) + # clean these values for subsequent executions + self.__transmission_sample = "" + self.__transmission_can = "" + for role in self._temporys.keys(): try: DeleteWorkspace(Workspace=self._temporys[role]) From 4a28c1847b6cda18442fdb4b05be4b44953fb968 Mon Sep 17 00:00:00 2001 From: Gesner Passos Date: Mon, 18 Nov 2013 15:16:18 +0000 Subject: [PATCH 18/18] re #8455: SampleGeomCor uses only public methods from isis_reducer Code improvement. It does not use the protected attribute _sample_run, but only public methods. Besides, it does not calculate twice the same value for volume, using the value calculated already. --- .../instruments/sans/sans_reduction_steps.py | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py b/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py index 260bdd3d3dea..12ebbe390eed 100644 --- a/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py +++ b/Code/Mantid/scripts/reduction/instruments/sans/sans_reduction_steps.py @@ -750,35 +750,45 @@ class SampleGeomCor(ReductionStep): ORNL only divides by thickness, in the absolute scaling step """ - def execute(self, reducer, workspace): - """ - Divide the counts by the volume of the sample - """ - self.geo = reducer._sample_run.geometry - assert( issubclass(self.geo.__class__, GetSampleGeom)) + def __init__(self): + self.volume = 1.0 + + def calculate_volume(self, reducer): + geo = reducer.get_sample().geometry + assert( issubclass(geo.__class__, GetSampleGeom)) try: - if self.geo.shape == 'cylinder-axis-up': + if geo.shape == 'cylinder-axis-up': # Volume = circle area * height # Factor of four comes from radius = width/2 - volume = self.geo.height*math.pi - volume *= math.pow(self.geo.width,2)/4.0 - elif self.geo.shape == 'cuboid': + volume = geo.height*math.pi + volume *= math.pow(geo.width,2)/4.0 + elif geo.shape == 'cuboid': # Flat plate sample - volume = self.geo.width - volume *= self.geo.height*self.geo.thickness - elif self.geo.shape == 'cylinder-axis-along': + volume = geo.width + volume *= geo.height*geo.thickness + elif geo.shape == 'cylinder-axis-along': # Factor of four comes from radius = width/2 # Disc - where height is not used - volume = self.geo.thickness*math.pi - volume *= math.pow(self.geo.width, 2)/4.0 + volume = geo.thickness*math.pi + volume *= math.pow(geo.width, 2)/4.0 else: - raise NotImplemented('Shape "'+self.geo.shape+'" is not in the list of supported shapes') + raise NotImplemented('Shape "'+geo.shape+'" is not in the list of supported shapes') except TypeError: - raise TypeError('Error calculating sample volume with width='+str(self._width) + ' height='+str(self._height) + 'and thickness='+str(self._thickness)) - - ws = mtd[workspace] - ws /= volume + raise TypeError('Error calculating sample volume with width='+str(geo.width) + ' height='+str(geo.height) + 'and thickness='+str(geo.thickness)) + + return volume + + def execute(self, reducer, workspace): + """ + Divide the counts by the volume of the sample + """ + if not reducer.is_can(): + # it calculates the volume for the sample and may or not apply to the can as well. + self.volume = self.calculate_volume(reducer) + + ws = mtd[str(workspace)] + ws /= self.volume class StripEndZeros(ReductionStep): # ISIS only