diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentHelper.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentHelper.h index 94ef2c4bc85a..71affcf9001d 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentHelper.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentHelper.h @@ -2,6 +2,7 @@ #define MANTID_GEOMETRY_COMPONENTHELPERS_H_ #include "MantidGeometry/DllConfig.h" +#include "MantidGeometry/Instrument.h" namespace Mantid { namespace Kernel { @@ -61,6 +62,17 @@ MANTID_GEOMETRY_DLL void rotateComponent(const IComponent &comp, ParameterMap &pmap, const Kernel::Quat &rot, const TransformType positionType); + +MANTID_GEOMETRY_DLL Geometry::Instrument_sptr createMinimalInstrument(const Mantid::Kernel::V3D& sourcePos, + const Mantid::Kernel::V3D& samplePos, + const Mantid::Kernel::V3D& detectorPos ); + +MANTID_GEOMETRY_DLL Object_sptr createSphere(double radius, const Kernel::V3D ¢re, + const std::string &id); + +MANTID_GEOMETRY_DLL std::string sphereXML(double radius, const Kernel::V3D ¢re, const std::string &id) ; + + } } // namespace Geometry } // namespace Mantid diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/ComponentHelper.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/ComponentHelper.cpp index 0b197b81ffc9..66431f6c817a 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/ComponentHelper.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/ComponentHelper.cpp @@ -4,8 +4,12 @@ #include "MantidGeometry/Instrument/ComponentHelper.h" #include "MantidGeometry/Instrument/ParameterMap.h" #include "MantidGeometry/IComponent.h" +#include "MantidGeometry/Instrument/ReferenceFrame.h" +#include "MantidGeometry/Objects/ShapeFactory.h" +#include "MantidGeometry/Instrument/Detector.h" #include +#include namespace Mantid { namespace Geometry { @@ -92,6 +96,71 @@ void rotateComponent(const IComponent &comp, ParameterMap &pmap, pmap.addQuat(comp.getComponentID(), "rot", newRot); } + +/** + * createOneDetectorInstrument, creates the most simple possible definition of an instrument in which we can extract a valid L1 and L2 distance for unit calculations. + * + * Beam direction is along X, + * Up direction is Y + * + * @param sourcePos : V3D position + * @param samplePos : V3D sample position + * @param detectorPos : V3D detector position + * @return Instrument generated. + */ +Geometry::Instrument_sptr createMinimalInstrument(const Mantid::Kernel::V3D& sourcePos, const Mantid::Kernel::V3D& samplePos, const Mantid::Kernel::V3D& detectorPos ) +{ + Instrument_sptr instrument = boost::make_shared(); + instrument->setReferenceFrame( + boost::make_shared(Mantid::Geometry::Y /*up*/, Mantid::Geometry::X /*along*/, Left, "0,0,0")); + + // A source + ObjComponent *source = new ObjComponent("source"); + source->setPos(sourcePos); + source->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1")); + instrument->add(source); + instrument->markAsSource(source); + + // A sample + ObjComponent *sample = new ObjComponent("some-surface-holder"); + sample->setPos(samplePos); + sample->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1")); + instrument->add(sample); + instrument->markAsSamplePos(sample); + + // A detector + Detector *det = new Detector("point-detector", 1 /*detector id*/, NULL); + det->setPos(detectorPos); + det->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1")); + instrument->add(det); + instrument->markAsDetector(det); + + return instrument; +} + + +/** + * Create a sphere object + */ +Object_sptr createSphere(double radius, const V3D ¢re, + const std::string &id) { + ShapeFactory shapeMaker; + return shapeMaker.createShape(sphereXML(radius, centre, id)); +} + +/** + * Return the XML for a sphere. + */ +std::string sphereXML(double radius, const Kernel::V3D ¢re, const std::string &id) { + std::ostringstream xml; + xml << "" + << "" + << "" + << ""; + return xml.str(); +} + } // namespace ComponentHelper } } // namespace Mantid::Geometry diff --git a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt index 73fc2144b86b..4ef36d277d83 100644 --- a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt @@ -19,6 +19,7 @@ set ( SRC_FILES src/ConvToMDHistoWS.cpp src/ConvToMDSelector.cpp src/ConvertCWPDMDToSpectra.cpp + src/ConvertCWSDExpToMomentum.cpp src/ConvertMDHistoToMatrixWorkspace.cpp src/ConvertSpiceDataToRealSpace.cpp src/ConvertToDetectorFaceMD.cpp @@ -136,6 +137,7 @@ set ( INC_FILES inc/MantidMDAlgorithms/CompareMDWorkspaces.h inc/MantidMDAlgorithms/ConvToMDBase.h inc/MantidMDAlgorithms/ConvertCWPDMDToSpectra.h + inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h inc/MantidMDAlgorithms/ConvertMDHistoToMatrixWorkspace.h inc/MantidMDAlgorithms/ConvertSpiceDataToRealSpace.h inc/MantidMDAlgorithms/ConvertToDetectorFaceMD.h @@ -252,6 +254,7 @@ set ( TEST_FILES CloneMDWorkspaceTest.h CompareMDWorkspacesTest.h ConvertCWPDMDToSpectraTest.h + ConvertCWSDExpToMomentumTest.h ConvertEventsToMDTest.h ConvertMDHistoToMatrixWorkspaceTest.h ConvertSpiceDataToRealSpaceTest.h @@ -321,8 +324,8 @@ set ( TEST_FILES ReflectometryTransformQxQzTest.h ResolutionConvolvedCrossSectionTest.h SaveIsawQvectorTest.h - SaveMDTest.h SaveMD2Test.h + SaveMDTest.h SaveZODSTest.h SetMDUsingMaskTest.h SimulateResolutionConvolvedModelTest.h diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h new file mode 100644 index 000000000000..34430c5e0e4f --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h @@ -0,0 +1,41 @@ +#ifndef MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUM_H_ +#define MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUM_H_ + +#include "MantidKernel/System.h" + +namespace Mantid { +namespace MDAlgorithms { + +/** ConvertCWSDExpToMomentum : TODO: DESCRIPTION + + Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge + National Laboratory & European Spallation Source + + 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 ConvertCWSDExpToMomentum { +public: + ConvertCWSDExpToMomentum(); + virtual ~ConvertCWSDExpToMomentum(); +}; + +} // namespace MDAlgorithms +} // namespace Mantid + +#endif /* MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUM_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp new file mode 100644 index 000000000000..28ee2f65d5e0 --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp @@ -0,0 +1,17 @@ +#include "MantidMDAlgorithms/ConvertCWSDExpToMomentum.h" + +namespace Mantid { +namespace MDAlgorithms { + +//---------------------------------------------------------------------------------------------- +/** Constructor + */ +ConvertCWSDExpToMomentum::ConvertCWSDExpToMomentum() {} + +//---------------------------------------------------------------------------------------------- +/** Destructor + */ +ConvertCWSDExpToMomentum::~ConvertCWSDExpToMomentum() {} + +} // namespace MDAlgorithms +} // namespace Mantid \ No newline at end of file diff --git a/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h b/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h new file mode 100644 index 000000000000..0162d19e43f1 --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h @@ -0,0 +1,28 @@ +#ifndef MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUMTEST_H_ +#define MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUMTEST_H_ + +#include + +#include "MantidMDAlgorithms/ConvertCWSDExpToMomentum.h" + +using Mantid::MDAlgorithms::ConvertCWSDExpToMomentum; +using namespace Mantid::API; + +class ConvertCWSDExpToMomentumTest : public CxxTest::TestSuite { +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static ConvertCWSDExpToMomentumTest *createSuite() { return new ConvertCWSDExpToMomentumTest(); } + static void destroySuite( ConvertCWSDExpToMomentumTest *suite ) { delete suite; } + + + void test_Something() + { + TSM_ASSERT( "You forgot to write a test!", 0); + } + + +}; + + +#endif /* MANTID_MDALGORITHMS_CONVERTCWSDEXPTOMOMENTUMTEST_H_ */ \ No newline at end of file diff --git a/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst b/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst new file mode 100644 index 000000000000..594779c4f6a3 --- /dev/null +++ b/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst @@ -0,0 +1,257 @@ +.. algorithm:: + +.. summary:: + +.. alias:: + +.. properties:: + +Description +----------- + +This algorithms is to convert an experiment done on reactor-based four-circle instrument +(such as HFIR HB3A) to a MDEventWorkspace with each MDEvent in momentum space. + + +In this algorithm's name, ConvertCWSDToMomentum, *CW* stands for constant wave +(reactor-source instrument); *SD* stands for single crystal diffraction. + +This algorithm takes ??? as inputs. + +Futhermore, the unit of the output matrix workspace can be converted to +momentum transfer (:math:`Q`). + + +Outline of algorithm +#################### + +1. Create output workspace. + * Build a virtual instrument, requiring + - position of source + - position of sample + - detector ID, position, detector size of pixels +2. Read in data via table workspace + * From each row, (1) file name and (2) starting detector ID are read in. + * Detector position in (virtual) instrument of MDEventWorkspace is compared with the position in MatrixWorkspace + * Momentum is calcualted by goniometry values + + +Input Workspaces +################ + +??? input MDEventWorkspaces are required. + +{\it InputWorkspace} is .... + + +These two MDEventWorkspace should have the same number of runs and same number of MDEvent. + + +Outputs +####### + +The output is an MDEventWorkspace ... + + +MDEvent ++++++++ + +Each MDEvent in output MDEventWorkspace contain +* *Kx* +* *Ky* +* *Kz* +* Signal +* Error +* Detector ID +* Run Number + + + +Combine Experiment Into One MDEventWorkspace +-------------------------------------------- + +One typical HB3A (reactor-based four-circle diffractometer) experiment consists of +a set of scans, each of which contains multiple experiment point (labeled as *Pt.* in SPICE). + +Each experiment point is independent to the others. +They can have various detector positions, goniometer setup and even sample environment setup. + +In order to integrate them into an organized data structure, i.e., *MDEventWorkspace*, +a virtual instrument is built in the algorithm. + +Virtual instrument +================== + +A virtual instrument is built in the algorithm. +In this virtual instrument, the number of detectors and their position are determined +by the number of individual detector's positions in the *experiment*. + + +MDEventWorkspace +================ + +There is only one *virtual* instrument and *N* ExperimentInfo. +*N* is the total number of experiment points in the *experiment*. + + +Sample Logs +########### + + + +Target Units +############ + +Three units are supported by this algorithm via property *UnitOutput*. +They are :math:`2\theta`, dSpacing and MomentumTransfer(Q). + +The following equations are used to convert the units. + +.. math:: \lambda = 2d\sin(\theta) + +.. math:: d = \frac{4\pi}{Q} + +Therefore neutron wavelength :math:`\lambda` must be given either in sample log or via input property +if the unit of the output workspace is targeted to be dSpacing or MomentumTransfer. + + +Binning, Normalization and Error +################################ + +According to the input binning parameters, the bins in :math:`2\theta` are created as +:math:`2\theta_{min}, 2\theta_{min}+\Delta, 2\theta_{min}+2\Delta, \cdots`. + +If the unit of ouput workspace is specified as dSpacing or MomentrumTransfer, +then the bins should be created as :math:`d_{min}, d_{min}+\Delta, d_{min}+2\Delta, \cdots, d_{max}` +or :math:`q_{min}, q_{min}+\Delta, \cdots, q_{max}` respectively. + +For each detector, if its position falls between :math:`2\theta_i` and :math:`2\theta_{i+1}`,, +:math:`d_i` and :math:`d_{i+1}`, or :math:`Q_i` and :math:`Q_{i+1}`, +then its counts is added to :math:`Y_i` and the corresponding monitor counts is added to +:math:`M_i`. + +The singals on these bins are normalized by its monitor counts, such that + +.. math:: y_i = \frac{Y_i}{M_i} + + +The error (i.e., standard deviation) is defined as + +.. math:: \frac{\Delta y_i}{y_i} = \sqrt{(\frac{\Delta Y_i}{Y_i})^2 + (\frac{\Delta M_i}{M_i})^2} + +Scaling +####### + +The normalized histogram can be scaled up by a factor specified by *ScaleFactor*. +In most cases, the scaling factor is equal to average monitor counts of all measurements. + +If the scaling factor is specified, then +the standard error of data point :math:`i` will be converted to + +.. math:: \sigma^{(s)}_i = f \times \sigma^{(n)}_i + +where :math:`f` is the scaling factor, :math:`\sigma^{(n)}_i` is the standard error of the normalized signal +of data point :math:`i`, and +:math:`\sigma^{(s)}_i` is the standard error of the signal scaled up. + +Linear Interpolation +#################### + +If a user specifies a bin size that is smaller than the resolution of the instrument, +then it is very likely to occur that some bins have zero count, while their neighboring +bins have counts that are significantly larger than noise. +In this case, an option to do linear interpolation to the zero count bins +in the histogram is provided. +Property *LinearInterpolateZeroCounts* is used to set the flag to do linear interpolation. + +The linear interpolation will be only applied to those zero-count bins within +the measuring range. + +Excluding detectors +################### + +Detectors can be excluded from conversion process. +They can be specified by their *Detector ID*s via property *ExcludedDetectorIDs*. +If a detector is specified as being excluded, +all of its counts of all runs (pts) will be taken out of binning process. + + +Workflow +-------- + +This algorithm is the third step to reduce powder diffraction data from a SPICE file. +Following algorithm *LoadSpiceAscii*, which loads SPICE file to a TableWorkspace +and {\it ConvertSpiceToRealSpace}, which converts the TableWorkspace to MDEvnetWorkspace +that is able to reflect all the information of the epxeriment, +{\it ConvertCWPDMDToSpectra} goes through all the detectors' counts and rebins the data. + +An Example +########## + +1. LoadSpiceAscii +2. ConvertSpiceToRealSpace +3. Merge a few data MDWorkspaces together; merge the corresponding monitor MDWorkspaces together; +4. ConvertCWPDMDToSpectra. + +Experimental data with different neutron wavelengths can be binned together to d-spacing or momentum transfer space. + + +Usage +----- + +**Example - reduce a SPICE file for HB2A to Fullprof file:** + +.. testcode:: ExReduceHB2AToFullprof + + # create table workspace and parent log workspace + LoadSpiceAscii(Filename='HB2A_exp0231_scan0001.dat', + IntegerSampleLogNames="Sum of Counts, scan, mode, experiment_number", + FloatSampleLogNames="samplemosaic, preset_value, Full Width Half-Maximum, Center of Mass", + DateAndTimeLog='date,MM/DD/YYYY,time,HH:MM:SS AM', + OutputWorkspace='Exp0231DataTable', + RunInfoWorkspace='Exp0231ParentWS') + + # load for HB2A + ConvertSpiceDataToRealSpace(InputWorkspace='Exp0231DataTable', + RunInfoWorkspace='Exp0231ParentWS', + OutputWorkspace='Exp0231DataMD', + OutputMonitorWorkspace='Exp0231MonitorMD') + + # Convert from real-space MD to Fullprof data + ConvertCWPDMDToSpectra( + InputWorkspace = 'Exp0231DataMD', + InputMonitorWorkspace = 'Exp0231MonitorMD', + OutputWorkspace = 'Exp0231Reduced', + BinningParams = '5, 0.1, 150', + UnitOutput = '2theta', + ScaleFactor = 100., + LinearInterpolateZeroCounts = True + ) + + # output + ws = mtd["Exp0231Reduced"] + + vecx = ws.readX(0) + vecy = ws.readY(0) + vece = ws.readE(0) + + for i in [100, 100, 1101, 1228]: + print "2theta = %-5f, Y = %-5f, E = %-5f" % (vecx[i], vecy[i], vece[i]) + +.. testcleanup:: ExReduceHB2AToFullprof + + DeleteWorkspace('Exp0231DataTable') + DeleteWorkspace('Exp0231ParentWS') + DeleteWorkspace('Exp0231DataMD') + DeleteWorkspace('Exp0231MonitorMD') + +Output: + +.. testoutput:: ExReduceHB2AToFullprof + + 2theta = 15.000000, Y = 0.386563, E = 0.024744 + 2theta = 15.000000, Y = 0.386563, E = 0.024744 + 2theta = 115.100000, Y = 1.846279, E = 0.054287 + 2theta = 127.800000, Y = 0.237738, E = 0.027303 + +.. categories::