diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 627e4776cdd718943ce8edf0db032f34c55d6008..924cac8aa7766ee6f036a01ef6705695b2adb0c5 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -137,6 +137,7 @@ set ( SRC_FILES src/RemovePromptPulse.cpp src/RenameWorkspace.cpp src/ReplaceSpecialValues.cpp + src/ResizeRectangularDetector.cpp src/SANSDirectBeamScaling.cpp src/Scale.cpp src/ScaleX.cpp @@ -308,6 +309,7 @@ set ( INC_FILES inc/MantidAlgorithms/RemovePromptPulse.h inc/MantidAlgorithms/RenameWorkspace.h inc/MantidAlgorithms/ReplaceSpecialValues.h + inc/MantidAlgorithms/ResizeRectangularDetector.h inc/MantidAlgorithms/SANSDirectBeamScaling.h inc/MantidAlgorithms/Scale.h inc/MantidAlgorithms/ScaleX.h @@ -464,6 +466,7 @@ set ( TEST_FILES test/RemovePromptPulseTest.h test/RenameWorkspaceTest.h test/ReplaceSpecialValuesTest.h + test/ResizeRectangularDetectorTest.h test/ScaleTest.h test/ScaleXTest.h test/ShiftLogTimeTest.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ResizeRectangularDetector.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ResizeRectangularDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..ba98ba02f39e4a867ad16bd87c9b25d06f9fb549 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/ResizeRectangularDetector.h @@ -0,0 +1,58 @@ +#ifndef MANTID_ALGORITHMS_RESIZERECTANGULARDETECTOR_H_ +#define MANTID_ALGORITHMS_RESIZERECTANGULARDETECTOR_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ +namespace Algorithms +{ + + /** ResizeRectangularDetector : TODO: DESCRIPTION + + @date 2011-11-22 + + Copyright © 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class DLLExport ResizeRectangularDetector : public API::Algorithm + { + public: + ResizeRectangularDetector(); + virtual ~ResizeRectangularDetector(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + + private: + virtual void initDocs(); + void init(); + void exec(); + + + }; + + +} // namespace Algorithms +} // namespace Mantid + +#endif /* MANTID_ALGORITHMS_RESIZERECTANGULARDETECTOR_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/Algorithms/src/ResizeRectangularDetector.cpp b/Code/Mantid/Framework/Algorithms/src/ResizeRectangularDetector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb61489dccdfc900e8f6a958253f6280f67fbf33 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/ResizeRectangularDetector.cpp @@ -0,0 +1,124 @@ +/*WIKI* + +This algorithm will resize a [[RectangularDetector]] by applying X and Y scaling factors. +Each pixel's position will be modifed relative to the 0,0 point of the detector by these factors. +Typically, a RectangularDetector is constructed around its center, so this would scale the detector around its center. + +This only works on [[RectangularDetector]]s. Banks formed by e.g. tubes cannot be scaled in this way. + +Internally, this sets the "scalex" and "scaley" parameters on the [[RectangularDetector]]. +Note that the scaling is relative to the original size, and is not cumulative: that is, +if you Resize * 2 and again * 3, your final detector is 3 times larger than the original, not 6 times. + +Note: As of this writing, the algorithm does NOT modify the shape of individual pixels. This means +that algorithms based on solid angle calculations might be off. +Ray-tracing (e.g. peak finding) are unaffected. + +See also [[MoveInstrumentComponent]] and [[RotateInstrumentComponent]] for other ways to move components. + +*WIKI*/ + +#include "MantidAlgorithms/ResizeRectangularDetector.h" +#include "MantidKernel/System.h" +#include "MantidAPI/WorkspaceProperty.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidGeometry/Instrument.h" +#include "MantidGeometry/IComponent.h" +#include "MantidGeometry/Instrument/RectangularDetector.h" + +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace Mantid::Geometry; + +namespace Mantid +{ +namespace Algorithms +{ + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(ResizeRectangularDetector) + + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + ResizeRectangularDetector::ResizeRectangularDetector() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + ResizeRectangularDetector::~ResizeRectangularDetector() + { + } + + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string ResizeRectangularDetector::name() const { return "ResizeRectangularDetector";}; + + /// Algorithm's version for identification. @see Algorithm::version + int ResizeRectangularDetector::version() const { return 1;}; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string ResizeRectangularDetector::category() const { return "DataHandling\\Instrument";} + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void ResizeRectangularDetector::initDocs() + { + this->setWikiSummary("Resize a RectangularDetector in X and/or Y."); + this->setOptionalMessage("Resize a RectangularDetector in X and/or Y."); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void ResizeRectangularDetector::init() + { + // When used as a sub-algorithm the workspace name is not used - hence the "Anonymous" to satisfy the validator + declareProperty(new WorkspaceProperty<MatrixWorkspace>("Workspace","Anonymous",Direction::InOut)); + declareProperty("ComponentName","", + "The name of the RectangularDetector to resize."); + declareProperty("ScaleX", 1.0, + "The scaling factor in the X direction. Default 1.0"); + declareProperty("ScaleY", 1.0, + "The scaling factor in the Y direction. Default 1.0"); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void ResizeRectangularDetector::exec() + { + MatrixWorkspace_sptr WS = getProperty("Workspace"); + std::string ComponentName = getPropertyValue("ComponentName"); + double ScaleX = getProperty("ScaleX"); + double ScaleY = getProperty("ScaleY"); + + if (ComponentName.empty()) + throw std::runtime_error("You must specify a ComponentName."); + + Instrument_const_sptr inst = WS->getInstrument(); + IComponent_const_sptr comp; + + comp = inst->getComponentByName(ComponentName); + if (!comp) + throw std::runtime_error("Component with name " + ComponentName + " was not found."); + + RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(comp); + if (!det) + throw std::runtime_error("Component with name " + ComponentName + " is not a RectangularDetector."); + + Geometry::ParameterMap& pmap = WS->instrumentParameters(); + // Add a parameter for the new scale factors + pmap.addDouble(det.get(), "scalex", ScaleX); + pmap.addDouble(det.get(), "scaley", ScaleY); + } + + + +} // namespace Mantid +} // namespace Algorithms diff --git a/Code/Mantid/Framework/Algorithms/test/ResizeRectangularDetectorTest.h b/Code/Mantid/Framework/Algorithms/test/ResizeRectangularDetectorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..442657f6219d1b126aa64a5c37c119e7ee43050c --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/test/ResizeRectangularDetectorTest.h @@ -0,0 +1,72 @@ +#ifndef MANTID_ALGORITHMS_RESIZERECTANGULARDETECTORTEST_H_ +#define MANTID_ALGORITHMS_RESIZERECTANGULARDETECTORTEST_H_ + +#include "MantidAlgorithms/ResizeRectangularDetector.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidDataObjects/EventWorkspace.h" +#include "MantidGeometry/Instrument.h" +#include "MantidGeometry/Instrument/RectangularDetector.h" +#include "MantidKernel/System.h" +#include "MantidKernel/Timer.h" +#include "MantidKernel/V3D.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include <cxxtest/TestSuite.h> +#include <iomanip> +#include <iostream> + +using namespace Mantid; +using namespace Mantid::Kernel; +using namespace Mantid::Geometry; +using namespace Mantid::Algorithms; +using namespace Mantid::API; + +class ResizeRectangularDetectorTest : public CxxTest::TestSuite +{ +public: + void test_Init() + { + ResizeRectangularDetector alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_exec() + { + Mantid::DataObjects::EventWorkspace_sptr ews = WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(2, 10); + + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(ews); + + ResizeRectangularDetector alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace", ws) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("ComponentName", "bank1") ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("ScaleX", 2.0) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("ScaleY", 0.5) ); + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + Instrument_const_sptr inst = ws->getInstrument(); + boost::shared_ptr<const RectangularDetector> det = boost::dynamic_pointer_cast<const RectangularDetector>(inst->getComponentByName("bank1")); + + // Bank 1 got scaled + V3D pos; + pos = det->getAtXY(1,1)->getPos(); + TS_ASSERT( ws->instrumentParameters().contains(det.get(), "scalex") ); + TS_ASSERT( ws->instrumentParameters().contains(det.get(), "scaley") ); + TS_ASSERT_EQUALS( pos,V3D(0.008*2, 0.008*0.5, 5.0) ); + TS_ASSERT_DELTA( det->xstep(), 0.008 * 2, 1e-6); + + // Bank 2 did not get scaled + det = boost::dynamic_pointer_cast<const RectangularDetector>(inst->getComponentByName("bank2")); + pos = det->getAtXY(1,1)->getPos(); + TS_ASSERT_EQUALS( pos,V3D(0.008*1.0, 0.008*1.0, 10.0) ); + TS_ASSERT_DELTA( det->xstep(), 0.008 * 1, 1e-6); + + } + + +}; + + +#endif /* MANTID_ALGORITHMS_RESIZERECTANGULARDETECTORTEST_H_ */ diff --git a/Code/Mantid/Framework/DataHandling/src/MoveInstrumentComponent.cpp b/Code/Mantid/Framework/DataHandling/src/MoveInstrumentComponent.cpp index 6d08859ff89f334c6d5cb77ed0715cd919fdb47a..4f2b69dc37810f5be2626939f659ee8ee9292b62 100644 --- a/Code/Mantid/Framework/DataHandling/src/MoveInstrumentComponent.cpp +++ b/Code/Mantid/Framework/DataHandling/src/MoveInstrumentComponent.cpp @@ -1,5 +1,8 @@ /*WIKI* +This moves an instrument component, e.g. a bank or a pixel. +You can either specify an absolute position or a relative position. +The relative position will be applied to the current position, so applying this twice will move the detector twice. *WIKI*/ //---------------------------------------------------------------------- @@ -20,7 +23,7 @@ DECLARE_ALGORITHM(MoveInstrumentComponent) /// Sets documentation strings for this algorithm void MoveInstrumentComponent::initDocs() { - this->setWikiSummary(" Moves an instrument component to a new position. "); + this->setWikiSummary("Moves an instrument component to a new position."); this->setOptionalMessage("Moves an instrument component to a new position."); } @@ -37,13 +40,20 @@ MoveInstrumentComponent::MoveInstrumentComponent() void MoveInstrumentComponent::init() { // When used as a sub-algorithm the workspace name is not used - hence the "Anonymous" to satisfy the validator - declareProperty(new WorkspaceProperty<MatrixWorkspace>("Workspace","Anonymous",Direction::InOut)); - declareProperty("ComponentName",""); - declareProperty("DetectorID",-1); - declareProperty("X",0.0); - declareProperty("Y",0.0); - declareProperty("Z",0.0); - declareProperty("RelativePosition",true); + declareProperty(new WorkspaceProperty<MatrixWorkspace>("Workspace","Anonymous",Direction::InOut), + "The name of the workspace for which the new instrument configuration will have an effect. Any other workspaces stored in the analysis data service will be unaffected."); + declareProperty("ComponentName","", + "The name of the component to move. Component names are defined in the instrument definition files."); + declareProperty("DetectorID",-1, + "The ID of the detector to move. If both the component name and the detector ID are set the latter will be used."); + declareProperty("X",0.0, + "The x-part of the new location vector."); + declareProperty("Y",0.0, + "The y-part of the new location vector."); + declareProperty("Z",0.0, + "The z-part of the new location vector."); + declareProperty("RelativePosition",true, + "The property defining how the (X,Y,Z) vector should be interpreted. If true it is a vector relative to the initial component's position. Otherwise it is a new position in the absolute co-ordinates."); } /** Executes the algorithm. diff --git a/Code/Mantid/Framework/Geometry/CMakeLists.txt b/Code/Mantid/Framework/Geometry/CMakeLists.txt index 95c2d75bf2fbc2f81173871c539acaeff61fd184..37ceeda301b765687062140b88073efaaa2185bd 100644 --- a/Code/Mantid/Framework/Geometry/CMakeLists.txt +++ b/Code/Mantid/Framework/Geometry/CMakeLists.txt @@ -21,6 +21,7 @@ set ( SRC_FILES src/Instrument/Parameter.cpp src/Instrument/ParameterMap.cpp src/Instrument/RectangularDetector.cpp + src/Instrument/RectangularDetectorPixel.cpp src/Instrument/XMLlogfile.cpp src/MDGeometry/IMDDimension.cpp src/MDGeometry/IMDDimensionFactory.cpp @@ -112,6 +113,7 @@ set ( INC_FILES inc/MantidGeometry/Instrument/ParameterFactory.h inc/MantidGeometry/Instrument/ParameterMap.h inc/MantidGeometry/Instrument/RectangularDetector.h + inc/MantidGeometry/Instrument/RectangularDetectorPixel.h inc/MantidGeometry/Instrument/XMLlogfile.h inc/MantidGeometry/MDGeometry/IMDDimension.h inc/MantidGeometry/MDGeometry/IMDDimensionFactory.h @@ -203,17 +205,18 @@ set ( TEST_FILES test/ObjectTest.h test/OneToOneSpectraDetectorMapTest.h test/OrientedLatticeTest.h - test/ParameterMapTest.h test/ParCompAssemblyTest.h test/ParComponentFactoryTest.h test/ParDetectorTest.h test/ParInstrumentTest.h test/ParObjCompAssemblyTest.h test/ParObjComponentTest.h + test/ParameterMapTest.h test/ParametrizedComponentTest.h test/PlaneTest.h test/PolygonEdgeTest.h test/QuadrilateralTest.h + test/RectangularDetectorPixelTest.h test/RectangularDetectorTest.h test/ReflectionConditionTest.h test/RotCounterTest.h diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/IComponent.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/IComponent.h index 4cc9faaa3c00b8b700e6f5302b79c2846f3ee4a3..76260757603549d68ed5b3ffa8b4f94f06cd1e57 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/IComponent.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/IComponent.h @@ -106,7 +106,7 @@ namespace Mantid //! Rotate the IComponent by an angle in degrees with respect to an axis. virtual void rotate(double,const Kernel::V3D&) = 0; //! Get the position relative to the parent IComponent (absolute if no parent) - virtual const Kernel::V3D & getRelativePos() const = 0; + virtual const Kernel::V3D getRelativePos() const = 0; //! Get the position of the IComponent. Tree structure is traverse through the parent chain virtual Kernel::V3D getPos() const = 0; //! Get the relative Orientation diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Component.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Component.h index b3814f1ca2b34b3bd3049292b71e2beb75eaee94..a92a8d4102b01493d9de97ea3f58a76bfb5d26fd 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Component.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Component.h @@ -122,7 +122,7 @@ namespace Mantid void rotate(double,const Kernel::V3D&); //! Get the position relative to the parent IComponent (absolute if no parent) - const Kernel::V3D & getRelativePos() const; + virtual const Kernel::V3D getRelativePos() const; //! Get the position of the IComponent. Tree structure is traverse through the parent chain virtual Kernel::V3D getPos() const; diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Detector.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Detector.h index 4c1a965ba177b999d7bcedaec8cd77444965ab26..62160471c83f8a4fcfe2728216cb72ee2325f67f 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Detector.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/Detector.h @@ -7,6 +7,7 @@ #include "MantidGeometry/IDetector.h" #include "MantidGeometry/Instrument/ObjComponent.h" #include <string> +#include "MantidKernel/V3D.h" namespace Mantid { @@ -69,6 +70,10 @@ public: /** returns the detector's topology, namely, the meaning of the detector's angular measurements. It is different in cartesian and cylindrical (surrounding the beam) coordinate system */ det_topology getTopology(Kernel::V3D ¢er)const; + + /// Return the relative position to the parent + virtual const Kernel::V3D getRelativePos() const + { return ObjComponent::getRelativePos(); } private: /// The detector id diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/DetectorGroup.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/DetectorGroup.h index 927e08466bd669fd2c2ef6032cf41b9f1d55422d..ab5b07ae31ab740d517a4931ea8f3bfa1714961c 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/DetectorGroup.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/DetectorGroup.h @@ -159,7 +159,7 @@ namespace Mantid void translate(double, double, double){} void rotate(const Kernel::Quat&){} void rotate(double,const Kernel::V3D&){} - const Kernel::V3D& getRelativePos() const { throw std::runtime_error("Cannot call getRelativePos on a DetectorGroup"); } + const Kernel::V3D getRelativePos() const { throw std::runtime_error("Cannot call getRelativePos on a DetectorGroup"); } const Kernel::Quat& getRelativeRot() const{ throw std::runtime_error("Cannot call getRelativeRot on a DetectorGroup"); } const Kernel::Quat getRotation() const{ return Kernel::Quat(); } void printSelf(std::ostream&) const{} diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetector.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetector.h index c5da767552092292a27b00a654654e0d9ae01864..a41834956125b3736e684fbff53ec5fb961b99bd 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetector.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetector.h @@ -46,6 +46,8 @@ namespace Geometry class MANTID_GEOMETRY_DLL RectangularDetector : public CompAssembly, public IObjComponent { + friend class RectangularDetectorPixel; + public: ///String description of the type of component virtual std::string type() const { return "RectangularDetector";} diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetectorPixel.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetectorPixel.h new file mode 100644 index 0000000000000000000000000000000000000000..32a228656da88a31120973624abdd4cb298f6f46 --- /dev/null +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/RectangularDetectorPixel.h @@ -0,0 +1,79 @@ +#ifndef MANTID_GEOMETRY_RECTANGULARDETECTORPIXEL_H_ +#define MANTID_GEOMETRY_RECTANGULARDETECTORPIXEL_H_ + +#include "MantidKernel/System.h" +#include "MantidGeometry/Instrument/Detector.h" +#include "MantidGeometry/IComponent.h" +#include "MantidGeometry/Instrument/ParameterMap.h" +#include "MantidKernel/V3D.h" + + +namespace Mantid +{ +namespace Geometry +{ + + // Forward declaration + class RectangularDetector; + + /** RectangularDetectorPixel: a sub-class of Detector + that is one pixel inside a RectangularDetector. + + The position of the pixel is calculated on the fly from the row/column + of the pixel and the size of the parent (which is parametrized). + + @date 2011-11-22 + + Copyright © 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class DLLExport RectangularDetectorPixel : public Detector + { + friend class RectangularDetector; + public: + ///A string representation of the component type + virtual std::string type() const {return "RectangularDetectorPixel";} + + /// Constructor for parametrized version + RectangularDetectorPixel(const RectangularDetectorPixel* base, const ParameterMap * map); + RectangularDetectorPixel(const std::string& name, int it, boost::shared_ptr<Object> shape, IComponent* parent, + RectangularDetector * panel, size_t row, size_t col); + + RectangularDetectorPixel(); + virtual ~RectangularDetectorPixel(); + + virtual const Kernel::V3D getRelativePos() const; + + + protected: + /// RectangularDetector that is the parent of this pixel. + RectangularDetector * m_panel; + /// Row of the pixel in the panel (y index) + size_t m_row; + /// Column of the pixel in the panel (x index) + size_t m_col; + + }; + + +} // namespace Geometry +} // namespace Mantid + +#endif /* MANTID_GEOMETRY_RECTANGULARDETECTORPIXEL_H_ */ diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/Component.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/Component.cpp index 54ed114bcda62db204f7e212e9c0e605e80c8390..72dc794417e4405560277cfe18fabe7d31eb036a 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/Component.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/Component.cpp @@ -300,7 +300,7 @@ namespace Geometry /** Gets the position relative to the parent * @returns A vector of the relative position */ - const V3D & Component::getRelativePos() const + const V3D Component::getRelativePos() const { if( m_isParametrized ) { @@ -342,12 +342,12 @@ namespace Geometry const IComponent * baseParent = m_base->m_parent; if ( !baseParent ) { - return getRelativePos(); + return this->getRelativePos(); } else { // Avoid instantiation of parent shared pointer if we can - V3D absPos = getRelativePos(); + V3D absPos = this->getRelativePos(); //get the parent rotation, try to get it from the cache first to avoid instantiaing the class Quat parentRot; V3D parentPos; diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/ParComponentFactory.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/ParComponentFactory.cpp index bbb1bdf0a02d42ee8192575f2b41d2aecf8b9cec..36aafdbbb46b96d05fb0505a40c9ad9bfce1e9d6 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/ParComponentFactory.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/ParComponentFactory.cpp @@ -6,6 +6,7 @@ #include "MantidGeometry/Instrument/ObjComponent.h" #include "MantidGeometry/Instrument/ParComponentFactory.h" #include "MantidGeometry/Instrument/RectangularDetector.h" +#include "MantidGeometry/Instrument/RectangularDetectorPixel.h" namespace Mantid { @@ -54,6 +55,11 @@ namespace Mantid IComponent_sptr ParComponentFactory::create(IComponent_const_sptr base, const ParameterMap * map) { + // RectangularDetectorPixel subclasses Detector so it has to be checked before. + const RectangularDetectorPixel* rdp = dynamic_cast<const RectangularDetectorPixel*>(base.get()); + if (rdp) + return boost::shared_ptr<IComponent>(new RectangularDetectorPixel(rdp,map)); + boost::shared_ptr<const IDetector> det_sptr = boost::dynamic_pointer_cast<const IDetector>(base); if( det_sptr ) { diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetector.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetector.cpp index 6a40e137f7200a3dc0d631639be5087c5064dd20..a15e1d0d0225b045f779778c1307de02a55050d0 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetector.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetector.cpp @@ -9,6 +9,7 @@ #include <algorithm> #include <ostream> #include <stdexcept> +#include "MantidGeometry/Instrument/RectangularDetectorPixel.h" namespace Mantid { @@ -155,7 +156,12 @@ int RectangularDetector::ypixels() const double RectangularDetector::xstep() const { if (m_isParametrized) - return m_rectBase->m_xstep; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scalex") ) + scaling = m_map->get(m_rectBase, "scalex")->value<double>(); + return m_rectBase->m_xstep * scaling; + } else return this->m_xstep; } @@ -166,7 +172,12 @@ double RectangularDetector::xstep() const double RectangularDetector::ystep() const { if (m_isParametrized) - return m_rectBase->m_ystep; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scaley") ) + scaling = m_map->get(m_rectBase, "scaley")->value<double>(); + return m_rectBase->m_ystep * scaling; + } else return this->m_ystep; } @@ -176,7 +187,12 @@ double RectangularDetector::ystep() const double RectangularDetector::xstart() const { if (m_isParametrized) - return m_rectBase->m_xstart; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scalex") ) + scaling = m_map->get(m_rectBase, "scalex")->value<double>(); + return m_rectBase->m_xstart * scaling; + } else return this->m_xstart; } @@ -187,7 +203,12 @@ double RectangularDetector::xstart() const double RectangularDetector::ystart() const { if (m_isParametrized) - return m_rectBase->m_ystart; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scaley") ) + scaling = m_map->get(m_rectBase, "scaley")->value<double>(); + return m_rectBase->m_ystart * scaling; + } else return this->m_ystart; } @@ -197,7 +218,12 @@ double RectangularDetector::ystart() const double RectangularDetector::xsize() const { if (m_isParametrized) - return m_rectBase->m_xsize; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scalex") ) + scaling = m_map->get(m_rectBase, "scalex")->value<double>(); + return m_rectBase->m_xsize * scaling; + } else return this->m_xsize; } @@ -208,7 +234,12 @@ double RectangularDetector::xsize() const double RectangularDetector::ysize() const { if (m_isParametrized) - return m_rectBase->m_ysize; + { + double scaling = 1.0; + if( m_map->contains(m_rectBase, "scaley") ) + scaling = m_map->get(m_rectBase, "scaley")->value<double>(); + return m_rectBase->m_ysize * scaling; + } else return this->m_ysize; } @@ -264,7 +295,15 @@ int RectangularDetector::idstep() const V3D RectangularDetector::getRelativePosAtXY(int x, int y) const { if (m_isParametrized) - return m_rectBase->getRelativePosAtXY(x,y); + { + double scalex = 1.0; + if( m_map->contains(m_rectBase, "scalex") ) + scalex = m_map->get(m_rectBase, "scalex")->value<double>(); + double scaley = 1.0; + if( m_map->contains(m_rectBase, "scaley") ) + scaley = m_map->get(m_rectBase, "scaley")->value<double>(); + return m_rectBase->getRelativePosAtXY(x,y) * V3D(scalex, scaley, 1.0); + } else return V3D( m_xstart + m_xstep * x, m_ystart + m_ystep * y, 0); } @@ -361,13 +400,14 @@ void RectangularDetector::initialize(boost::shared_ptr<Object> shape, maxDetId=id; } //Create the detector from the given id & shape and with xColumn as the parent. - Detector* detector = new Detector(oss.str(), id, shape, xColumn); + RectangularDetectorPixel* detector = new RectangularDetectorPixel(oss.str(), id, shape, xColumn, + this, size_t(iy), size_t(ix)); //Calculate the x,y position double x = xstart + ix * xstep; double y = ystart + iy * ystep; V3D pos(x,y,0); - //Translate (relative to parent) + //Translate (relative to parent). This gives the un-parametrized position. detector->translate(pos); //Add it to the x-colum diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetectorPixel.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetectorPixel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0bf8625a76015ff998f7b9e2a541bf18fd27861 --- /dev/null +++ b/Code/Mantid/Framework/Geometry/src/Instrument/RectangularDetectorPixel.cpp @@ -0,0 +1,80 @@ +#include "MantidGeometry/Instrument/RectangularDetectorPixel.h" +#include "MantidKernel/System.h" +#include "MantidGeometry/Instrument/RectangularDetector.h" +#include "MantidKernel/V3D.h" + +using namespace Mantid::Kernel; + +namespace Mantid +{ +namespace Geometry +{ + + + + /** Constructor for a parametrized Detector + * @param base: the base (un-parametrized) IComponent + * @param map: pointer to the ParameterMap + * */ + RectangularDetectorPixel::RectangularDetectorPixel(const RectangularDetectorPixel* base, const ParameterMap * map) + : Detector(base, map), + m_panel(base->m_panel), m_row(base->m_row), m_col(base->m_col) + { + } + + /** Constructor + * + * @param name :: The name of the component + * @param id :: detector ID + * @param shape :: A pointer to the object describing the shape of this component + * @param parent :: parent IComponent (assembly, normally) + * @param panel :: parent RectangularDetector + * @param row :: row of the pixel in the panel + * @param col :: column of the pixel in the panel + */ + RectangularDetectorPixel::RectangularDetectorPixel(const std::string& name, int id, boost::shared_ptr<Object> shape, IComponent* parent, + RectangularDetector * panel, size_t row, size_t col) + : Detector(name, id, shape, parent), + m_panel(panel), m_row(row), m_col(col) + { + if (!m_panel) + throw std::runtime_error("RectangularDetectorPixel::ctor(): pixel " + name + " has no valid RectangularDetector parent."); + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + RectangularDetectorPixel::~RectangularDetectorPixel() + { + } + + + //---------------------------------------------------------------------------------------------- + /** Get the position relative to the parent IComponent (absolute if no parent) + * This is calculated on-the-fly. + * + * @return position relative to the 0,0 point of the parent panel + */ + const Kernel::V3D RectangularDetectorPixel::getRelativePos() const + { + //Calculate the x,y position + double x = m_panel->xstart() + double(m_col) * m_panel->xstep(); + double y = m_panel->ystart() + double(m_row) * m_panel->ystep(); + + // The parent m_panel is always the unparametrized version, + // so the xstep() etc. returned are the UNSCALED one. + if (m_isParametrized) + { + // Apply the scaling factors + if( m_map->contains(m_panel, "scalex") ) + x *= m_map->get(m_panel, "scalex")->value<double>(); + if( m_map->contains(m_panel, "scaley") ) + y *= m_map->get(m_panel, "scaley")->value<double>(); + } + + return V3D(x,y,0); + } + + +} // namespace Mantid +} // namespace Geometry diff --git a/Code/Mantid/Framework/Geometry/test/RectangularDetectorPixelTest.h b/Code/Mantid/Framework/Geometry/test/RectangularDetectorPixelTest.h new file mode 100644 index 0000000000000000000000000000000000000000..ee90fd8bf109ec4bb94cc270fab8049362fc82bb --- /dev/null +++ b/Code/Mantid/Framework/Geometry/test/RectangularDetectorPixelTest.h @@ -0,0 +1,28 @@ +#ifndef MANTID_GEOMETRY_RECTANGULARDETECTORPIXELTEST_H_ +#define MANTID_GEOMETRY_RECTANGULARDETECTORPIXELTEST_H_ + +#include <cxxtest/TestSuite.h> +#include "MantidKernel/Timer.h" +#include "MantidKernel/System.h" +#include <iostream> +#include <iomanip> + +#include "MantidGeometry/Instrument/RectangularDetectorPixel.h" + +using namespace Mantid; +using namespace Mantid::Geometry; + +class RectangularDetectorPixelTest : public CxxTest::TestSuite +{ +public: + + /// This test properly requires a RectangularDetector. See RectangularDetectorTest. + void test_nothing() + { + } + + +}; + + +#endif /* MANTID_GEOMETRY_RECTANGULARDETECTORPIXELTEST_H_ */ diff --git a/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h b/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h index 45e068d090bc187ce3f8ae9a5d87d2a675121651..d44a1f72f36551dec8f23d1c69f6534f4e4bf130 100644 --- a/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h +++ b/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h @@ -18,9 +18,12 @@ using namespace Mantid::Geometry; using Mantid::Kernel::V3D; using Mantid::Kernel::Quat; + class RectangularDetectorTest : public CxxTest::TestSuite { public: + + void testEmptyConstructor() { RectangularDetector q; @@ -102,7 +105,7 @@ public: /** Test on a rectangular detector that will be - * repeated on an un-moved parametrized version. + * repeated on an un-moved pRectangularDetectorPixelarametrized version. */ void do_test_on(RectangularDetector *det) { @@ -171,6 +174,45 @@ public: TS_ASSERT_DELTA(box.zMax(), 3000.5, 1e-08); } + /** Create a parametrized RectangularDetector with a parameter that + * resizes it. + */ + void testResizingParameter() + { + boost::shared_ptr<Geometry::Object> cuboidShape = ComponentCreationHelper::createCuboid(0.5); + + RectangularDetector *det = new RectangularDetector("MyRectangle"); + det->setPos(1000., 2000., 3000.); + det->initialize(cuboidShape, 100, -50.0, 1.0, 200, -100.0, 1.0, 1000000, true, 1000 ); + + // --- Now make a parametrized version ---- + ParameterMap_sptr pmap( new ParameterMap() ); + RectangularDetector *parDet = new RectangularDetector(det, pmap.get()); + pmap->addDouble(det, "scalex", 12); + pmap->addDouble(det, "scaley", 23); + + // Sizes and steps are scaled by these factors + TS_ASSERT_DELTA( parDet->xstep(), 12, 1e-5); + TS_ASSERT_DELTA( parDet->ystep(), 23, 1e-5); + TS_ASSERT_DELTA( parDet->xstart(), -50*12, 1e-5); + TS_ASSERT_DELTA( parDet->ystart(), -100*23, 1e-5); + TS_ASSERT_DELTA( parDet->xsize(), 100*12, 1e-5); + TS_ASSERT_DELTA( parDet->ysize(), 200*23, 1e-5); + + V3D pos = parDet->getRelativePosAtXY(1,1); + TS_ASSERT_EQUALS(pos, V3D( (-50+1)*12., (-100+1)*23., 0.) ); + + //Check some positions + std::cout << parDet->getAtXY(0,0)->getPos() << std::endl; + std::cout << parDet->getAtXY(1,0)->getPos() << std::endl; + std::cout << parDet->getAtXY(1,1)->getPos() << std::endl; + TS_ASSERT_EQUALS(parDet->getAtXY(0,0)->getPos(), V3D( 1000-(50)*12., 2000-(100*23.), 3000.) ); + TS_ASSERT_EQUALS(parDet->getAtXY(1,0)->getPos(), V3D( 1000+(-50.+1)*12., 2000-(100*23.), 3000.) ); + TS_ASSERT_EQUALS(parDet->getAtXY(1,1)->getPos(), V3D( 1000+(-50.+1)*12., 2000+(-100.+1)*23., 3000.) ); + + delete det; + delete parDet; + } };