diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/SetupEQSANSReduction.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/SetupEQSANSReduction.cpp index bf7a84450323e7a4a3ac35a2ed886d0378acdf07..255573f0932c6b648cfca5866248be5750bdf655 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/SetupEQSANSReduction.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/SetupEQSANSReduction.cpp @@ -50,7 +50,12 @@ void SetupEQSANSReduction::init() declareProperty("SkipTOFCorrection", false, "IF true, the EQSANS TOF correction will be skipped"); declareProperty("PreserveEvents", true, "If true, the output workspace will be an event workspace"); + declareProperty("LoadMonitors", false, "If true, the monitor workspace will be loaded"); + declareProperty("NormaliseToBeam", true, "If true, the data will be normalised to the total charge and divided by the beam profile"); + declareProperty("NormaliseToMonitor", false, "If true, the data will be normalised to the monitor, otherwise the total charge will be used"); + declareProperty(new API::FileProperty("MonitorReferenceFile", "", API::FileProperty::OptionalLoad, "_event.nxs"), + "The name of the beam monitor reference file used for normalisation"); declareProperty("SolidAngleCorrection", true, "If true, the solide angle correction will be applied to the data"); @@ -67,6 +72,10 @@ void SetupEQSANSReduction::init() setPropertyGroup("PreserveEvents", load_grp); setPropertyGroup("LoadMonitors", load_grp); + setPropertyGroup("NormaliseToBeam", load_grp); + setPropertyGroup("NormaliseToMonitor", load_grp); + setPropertyGroup("MonitorReferenceFile", load_grp); + setPropertyGroup("SolidAngleCorrection", load_grp); declareProperty("SampleDetectorDistance", EMPTY_DBL(), "Sample to detector distance to use (overrides meta data), in mm"); @@ -134,14 +143,14 @@ void SetupEQSANSReduction::init() declareProperty(new API::FileProperty("TransmissionDirectBeam", "", API::FileProperty::OptionalLoad, "_event.nxs"), "Direct beam data file used to compute transmission"); - declareProperty(new API::FileProperty("TransmissionEmptyBeam", "", API::FileProperty::OptionalLoad, "_event.nxs"), "Empty beam data file used to compute transmission"); + declareProperty("ThetaDependentTransmission",true, "If true, a theta-dependent transmission correction will be used"); setPropertySettings("TransmissionValue", new EnabledWhenProperty("SetupReducer", IS_EQUAL_TO, "1") ); setPropertySettings("TransmissionDirectBeam", new EnabledWhenProperty("SetupReducer", IS_EQUAL_TO, "1") ); setPropertySettings("TransmissionEmptyBeam", new EnabledWhenProperty("SetupReducer", IS_EQUAL_TO, "1") ); - + setPropertySettings("ThetaDependentTransmission", new EnabledWhenProperty("SetupReducer", IS_EQUAL_TO, "1") ); // Outputs declareProperty("OutputMessage","",Direction::Output); @@ -163,6 +172,30 @@ void SetupEQSANSReduction::exec() // Store name of the instrument reductionManager->declareProperty(new PropertyWithValue<std::string>("InstrumentName", "EQSANS") ); + // Store normalization algorithm + bool loadMonitors = getProperty("LoadMonitors"); + const bool normalizeToBeam = getProperty("NormaliseToBeam"); + const bool normalizeToMonitor = getProperty("NormaliseToMonitor"); + const std::string monitorRefFile = getPropertyValue("MonitorReferenceFile"); + // If we normalize to monitor, force the loading of monitor data + IAlgorithm_sptr normAlg = createSubAlgorithm("EQSANSNormalise"); + if (normalizeToMonitor) + { + loadMonitors = true; + if (monitorRefFile.size()==0) + { + g_log.error() << "ERROR: normalize-to-monitor was turned ON but no reference data was selected" << std::endl; + return; + } + normAlg->setProperty("NormaliseToMonitor", true); + normAlg->setProperty("BeamSpectrumFile", monitorRefFile); + } else { + normAlg->setProperty("NormaliseToBeam", normalizeToBeam); + } + normAlg->setPropertyValue("ReductionProperties", reductionManagerName); + reductionManager->declareProperty(new AlgorithmProperty("NormaliseAlgorithm")); + reductionManager->setProperty("NormaliseAlgorithm", normAlg); + // Load algorithm IAlgorithm_sptr loadAlg = createSubAlgorithm("EQSANSLoad"); const bool useConfigBeam = getProperty("UseConfigBeam"); @@ -185,7 +218,6 @@ void SetupEQSANSReduction::exec() const bool preserveEvents = getProperty("PreserveEvents"); loadAlg->setProperty("PreserveEvents", preserveEvents); - const bool loadMonitors = getProperty("LoadMonitors"); loadAlg->setProperty("LoadMonitors", loadMonitors); const double sdd = getProperty("SampleDetectorDistance"); @@ -295,7 +327,8 @@ void SetupEQSANSReduction::initializeReduction(boost::shared_ptr<PropertyManager { // Write the Reducer python script to be executed std::string script = "import reduction.instruments.sans.sns_command_interface as cmd\n"; - + const std::string reductionManagerName = getProperty("ReductionProperties"); + const bool preserveEvents = getProperty("PreserveEvents"); // - beam center double center_x = 0.0; @@ -309,7 +342,10 @@ void SetupEQSANSReduction::initializeReduction(boost::shared_ptr<PropertyManager else throw std::runtime_error("EQSANSReduce not yet compatible with beam finder: enter beam center coordinates"); - script += "cmd.EQSANS()\n"; + if (preserveEvents) + script += "cmd.EQSANS(True, \"" + reductionManagerName + "\")\n"; + else + script += "cmd.EQSANS(False, \"" + reductionManagerName + "\")\n"; script += "cmd.SetBeamCenter(" + Poco::NumberFormatter::format(center_x, 2) + ", " + Poco::NumberFormatter::format(center_y, 2) + ")\n"; @@ -323,6 +359,12 @@ void SetupEQSANSReduction::initializeReduction(boost::shared_ptr<PropertyManager } // - load options + const bool useConfig = getProperty("UseConfig"); + if (useConfig) + script += "cmd.UseConfig(True)\n"; + else + script += "cmd.UseConfig(False)\n"; + if (reductionManager->existsProperty("LoadAlgorithm")) { IAlgorithm_sptr loadAlg = reductionManager->getProperty("LoadAlgorithm"); @@ -356,8 +398,41 @@ void SetupEQSANSReduction::initializeReduction(boost::shared_ptr<PropertyManager script += "cmd.UseConfigMask(use_config=False)\n"; } + // - Solid angle correction + const bool solidAngle = getProperty("SolidAngleCorrection"); + if (solidAngle) + script += "cmd.SolidAngle()\n"; + else + script += "cmd.NoSolidAngle()\n"; + + // - Dark current + const std::string darkCurrentFile = getPropertyValue("DarkCurrentFile"); + if (darkCurrentFile.size() > 0) + { + script += "cmd.DarkCurrent(\"" + darkCurrentFile + "\")\n"; + } + + // - Normalization options + if (reductionManager->existsProperty("NormaliseAlgorithm")) + { + IAlgorithm_sptr normAlg = reductionManager->getProperty("NormaliseAlgorithm"); + const bool normaliseToBeam = normAlg->getProperty("NormaliseToBeam"); + const bool normaliseToMonitor = normAlg->getProperty("NormaliseToMonitor"); + const std::string fileName = normAlg->getPropertyValue("BeamSpectrumFile"); + if (normaliseToMonitor) + { + script += "cmd.BeamMonitorNormalization(\"" + fileName + "\")\n"; + } else { + if (normaliseToBeam) + script += "cmd.TotalChargeNormalization(normalize_to_beam=True)\n"; + else + script += "cmd.TotalChargeNormalization(normalize_to_beam=False)\n"; + } + } + // - Transmission const double trans = getProperty("TransmissionValue"); + const bool thetaDependent = getProperty("ThetaDependentTransmission"); if (isEmpty(trans)) { const std::string directBeam = getPropertyValue("TransmissionDirectBeam"); @@ -365,11 +440,17 @@ void SetupEQSANSReduction::initializeReduction(boost::shared_ptr<PropertyManager script += "cmd.DirectBeamTransmission(\"" + directBeam + "\", \"" + emptyBeam + "\")\n"; - script += "cmd.ThetaDependentTransmission(False)\n"; + if (thetaDependent) + script += "cmd.ThetaDependentTransmission(True)\n"; + else + script += "cmd.ThetaDependentTransmission(False)\n"; } else { - script += "cmd.SetTransmission(" + Poco::NumberFormatter::format(trans, 2) + ", 0.0)\n"; + if (thetaDependent) + script += "cmd.SetTransmission(" + Poco::NumberFormatter::format(trans, 2) + ", 0.0, True)\n"; + else + script += "cmd.SetTransmission(" + Poco::NumberFormatter::format(trans, 2) + ", 0.0, False)\n"; } script += "cmd.ReductionSingleton().set_azimuthal_averager(None)\n"; diff --git a/Code/Mantid/scripts/Interface/reduction_gui/reduction/sans/eqsans_options_script.py b/Code/Mantid/scripts/Interface/reduction_gui/reduction/sans/eqsans_options_script.py index ad366fbfbcdbc0d60f630e17945a559b27fa70a3..dc4c2d0ffc4f04d6a75052366267d23e31a497a8 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/reduction/sans/eqsans_options_script.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/reduction/sans/eqsans_options_script.py @@ -97,7 +97,13 @@ class ReductionOptions(BaseOptions): if self.dark_current_corr: script += " DarkCurrentFile='%s',\n" % self.dark_current_data - #TODO: add monitor options + if self.normalization==ReductionOptions.NORMALIZATION_MONITOR: + if self.use_beam_monitor: + script += " NormaliseToMonitor=1,\n" + script += " MonitorReferenceFile='%s',\n" % self.beam_monitor_reference + else: + script += " NormaliseToMonitor=0,\n" + return script def _normalization_options(self): diff --git a/Code/Mantid/scripts/reduction/instruments/sans/sns_command_interface.py b/Code/Mantid/scripts/reduction/instruments/sans/sns_command_interface.py index 8020204912a22ad5314c449e160b959a55be1592..4539b356c9a203eaa2c17b7346a3ae51bb561d89 100644 --- a/Code/Mantid/scripts/reduction/instruments/sans/sns_command_interface.py +++ b/Code/Mantid/scripts/reduction/instruments/sans/sns_command_interface.py @@ -23,13 +23,16 @@ from reduction.find_data import find_data import mantidsimple -def EQSANS(keep_events=False): +def EQSANS(keep_events=False, property_manager=None): Clear(EqSansReducer) ReductionSingleton().set_instrument(sns_instrument.EQSANS()) NoSolidAngle() AzimuthalAverage() ReductionSingleton().set_data_loader(sns_reduction_steps.LoadRun(keep_events=keep_events)) - ReductionSingleton().set_reduction(sns_reduction_steps.EQSANSSetup()) + if property_manager is None: + ReductionSingleton().set_reduction(sns_reduction_steps.EQSANSSetup()) + else: + ReductionSingleton().set_reduction_table_name(property_manager) def FrameSkipping(value=False): raise RuntimeError, "The FrameSkipping command is no longer needed and no longer supported" diff --git a/Code/Mantid/scripts/reduction/instruments/sans/sns_reduction_steps.py b/Code/Mantid/scripts/reduction/instruments/sans/sns_reduction_steps.py index 18669cd74d21a438ecf7b816820c6448d8ba0047..bfcd54df1231f7a12cac7722124ce05596ebf80b 100644 --- a/Code/Mantid/scripts/reduction/instruments/sans/sns_reduction_steps.py +++ b/Code/Mantid/scripts/reduction/instruments/sans/sns_reduction_steps.py @@ -168,7 +168,9 @@ class AzimuthalAverageByFrame(WeightedAzimuthalAverage): qmin, qstep, qmax = self._get_binning(reducer, workspace, min(wl_min_f1, wl_min_f2), max(wl_max_f1, wl_max_f2)) self._binning = "%g, %g, %g" % (qmin, qstep, qmax) # Average second frame - Rebin(workspace, workspace+'_frame2', "%4.2f,%4.2f,%4.2f" % (wl_min_f2, 0.1, wl_max_f2), False) + Rebin(InputWorkspace=workspace, OutputWorkspace=workspace+'_frame2', + Params="%4.2f,%4.2f,%4.2f" % (wl_min_f2, 0.1, wl_max_f2), + PreserveEvents=False) ReplaceSpecialValues(workspace+'_frame2', workspace+'_frame2', NaNValue=0.0,NaNError=0.0) super(AzimuthalAverageByFrame, self).execute(reducer, workspace+'_frame2') @@ -183,7 +185,9 @@ class AzimuthalAverageByFrame(WeightedAzimuthalAverage): # Average first frame if self._independent_binning: self._binning = None - Rebin(workspace, workspace+'_frame1', "%4.2f,%4.2f,%4.2f" % (wl_min_f1, 0.1, wl_max_f1), False) + Rebin(InputWorkspace=workspace, OutputWorkspace=workspace+'_frame1', + Params="%4.2f,%4.2f,%4.2f" % (wl_min_f1, 0.1, wl_max_f1), + PreserveEvents=False) ReplaceSpecialValues(workspace+'_frame1', workspace+'_frame1', NaNValue=0.0,NaNError=0.0) super(AzimuthalAverageByFrame, self).execute(reducer, workspace+'_frame1') @@ -314,9 +318,15 @@ class DirectBeamTransmission(SingleFrameDirectBeamTransmission): else: raise RuntimeError, "DirectBeamTransmission could not retrieve the %s property" % wl_max_prop - Rebin(workspace, workspace+suffix, "%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), False) - Rebin(sample_mon_ws, sample_mon_ws+suffix, "%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), False) - Rebin(empty_mon_ws, empty_mon_ws+suffix, "%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), False) + Rebin(InputWorkspace=workspace, OutputWorkspace=workspace+suffix, + Params="%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), + PreserveEvents=False) + Rebin(InputWorkspace=sample_mon_ws, OutputWorkspace=sample_mon_ws+suffix, + Params="%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), + PreserveEvents=False) + Rebin(InputWorkspace=empty_mon_ws, OutputWorkspace=empty_mon_ws+suffix, + Params="%4.1f,%4.1f,%4.1f" % (wl_min, 0.1, wl_max), + PreserveEvents=False) self._calculate_transmission(sample_mon_ws+suffix, empty_mon_ws+suffix, first_det, self._transmission_ws+suffix) RebinToWorkspace(self._transmission_ws+suffix, workspace, OutputWorkspace=self._transmission_ws+suffix) RebinToWorkspace(self._transmission_ws+suffix+'_unfitted', workspace, OutputWorkspace=self._transmission_ws+suffix+'_unfitted') diff --git a/Code/Mantid/scripts/reduction/reducer.py b/Code/Mantid/scripts/reduction/reducer.py index 4f4b19f0e25f389bed0568cb5b70ff5a83251d11..2649a50cb8d4c349f710f40cc8062232304b756b 100644 --- a/Code/Mantid/scripts/reduction/reducer.py +++ b/Code/Mantid/scripts/reduction/reducer.py @@ -329,11 +329,15 @@ class Reducer(object): def __init__(self): self.UID = ''.join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for x in range(5)) + self.property_manager = "__reduction_parameters_"+self.UID self._data_files = {} self._reduction_steps = [] def get_reduction_table_name(self): - return "__reduction_parameters_"+self.UID + return self.property_manager + + def set_reduction_table_name(self, name): + self.property_manager = str(name) def set_instrument(self, configuration): if issubclass(configuration.__class__, Instrument):