diff --git a/Code/Mantid/Build/CMake/DarwinSetup.cmake b/Code/Mantid/Build/CMake/DarwinSetup.cmake index 77b73b1d40a4..0a9eac19a1b7 100644 --- a/Code/Mantid/Build/CMake/DarwinSetup.cmake +++ b/Code/Mantid/Build/CMake/DarwinSetup.cmake @@ -26,7 +26,7 @@ if ( PYTHON_VERSION_MAJOR ) message ( STATUS "Python version is " ${PY_VER} ) else () # Older versions of CMake don't set these variables so just assume 2.6 as before - set ( PY_VER 2.6 ) + set ( PY_VER 2.7 ) endif () ########################################################################### @@ -45,7 +45,8 @@ endif() ########################################################################### # Mac-specific installation setup ########################################################################### -set ( CMAKE_INSTALL_PREFIX /Applications ) +set ( CMAKE_INSTALL_PREFIX "" ) +set ( CPACK_PACKAGE_EXECUTABLES MantidPlot ) set ( INBUNDLE MantidPlot.app/ ) # We know exactly where this has to be on Darwin set ( PARAVIEW_APP_DIR "/Applications/${OSX_PARAVIEW_APP}" ) @@ -73,6 +74,12 @@ install ( FILES /Library/Python/${PY_VER}/site-packages/PyQt4/Qt.so /Library/Python/${PY_VER}/site-packages/PyQt4/QtXml.so /Library/Python/${PY_VER}/site-packages/PyQt4/__init__.py DESTINATION ${BIN_DIR}/PyQt4 ) +# Newer PyQt versions have a new internal library that we need to take +if ( EXISTS /Library/Python/${PY_VER}/site-packages/PyQt4/_qt.so ) + install ( FILES /Library/Python/${PY_VER}/site-packages/PyQt4/_qt.so + DESTINATION ${BIN_DIR}/PyQt4 ) +endif () + install ( DIRECTORY /Library/Python/${PY_VER}/site-packages/PyQt4/uic DESTINATION ${BIN_DIR}/PyQt4 ) # Python packages in Third_Party need copying to build directory and the final package @@ -101,27 +108,21 @@ execute_process( # Strip off any /CR or /LF string(STRIP ${OSX_VERSION} OSX_VERSION) -if (OSX_VERSION VERSION_LESS 10.6) - message (FATAL_ERROR "The minimum supported version of Mac OS X is 10.6 (Snow Leopard).") -endif() - -if (OSX_VERSION VERSION_GREATER 10.6 OR OSX_VERSION VERSION_EQUAL 10.6) - set ( OSX_CODENAME "Snow Leopard" ) -endif() - -if (OSX_VERSION VERSION_GREATER 10.7 OR OSX_VERSION VERSION_EQUAL 10.7) - set ( OSX_CODENAME "Lion") +if (OSX_VERSION VERSION_LESS 10.8) + message (FATAL_ERROR "The minimum supported version of Mac OS X is 10.8 (Mountain Lion).") endif() if (OSX_VERSION VERSION_GREATER 10.8 OR OSX_VERSION VERSION_EQUAL 10.8) set ( OSX_CODENAME "Mountain Lion") endif() +if (OSX_VERSION VERSION_GREATER 10.9 OR OSX_VERSION VERSION_EQUAL 10.9) + set ( OSX_CODENAME "Mavericks") +endif() + message (STATUS "Operating System: Mac OS X ${OSX_VERSION} (${OSX_CODENAME})") string (REPLACE " " "" CPACK_SYSTEM_NAME ${OSX_CODENAME}) -set ( CPACK_OSX_PACKAGE_VERSION 10.6 ) -set ( CPACK_PREFLIGHT_SCRIPT ${CMAKE_SOURCE_DIR}/Installers/MacInstaller/installer_hooks/preflight ) -set ( CPACK_GENERATOR PackageMaker ) +set ( CPACK_GENERATOR DragNDrop ) diff --git a/Code/Mantid/CMakeLists.txt b/Code/Mantid/CMakeLists.txt index 5332ca738af0..a35fde6900af 100644 --- a/Code/Mantid/CMakeLists.txt +++ b/Code/Mantid/CMakeLists.txt @@ -172,13 +172,8 @@ set ( ENABLE_CPACK CACHE BOOL "Switch to enable CPack package generation") if ( ENABLE_CPACK ) include ( CPackCommon ) - # Mac Packagemaker settings - if (OSX_VERSION VERSION_LESS 10.8) - set ( CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/Installers/MacInstaller/MacOSX-README.rtf ) - else() - set ( CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/Installers/MacInstaller/MacOSX10-8-README.rtf ) - endif () - set ( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/Installers/WinInstaller/License.rtf ) + # Mac package settings + set ( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/Installers/WinInstaller/License.txt ) IF ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) include ( CPackLinuxSetup ) diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h b/Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h index 6ed5b49afa44..34a92504ada9 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h @@ -15,6 +15,7 @@ namespace Mantid { class FunctionDomain; class IFunctionValues; + class Workspace; } namespace API @@ -89,12 +90,20 @@ namespace Mantid /// @param function :: A pointer to the fitting function /// @param domain :: The domain containing x-values for the function /// @param values :: A FunctionValues instance containing the fitting data - virtual void createOutputWorkspace( + /// @param outputWorkspacePropertyName :: Name of the property to declare and set to the created output workspace. + /// If empty do not create the property, just return a pointer + /// @return A shared pointer to the created workspace. + virtual boost::shared_ptr createOutputWorkspace( const std::string& baseName, API::IFunction_sptr function, boost::shared_ptr domain, - boost::shared_ptr values) - {UNUSED_ARG(baseName);UNUSED_ARG(function);UNUSED_ARG(domain);UNUSED_ARG(values);} + boost::shared_ptr values, + const std::string& outputWorkspacePropertyName = "OutputWorkspace" + ) + { + UNUSED_ARG(baseName);UNUSED_ARG(function);UNUSED_ARG(domain);UNUSED_ARG(values);UNUSED_ARG(outputWorkspacePropertyName); + throw std::logic_error("Method createOutputWorkspace() isn't implemented"); + } /// Initialize the function /// @param function :: A function to initialize. diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDIterator.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDIterator.h index 5ab004f60654..25422c19e5ca 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDIterator.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDIterator.h @@ -116,6 +116,9 @@ class IMDWorkspace; /// Find neighbouring indexes. virtual std::vector findNeighbourIndexes() const = 0; + /// Get the linear index. + virtual size_t getLinearIndex() const = 0; + protected: /// Normalization method for getNormalizedSignal() Mantid::API::MDNormalization m_normalization; diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/MatrixWorkspaceMDIterator.h b/Code/Mantid/Framework/API/inc/MantidAPI/MatrixWorkspaceMDIterator.h index e45be22ff5ce..8807f23593e9 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/MatrixWorkspaceMDIterator.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/MatrixWorkspaceMDIterator.h @@ -83,6 +83,8 @@ namespace API virtual std::vector findNeighbourIndexes() const; + virtual size_t getLinearIndex() const; + private: void calcWorkspacePos(size_t newWI); diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/MultiDomainFunction.h b/Code/Mantid/Framework/API/inc/MantidAPI/MultiDomainFunction.h index f7d78aaa15ef..a02d2a887308 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/MultiDomainFunction.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/MultiDomainFunction.h @@ -54,6 +54,12 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction virtual void function(const FunctionDomain& domain, FunctionValues& values)const; /// Derivatives of function with respect to active parameters virtual void functionDeriv(const FunctionDomain& domain, Jacobian& jacobian); + /// Called at the start of each iteration + virtual void iterationStarting(); + /// Called at the end of an iteration + virtual void iterationFinished(); + /// Create a list of equivalent functions + virtual std::vector createEquivalentFunctions() const; /// Associate a function and a domain void setDomainIndex(size_t funIndex, size_t domainIndex); @@ -63,6 +69,8 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction void clearDomainIndices(); /// Get the largest domain index size_t getMaxIndex() const {return m_maxIndex;} + /// Get domain indices for a member function + void getDomainIndices(size_t i, size_t nDomains, std::vector& domains)const; /// Returns the number of attributes associated with the function virtual size_t nLocalAttributes()const {return 1;} @@ -80,7 +88,6 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction /// Counts number of the domains void countNumberOfDomains(); void countValueOffsets(const CompositeDomain& domain)const; - void getFunctionDomains(size_t i, const CompositeDomain& cd, std::vector& domains)const; /// Domain index map: finction -> domain std::map > m_domains; diff --git a/Code/Mantid/Framework/API/src/CatalogManager.cpp b/Code/Mantid/Framework/API/src/CatalogManager.cpp index 4c53e1b82b84..96e6a556cc0b 100644 --- a/Code/Mantid/Framework/API/src/CatalogManager.cpp +++ b/Code/Mantid/Framework/API/src/CatalogManager.cpp @@ -55,7 +55,7 @@ namespace Mantid } // If we reached this point then the session is corrupt/invalid. - throw std::runtime_error("The session ID you have provided is invalid"); + throw std::runtime_error("The session ID you have provided is invalid."); } /** diff --git a/Code/Mantid/Framework/API/src/IFunction.cpp b/Code/Mantid/Framework/API/src/IFunction.cpp index b3757ed84363..2e660e46d1f8 100644 --- a/Code/Mantid/Framework/API/src/IFunction.cpp +++ b/Code/Mantid/Framework/API/src/IFunction.cpp @@ -1024,7 +1024,7 @@ void IFunction::convertValue(std::vector& values, Kernel::Unit_sptr& out { // Get l1, l2 and theta (see also RemoveBins.calculateDetectorPosition()) Instrument_const_sptr instrument = ws->getInstrument(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if (sample == NULL) { g_log.error() << "No sample defined instrument. Cannot convert units for function\n" diff --git a/Code/Mantid/Framework/API/src/MatrixWorkspace.cpp b/Code/Mantid/Framework/API/src/MatrixWorkspace.cpp index 601c7f9f843c..dc1268bf3a85 100644 --- a/Code/Mantid/Framework/API/src/MatrixWorkspace.cpp +++ b/Code/Mantid/Framework/API/src/MatrixWorkspace.cpp @@ -752,8 +752,8 @@ namespace Mantid { Instrument_const_sptr instrument = getInstrument(); - Geometry::IObjComponent_const_sptr source = instrument->getSource(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if ( source == NULL || sample == NULL ) { throw Kernel::Exception::InstrumentDefinitionError("Instrument not sufficiently defined: failed to get source and/or sample"); @@ -778,8 +778,8 @@ namespace Mantid */ double MatrixWorkspace::detectorTwoTheta(Geometry::IDetector_const_sptr det) const { - Geometry::IObjComponent_const_sptr source = getInstrument()->getSource(); - Geometry::IObjComponent_const_sptr sample = getInstrument()->getSample(); + Geometry::IComponent_const_sptr source = getInstrument()->getSource(); + Geometry::IComponent_const_sptr sample = getInstrument()->getSample(); if ( source == NULL || sample == NULL ) { throw Kernel::Exception::InstrumentDefinitionError("Instrument not sufficiently defined: failed to get source and/or sample"); @@ -1556,7 +1556,7 @@ namespace Mantid try { Geometry::Instrument_const_sptr inst = this->getInstrument(); - Geometry::IObjComponent_const_sptr sample = inst->getSample(); + Geometry::IComponent_const_sptr sample = inst->getSample(); if (sample) { Kernel::V3D sample_pos = sample->getPos(); diff --git a/Code/Mantid/Framework/API/src/MatrixWorkspaceMDIterator.cpp b/Code/Mantid/Framework/API/src/MatrixWorkspaceMDIterator.cpp index f3090f839d2d..4f73baa97d4f 100644 --- a/Code/Mantid/Framework/API/src/MatrixWorkspaceMDIterator.cpp +++ b/Code/Mantid/Framework/API/src/MatrixWorkspaceMDIterator.cpp @@ -311,6 +311,11 @@ namespace API throw std::runtime_error("MatrixWorkspaceMDIterator does not implement findNeighbourIndexes"); } + size_t MatrixWorkspaceMDIterator::getLinearIndex() const + { + throw std::runtime_error("MatrixWorkspaceMDIterator does not implement getLinearIndex"); + } + } // namespace Mantid } // namespace API diff --git a/Code/Mantid/Framework/API/src/MultiDomainFunction.cpp b/Code/Mantid/Framework/API/src/MultiDomainFunction.cpp index d6ab4d3c9df5..4628407a5de3 100644 --- a/Code/Mantid/Framework/API/src/MultiDomainFunction.cpp +++ b/Code/Mantid/Framework/API/src/MultiDomainFunction.cpp @@ -80,13 +80,16 @@ namespace API /** * Populates a vector with domain indices assigned to function i. + * @param i :: Index of a function to get the domain info about. + * @param nDomains :: Maximum number of domains. + * @param domains :: (Output) vector to collect domain indixes. */ - void MultiDomainFunction::getFunctionDomains(size_t i, const CompositeDomain& cd, std::vector& domains)const + void MultiDomainFunction::getDomainIndices(size_t i, size_t nDomains, std::vector& domains)const { auto it = m_domains.find(i); if (it == m_domains.end()) {// apply to all domains - domains.resize(cd.getNParts()); + domains.resize(nDomains); for(size_t i = 0; i < domains.size(); ++i) { domains[i] = i; @@ -128,7 +131,7 @@ namespace API { // find the domains member function must be applied to std::vector domains; - getFunctionDomains(iFun, cd, domains); + getDomainIndices(iFun, cd.getNParts(), domains); for(auto i = domains.begin(); i != domains.end(); ++i) { @@ -163,7 +166,7 @@ namespace API { // find the domains member function must be applied to std::vector domains; - getFunctionDomains(iFun, cd, domains); + getDomainIndices(iFun, cd.getNParts(), domains); for(auto i = domains.begin(); i != domains.end(); ++i) { @@ -174,6 +177,28 @@ namespace API } } + /** + * Called at the start of each iteration. Call iterationStarting() of the members. + */ + void MultiDomainFunction::iterationStarting() + { + for(size_t iFun = 0; iFun < nFunctions(); ++iFun) + { + getFunction(iFun)->iterationStarting(); + } + } + + /** + * Called at the end of an iteration. Call iterationFinished() of the members. + */ + void MultiDomainFunction::iterationFinished() + { + for(size_t iFun = 0; iFun < nFunctions(); ++iFun) + { + getFunction(iFun)->iterationFinished(); + } + } + /// Return a value of attribute attName IFunction::Attribute MultiDomainFunction::getLocalAttribute(size_t i, const std::string& attName)const { @@ -251,6 +276,58 @@ namespace API setDomainIndices(i,indx); } + /** + * Split this function into independent functions. The number of functions in the + * returned vector must be equal to the number + * of domains. The result of evaluation of the i-th function on the i-th domain must be + * the same as if this MultiDomainFunction was evaluated. + */ + std::vector MultiDomainFunction::createEquivalentFunctions() const + { + size_t nDomains = m_maxIndex + 1; + std::vector compositeFunctions(nDomains); + for(size_t iFun = 0; iFun < nFunctions(); ++iFun) + { + // find the domains member function must be applied to + std::vector domains; + getDomainIndices(iFun, nDomains, domains); + + for(auto i = domains.begin(); i != domains.end(); ++i) + { + size_t j = *i; + CompositeFunction_sptr cf = compositeFunctions[j]; + if ( !cf ) + { + // create a composite function for each domain + cf = CompositeFunction_sptr(new CompositeFunction()); + compositeFunctions[j] = cf; + } + // add copies of all functions applied to j-th domain to a single compositefunction + cf->addFunction( FunctionFactory::Instance().createInitialized( getFunction(iFun)->asString() )); + } + } + std::vector outFunctions(nDomains); + // fill in the output vector + // check functions containing a single member and take it out of the composite + for(size_t i = 0; i < compositeFunctions.size(); ++i) + { + auto fun = compositeFunctions[i]; + if ( !fun || fun->nFunctions() == 0 ) + { + throw std::runtime_error("There is no function for domain " + boost::lexical_cast(i)); + } + if ( fun->nFunctions() > 1 ) + { + outFunctions[i] = fun; + } + else + { + outFunctions[i] = fun->getFunction(0); + } + } + return outFunctions; + } + } // namespace API } // namespace Mantid diff --git a/Code/Mantid/Framework/API/test/AlgorithmHasPropertyTest.h b/Code/Mantid/Framework/API/test/AlgorithmHasPropertyTest.h index a3bf2cb4554e..780de495fe8f 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmHasPropertyTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmHasPropertyTest.h @@ -62,34 +62,34 @@ class AlgorithmHasPropertyTest : public CxxTest::TestSuite void test_Algorithm_With_Correct_Property_Is_Valid() { - AlgorithmHasProperty *check = new AlgorithmHasProperty("OutputWorkspace"); + AlgorithmHasProperty check("OutputWorkspace"); IAlgorithm_sptr tester(new AlgorithmWithWorkspace); tester->initialize(); tester->execute(); - TS_ASSERT_EQUALS(check->isValid(tester), ""); + TS_ASSERT_EQUALS(check.isValid(tester), ""); } void test_Algorithm_Without_Property_Is_Invalid() { - AlgorithmHasProperty *check = new AlgorithmHasProperty("OutputWorkspace"); + AlgorithmHasProperty check("OutputWorkspace"); IAlgorithm_sptr tester(new AlgorithmWithNoWorkspace); tester->initialize(); tester->execute(); - TS_ASSERT_EQUALS(check->isValid(tester), - "Algorithm object does not have the required property \"OutputWorkspace\""); + TS_ASSERT_EQUALS(check.isValid(tester), + "Algorithm object does not have the required property \"OutputWorkspace\""); } void test_Algorithm_With_Invalid_Property_Is_Invalid() { - AlgorithmHasProperty *check = new AlgorithmHasProperty("OutputValue"); + AlgorithmHasProperty check("OutputValue"); IAlgorithm_sptr tester(new AlgorithmWithInvalidProperty); tester->initialize(); - TS_ASSERT_EQUALS(check->isValid(tester), - "Algorithm object contains the required property \"OutputValue\" but " - "it has an invalid value: -1"); + TS_ASSERT_EQUALS(check.isValid(tester), + "Algorithm object contains the required property \"OutputValue\" but " + "it has an invalid value: -1"); } diff --git a/Code/Mantid/Framework/API/test/AlgorithmHistoryTest.h b/Code/Mantid/Framework/API/test/AlgorithmHistoryTest.h index d701d43e1c90..8636bca963e1 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmHistoryTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmHistoryTest.h @@ -72,7 +72,7 @@ class AlgorithmHistoryTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(compareAlg->getPropertyValue("arg2_param"), "5"); Mantid::API::AlgorithmFactory::Instance().unsubscribe("testalg1",1); - + delete testInput; } private: diff --git a/Code/Mantid/Framework/API/test/AlgorithmManagerTest.h b/Code/Mantid/Framework/API/test/AlgorithmManagerTest.h index d1a9e9bfc6bc..415545297559 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmManagerTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmManagerTest.h @@ -201,6 +201,7 @@ class AlgorithmManagerTest : public CxxTest::TestSuite resA.wait(); TSM_ASSERT_EQUALS( "Notification was received (proxy).", m_notificationValue, 12345 ); + AlgorithmManager::Instance().notificationCenter.removeObserver(my_observer); } /** Keep the right number of algorithms in the list. diff --git a/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h b/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h index e4d8d0f29977..76fe87390d0e 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h @@ -103,14 +103,14 @@ class AlgorithmPropertyTest : public CxxTest::TestSuite adder.execute(); TS_ASSERT_EQUALS(adder.getPropertyValue("Output1"), "3"); - AlgorithmProperty *testProp = new AlgorithmProperty("CalculateStep"); - TS_ASSERT_EQUALS(testProp->setValue(adder.toString()), ""); + AlgorithmProperty testProp("CalculateStep"); + TS_ASSERT_EQUALS(testProp.setValue(adder.toString()), ""); } void test_An_Invalid_String_Returns_An_Appropriate_Error() { - AlgorithmProperty *testProp = new AlgorithmProperty("CalculateStep"); - TS_ASSERT_EQUALS(testProp->setValue("ComplexSum()"), + AlgorithmProperty testProp("CalculateStep"); + TS_ASSERT_EQUALS(testProp.setValue("ComplexSum()"), "AlgorithmManager:: Unable to create algorithm ComplexSum Algorithm not registered ComplexSum"); } diff --git a/Code/Mantid/Framework/API/test/BoxControllerTest.h b/Code/Mantid/Framework/API/test/BoxControllerTest.h index aab1cbdb93f0..0a6b46390458 100644 --- a/Code/Mantid/Framework/API/test/BoxControllerTest.h +++ b/Code/Mantid/Framework/API/test/BoxControllerTest.h @@ -202,12 +202,12 @@ class BoxControllerTest : public CxxTest::TestSuite void test_CloneFileBased() { - BoxController_sptr a = boost::shared_ptr(new BoxController(2)); + auto a = boost::make_shared(2); a->setMaxDepth(4); a->setSplitInto(10); a->setMaxDepth(10); a->setMaxId(123456); - boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a)); + boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a.get())); TS_ASSERT_THROWS_NOTHING(a->setFileBacked(pS,"fakeFile")); TS_ASSERT(a->isFileBacked()); @@ -216,7 +216,7 @@ class BoxControllerTest : public CxxTest::TestSuite compareBoxControllers(*a, *b); TS_ASSERT(!b->isFileBacked()); - boost::shared_ptr pS2(new MantidTestHelpers::BoxControllerDummyIO(b)); + boost::shared_ptr pS2(new MantidTestHelpers::BoxControllerDummyIO(b.get())); TS_ASSERT_THROWS_NOTHING(b->setFileBacked(pS2,"fakeFile2")); // Check that settings are the same but BC are different @@ -229,8 +229,8 @@ class BoxControllerTest : public CxxTest::TestSuite void test_MRU_access() { - BoxController_sptr a = boost::shared_ptr(new BoxController(2)); - boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a)); + auto a = boost::make_shared(2); + boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a.get())); a->setFileBacked(pS,"existingFakeFile"); DiskBuffer * dbuf = a->getFileIO(); @@ -250,10 +250,10 @@ class BoxControllerTest : public CxxTest::TestSuite void test_openCloseFileBacked() { - BoxController_sptr a = boost::shared_ptr(new BoxController(2)); + auto a = boost::make_shared(2); TS_ASSERT(!a->isFileBacked()); - boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a)); + boost::shared_ptr pS(new MantidTestHelpers::BoxControllerDummyIO(a.get())); TS_ASSERT_THROWS_NOTHING(a->setFileBacked(pS,"fakeFile")); TSM_ASSERT("Box controller should have open faked file",pS->isOpened()); diff --git a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h index 27fd286cdd0e..61ba1e7b687d 100644 --- a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h +++ b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h @@ -315,6 +315,7 @@ class ExperimentInfoTest : public CxxTest::TestSuite ExperimentInfo * ws2 = ws.cloneExperimentInfo(); do_compare_ExperimentInfo(ws,*ws2); + delete ws2; } void test_clone_then_copy() @@ -335,6 +336,8 @@ class ExperimentInfoTest : public CxxTest::TestSuite ws3.copyExperimentInfoFrom(ws2); do_compare_ExperimentInfo(ws,ws3); + + delete ws2; } void test_default_emode_is_elastic() @@ -710,11 +713,15 @@ class ExperimentInfoTest : public CxxTest::TestSuite ExperimentInfo_sptr exptInfo(new ExperimentInfo); boost::shared_ptr inst1(new Instrument()); inst1->setName("MyTestInst"); - inst1->markAsSource(new ObjComponent("source")); + auto source = new ObjComponent("source"); + inst1->add(source); + inst1->markAsSource(source); for(size_t i = 0; i < npoints; ++i) { - inst1->markAsChopperPoint(new ObjComponent("ChopperPoint")); + auto chopperPoint = new ObjComponent("ChopperPoint"); + inst1->add(chopperPoint); + inst1->markAsChopperPoint(chopperPoint); } exptInfo->setInstrument(inst1); return exptInfo; diff --git a/Code/Mantid/Framework/API/test/FilePropertyTest.h b/Code/Mantid/Framework/API/test/FilePropertyTest.h index 2363b34f0ccc..77d7507f9f0c 100644 --- a/Code/Mantid/Framework/API/test/FilePropertyTest.h +++ b/Code/Mantid/Framework/API/test/FilePropertyTest.h @@ -167,12 +167,11 @@ class FilePropertyTest : public CxxTest::TestSuite void testThatRunNumberReturnsFileWithCorrectPrefix() { - Mantid::API::FileProperty *fp = - new Mantid::API::FileProperty("Filename","", Mantid::API::FileProperty::Load, + Mantid::API::FileProperty fp("Filename","", Mantid::API::FileProperty::Load, std::vector(1, ".raw")); - std::string error = fp->setValue("48127"); + std::string error = fp.setValue("48127"); TS_ASSERT_EQUALS(error, ""); - TS_ASSERT_DIFFERS(fp->value().find("LOQ48127"),std::string::npos); + TS_ASSERT_DIFFERS(fp.value().find("LOQ48127"),std::string::npos); // Now test one with an upper case extension auto & fileFinder = Mantid::API::FileFinder::Instance(); @@ -181,9 +180,9 @@ class FilePropertyTest : public CxxTest::TestSuite fileFinder.setCaseSensitive(false); ConfigService::Instance().setString("default.instrument","LOQ"); - error = fp->setValue("25654"); + error = fp.setValue("25654"); TS_ASSERT_EQUALS(error, ""); - TS_ASSERT(fp->value().find("LOQ25654") != std::string::npos); + TS_ASSERT(fp.value().find("LOQ25654") != std::string::npos); fileFinder.setCaseSensitive(startingCaseOption); } diff --git a/Code/Mantid/Framework/API/test/MatrixWorkspaceMDIteratorTest.h b/Code/Mantid/Framework/API/test/MatrixWorkspaceMDIteratorTest.h index 18964eea49d4..89f8fc417175 100644 --- a/Code/Mantid/Framework/API/test/MatrixWorkspaceMDIteratorTest.h +++ b/Code/Mantid/Framework/API/test/MatrixWorkspaceMDIteratorTest.h @@ -86,6 +86,7 @@ class MatrixWorkspaceMDIteratorTest : public CxxTest::TestSuite TS_ASSERT_DELTA( it->getError(), 22.0, 1e-5); TS_ASSERT_DELTA( it->getCenter()[0], 3.0, 1e-5); TS_ASSERT_DELTA( it->getCenter()[1], 2.0, 1e-5); + delete it; } @@ -94,7 +95,9 @@ class MatrixWorkspaceMDIteratorTest : public CxxTest::TestSuite { boost::shared_ptr ws = makeFakeWS(); // The number of output cannot be larger than the number of histograms - TS_ASSERT_EQUALS( ws->createIterators(10, NULL).size(), 4); + std::vector it = ws->createIterators(10, NULL); + TS_ASSERT_EQUALS( it.size(), 4); + for ( size_t i = 0; i < it.size(); ++i ) delete it[i]; // Split in 4 iterators std::vector iterators = ws->createIterators(4, NULL); @@ -117,6 +120,7 @@ class MatrixWorkspaceMDIteratorTest : public CxxTest::TestSuite TS_ASSERT( it->next() ); TS_ASSERT( it->next() ); TS_ASSERT( !it->next() ); + delete it; } } @@ -130,6 +134,7 @@ class MatrixWorkspaceMDIteratorTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(det->isMasked(), it->getIsMasked()); it->next(); } + delete it; } diff --git a/Code/Mantid/Framework/API/test/MultipleExperimentInfosTest.h b/Code/Mantid/Framework/API/test/MultipleExperimentInfosTest.h index 666660a7616e..9943284c7713 100644 --- a/Code/Mantid/Framework/API/test/MultipleExperimentInfosTest.h +++ b/Code/Mantid/Framework/API/test/MultipleExperimentInfosTest.h @@ -20,16 +20,16 @@ class MultipleExperimentInfosTest : public CxxTest::TestSuite void test_setExperimentInfos() { - MultipleExperimentInfos * mei = new MultipleExperimentInfos(); - TS_ASSERT_EQUALS( mei->getNumExperimentInfo(), 0); + MultipleExperimentInfos mei; + TS_ASSERT_EQUALS( mei.getNumExperimentInfo(), 0); ExperimentInfo_sptr ei(new ExperimentInfo); - TS_ASSERT_EQUALS( mei->addExperimentInfo(ei), 0); - TS_ASSERT_EQUALS( mei->getNumExperimentInfo(), 1); - TS_ASSERT_EQUALS( mei->getExperimentInfo(0), ei); - TS_ASSERT_THROWS_ANYTHING( mei->getExperimentInfo(1) ); + TS_ASSERT_EQUALS( mei.addExperimentInfo(ei), 0); + TS_ASSERT_EQUALS( mei.getNumExperimentInfo(), 1); + TS_ASSERT_EQUALS( mei.getExperimentInfo(0), ei); + TS_ASSERT_THROWS_ANYTHING( mei.getExperimentInfo(1) ); ExperimentInfo_sptr ei2(new ExperimentInfo); - mei->setExperimentInfo(0, ei2); - TS_ASSERT_EQUALS( mei->getExperimentInfo(0), ei2); + mei.setExperimentInfo(0, ei2); + TS_ASSERT_EQUALS( mei.getExperimentInfo(0), ei2); } void test_copy_constructor() diff --git a/Code/Mantid/Framework/API/test/PropertyNexusTest.h b/Code/Mantid/Framework/API/test/PropertyNexusTest.h index 7dd571e8204d..ce47e6651e31 100644 --- a/Code/Mantid/Framework/API/test/PropertyNexusTest.h +++ b/Code/Mantid/Framework/API/test/PropertyNexusTest.h @@ -1,6 +1,7 @@ #ifndef MANTID_API_PROPERTYNEXUSTEST_H_ #define MANTID_API_PROPERTYNEXUSTEST_H_ +#include #include "MantidAPI/PropertyNexus.h" #include "MantidKernel/System.h" #include "MantidKernel/Timer.h" @@ -75,20 +76,18 @@ class PropertyNexusTest : public CxxTest::TestSuite // ---- Now re-load and compare to the original ones ---------------------------- th.reopenFile(); - Property * prop; - prop = PropertyNexus::loadProperty(th.file, "int_val"); check_prop(prop, &pi); - prop = PropertyNexus::loadProperty(th.file, "uint_val"); check_prop(prop, &pu); - prop = PropertyNexus::loadProperty(th.file, "double_val"); check_prop(prop, &pd); - prop = PropertyNexus::loadProperty(th.file, "float_val"); check_prop(prop, &pf); - prop = PropertyNexus::loadProperty(th.file, "string_val"); check_prop(prop, &ps); - prop = PropertyNexus::loadProperty(th.file, "vector_double_val"); check_prop(prop, &pvd); - - - prop = PropertyNexus::loadProperty(th.file, "int_series"); check_prop(prop, &tspi); - prop = PropertyNexus::loadProperty(th.file, "double_series"); check_prop(prop, &tspd); - prop = PropertyNexus::loadProperty(th.file, "bool_series"); check_prop(prop, &tspb); - prop = PropertyNexus::loadProperty(th.file, "string_series"); check_prop(prop, &tsps); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "int_val")).get(), &pi ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "uint_val")).get(), &pu ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "double_val")).get(), &pd ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "float_val")).get(), &pf ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "string_val")).get(), &ps ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "vector_double_val")).get(), &pvd ); + + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "int_series")).get(), &tspi ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "double_series")).get(), &tspd ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "bool_series")).get(), &tspb ); + check_prop( boost::scoped_ptr(PropertyNexus::loadProperty(th.file, "string_series")).get(), &tsps ); } diff --git a/Code/Mantid/Framework/API/test/SampleEnvironmentTest.h b/Code/Mantid/Framework/API/test/SampleEnvironmentTest.h index af30c0f58959..c4dd8bb0ce5d 100644 --- a/Code/Mantid/Framework/API/test/SampleEnvironmentTest.h +++ b/Code/Mantid/Framework/API/test/SampleEnvironmentTest.h @@ -34,9 +34,9 @@ class SampleEnvironmentTest : public CxxTest::TestSuite void test_That_Adding_A_Component_Without_A_Shape_Throws_Invalid_Argument() { - Component *part = new Component("part"); + Component part("part"); SampleEnvironment kit("TestKit"); - TS_ASSERT_THROWS(kit.add(part), std::invalid_argument); + TS_ASSERT_THROWS(kit.add(&part), std::invalid_argument); } diff --git a/Code/Mantid/Framework/API/test/SpectraAxisTest.h b/Code/Mantid/Framework/API/test/SpectraAxisTest.h index 886ba82b47c2..4a4bb8809827 100644 --- a/Code/Mantid/Framework/API/test/SpectraAxisTest.h +++ b/Code/Mantid/Framework/API/test/SpectraAxisTest.h @@ -32,6 +32,7 @@ class SpectraAxisTest : public CxxTest::TestSuite ~SpectraAxisTest() { delete spectraAxis; + delete ws; } void testConstructor() diff --git a/Code/Mantid/Framework/API/test/WorkspaceGroupTest.h b/Code/Mantid/Framework/API/test/WorkspaceGroupTest.h index 70ccc259c6a0..374cd1c0193d 100644 --- a/Code/Mantid/Framework/API/test/WorkspaceGroupTest.h +++ b/Code/Mantid/Framework/API/test/WorkspaceGroupTest.h @@ -62,8 +62,6 @@ class WorkspaceGroupTest : public CxxTest::TestSuite MOCK_CONST_METHOD0(getMemorySize, size_t()); }; -public: - /// Make a simple group WorkspaceGroup_sptr makeGroup() { @@ -81,6 +79,8 @@ class WorkspaceGroupTest : public CxxTest::TestSuite return group; } +public: + void test_toString_Produces_Expected_String() { WorkspaceGroup_sptr group = makeGroup(); @@ -332,6 +332,7 @@ class WorkspaceGroupTest : public CxxTest::TestSuite group1->addWorkspace( group ); Workspace_sptr b = boost::make_shared(); TS_ASSERT_THROWS( group->isInGroup( *b ), std::runtime_error ); + group1->removeAll(); } }; diff --git a/Code/Mantid/Framework/API/test/WorkspacePropertyTest.h b/Code/Mantid/Framework/API/test/WorkspacePropertyTest.h index 48ea790b7c93..4a7cad2cade0 100644 --- a/Code/Mantid/Framework/API/test/WorkspacePropertyTest.h +++ b/Code/Mantid/Framework/API/test/WorkspacePropertyTest.h @@ -246,14 +246,14 @@ class WorkspacePropertyTest : public CxxTest::TestSuite TS_ASSERT( wsp5->isLocking()); // Create one that is not locking - WorkspaceProperty * p1 = new WorkspaceProperty("workspace1","ws1",Direction::Input, PropertyMode::Mandatory, LockMode::NoLock); - TS_ASSERT( !p1->isLocking()); + WorkspaceProperty p1("workspace1","ws1",Direction::Input, PropertyMode::Mandatory, LockMode::NoLock); + TS_ASSERT( !p1.isLocking()); // Copy constructor, both ways - WorkspaceProperty * wsp1_copy = new WorkspaceProperty(*wsp1); - TS_ASSERT( wsp1_copy->isLocking()); - WorkspaceProperty * p2 = new WorkspaceProperty(*p1); - TS_ASSERT( !p2->isLocking()); + WorkspaceProperty wsp1_copy(*wsp1); + TS_ASSERT( wsp1_copy.isLocking()); + WorkspaceProperty p2(p1); + TS_ASSERT( !p2.isLocking()); } diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 174eb258a49f..805a9d834e56 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -6,6 +6,7 @@ set ( SRC_FILES src/AddLogDerivative.cpp src/AddPeak.cpp src/AddSampleLog.cpp + src/AddTimeSeriesLog.cpp src/AlignDetectors.cpp src/AlphaCalc.cpp src/AnyShapeAbsorption.cpp @@ -66,6 +67,7 @@ set ( SRC_FILES src/CrossCorrelate.cpp src/CuboidGaugeVolumeAbsorption.cpp src/CylinderAbsorption.cpp + src/DeleteLog.cpp src/DeleteWorkspace.cpp src/DetectorDiagnostic.cpp src/DetectorEfficiencyCor.cpp @@ -232,6 +234,7 @@ set ( INC_FILES inc/MantidAlgorithms/AddLogDerivative.h inc/MantidAlgorithms/AddPeak.h inc/MantidAlgorithms/AddSampleLog.h + inc/MantidAlgorithms/AddTimeSeriesLog.h inc/MantidAlgorithms/AlignDetectors.h inc/MantidAlgorithms/AlphaCalc.h inc/MantidAlgorithms/AnyShapeAbsorption.h @@ -292,6 +295,7 @@ set ( INC_FILES inc/MantidAlgorithms/CrossCorrelate.h inc/MantidAlgorithms/CuboidGaugeVolumeAbsorption.h inc/MantidAlgorithms/CylinderAbsorption.h + inc/MantidAlgorithms/DeleteLog.h inc/MantidAlgorithms/DeleteWorkspace.h inc/MantidAlgorithms/DetectorDiagnostic.h inc/MantidAlgorithms/DetectorEfficiencyCor.h @@ -470,6 +474,7 @@ set ( TEST_FILES AddLogDerivativeTest.h AddPeakTest.h AddSampleLogTest.h + AddTimeSeriesLogTest.h AlignDetectorsTest.h AlphaCalcTest.h AnyShapeAbsorptionTest.h @@ -529,6 +534,7 @@ set ( TEST_FILES CropWorkspaceTest.h CuboidGaugeVolumeAbsorptionTest.h CylinderAbsorptionTest.h + DeleteLogTest.h DeleteWorkspaceTest.h DetectorEfficiencyCorTest.h DetectorEfficiencyCorUserTest.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/AddTimeSeriesLog.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/AddTimeSeriesLog.h new file mode 100644 index 000000000000..ab5171845f3f --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/AddTimeSeriesLog.h @@ -0,0 +1,53 @@ +#ifndef MANTID_ALGORITHMS_ADDTIMESERIESLOG_H_ +#define MANTID_ALGORITHMS_ADDTIMESERIESLOG_H_ + +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ + namespace Algorithms + { + + /** + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport AddTimeSeriesLog : public API::Algorithm + { + public: + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + + private: + virtual void initDocs(); + void init(); + void exec(); + + /// Remove an existing log of the given name + void removeExisting(API::MatrixWorkspace_sptr &logWS, const std::string & name); + /// Create or update the named log entry + void createOrUpdate(API::Run &run, const std::string & name); + }; + + } // namespace Algorithms +} // namespace Mantid + +#endif /* MANTID_ALGORITHMS_ADDTIMESERIESLOG_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h index b96153c7ac1b..dce03429686f 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h @@ -112,6 +112,9 @@ class DLLExport CheckWorkspacesMatch : public API::Algorithm std::string result; ///< the result string API::Progress * prog; + /// Variable states if one wants to compare workspaces in parallell. This usully true but if one wants to look at the comparison logs, parallell comparison make things complicated as + /// logs from different threads are mixed together. In this case, it is better not to do parallell comparison. + bool m_ParallelComparison; }; } // namespace Algorithms diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CorrectFlightPaths.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CorrectFlightPaths.h index 13c5e95c34cb..99f11cc62055 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CorrectFlightPaths.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CorrectFlightPaths.h @@ -80,7 +80,7 @@ class DLLExport CorrectFlightPaths: public API::Algorithm { Geometry::Instrument_const_sptr m_instrument; - Geometry::IObjComponent_const_sptr m_sample; + Geometry::IComponent_const_sptr m_sample; double m_l2; double m_wavelength; diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/DeleteLog.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/DeleteLog.h new file mode 100644 index 000000000000..c657578faa06 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/DeleteLog.h @@ -0,0 +1,49 @@ +#ifndef MANTID_ALGORITHMS_DELETELOG_H_ +#define MANTID_ALGORITHMS_DELETELOG_H_ + +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ + namespace Algorithms + { + + /** + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport DeleteLog : public API::Algorithm + { + public: + 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_DELETELOG_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/RemoveLowResTOF.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/RemoveLowResTOF.h index acd3f9c2c2f8..01570316e1fc 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/RemoveLowResTOF.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/RemoveLowResTOF.h @@ -31,7 +31,7 @@ class DLLExport RemoveLowResTOF : public API::Algorithm double m_DIFCref; ///< The reference value for DIFC to filter with double m_K; ///< Mystery variable that I'm not sure what it is for Geometry::Instrument_const_sptr m_instrument; ///< The instrument - Geometry::IObjComponent_const_sptr m_sample; ///< The sample + Geometry::IComponent_const_sptr m_sample; ///< The sample double m_L1; ///< The instrument initial flightpath double m_Tmin; ///< The start of the time-of-flight frame double m_wavelengthMin; ///< The minimum wavelength accessible in the frame diff --git a/Code/Mantid/Framework/Algorithms/src/AddPeak.cpp b/Code/Mantid/Framework/Algorithms/src/AddPeak.cpp index 64adc57398ed..aadfc02c9e12 100644 --- a/Code/Mantid/Framework/Algorithms/src/AddPeak.cpp +++ b/Code/Mantid/Framework/Algorithms/src/AddPeak.cpp @@ -75,8 +75,8 @@ namespace Algorithms const double count = getProperty("BinCount"); Mantid::Geometry::Instrument_const_sptr instr = runWS->getInstrument(); - Mantid::Geometry::IObjComponent_const_sptr source = instr->getSource(); - Mantid::Geometry::IObjComponent_const_sptr sample = instr->getSample(); + Mantid::Geometry::IComponent_const_sptr source = instr->getSource(); + Mantid::Geometry::IComponent_const_sptr sample = instr->getSample(); Mantid::Geometry::IDetector_const_sptr det = instr->getDetector(detID); const Mantid::Kernel::V3D samplePos = sample->getPos(); diff --git a/Code/Mantid/Framework/Algorithms/src/AddTimeSeriesLog.cpp b/Code/Mantid/Framework/Algorithms/src/AddTimeSeriesLog.cpp new file mode 100644 index 000000000000..fb7973771ce8 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/AddTimeSeriesLog.cpp @@ -0,0 +1,169 @@ +/*WIKI* +Creates/updates a time-series log entry on a chosen workspace. The given timestamp & value are appended to the +named log entry. If the named entry does not exist then a new log is created. A time stamp must be given in +ISO8601 format, e.g. 2010-09-14T04:20:12. + +By default, the given value is interpreted as a double and a double series is either created or expected. However, +if the "Type" is set to "int" then the value is interpreted as an integer and an integer is either created +or expected. +*WIKI*/ +/*WIKI_USAGE* +'''Python''' + import datetime as dt + + # Add an entry for the current time + log_name = "temperature" + log_value = 21.5 + AddTimeSeriesLog(inOutWS, Name=log_name, Time=dt.datetime.utcnow().isoformat(), Value=log_value) + +*WIKI_USAGE*/ + +#include "MantidAlgorithms/AddTimeSeriesLog.h" +#include "MantidKernel/DateTimeValidator.h" +#include "MantidKernel/MandatoryValidator.h" +#include "MantidKernel/ListValidator.h" +#include "MantidKernel/TimeSeriesProperty.h" + +namespace Mantid +{ + namespace Algorithms + { + using namespace API; + using namespace Kernel; + + namespace + { + /** + * Creates/updates the named log on the given run. The template type + * specifies either the type of TimeSeriesProperty that is expected to + * exist or the type that will be created + * @param run A reference to the run object that stores the logs + * @param name The name of the log that is to be either created or updated + * @param time A time string in ISO format, passed to the DateAndTime constructor + * @param value The value at the given time + */ + template + void createOrUpdateValue(API::Run& run, const std::string & name, + const std::string & time, const T value) + { + TimeSeriesProperty *timeSeries(NULL); + if(run.hasProperty(name)) + { + timeSeries = dynamic_cast*>(run.getLogData(name)); + if(!timeSeries) throw std::invalid_argument("Log '" + name + "' already exists but the values are a different type."); + } + else + { + timeSeries = new TimeSeriesProperty(name); + run.addProperty(timeSeries); + } + timeSeries->addValue(time, value); + } + + } + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(AddTimeSeriesLog) + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string AddTimeSeriesLog::name() const { return "AddTimeSeriesLog"; } + + /// Algorithm's version for identification. @see Algorithm::version + int AddTimeSeriesLog::version() const { return 1; } + + /// Algorithm's category for identification. @see Algorithm::category + const std::string AddTimeSeriesLog::category() const { return "DataHandling\\Logs"; } + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void AddTimeSeriesLog::initDocs() + { + this->setWikiSummary("Creates/updates a time-series log"); + this->setOptionalMessage("Creates/updates a time-series log"); + } + + //---------------------------------------------------------------------------------------------- + /** + * Initialize the algorithm's properties. + */ + void AddTimeSeriesLog::init() + { + declareProperty(new WorkspaceProperty("Workspace", "", Direction::InOut), + "In/out workspace that will store the new log information"); + + declareProperty("Name", "", boost::make_shared>(), + "A string name for either a new time series log to be created " + "or an existing name to update", Direction::Input); + declareProperty("Time", "", boost::make_shared(), + "An ISO formatted date/time string specifying the timestamp for " + "the given log value, e.g 2010-09-14T04:20:12", + Direction::Input); + auto nonEmtpyDbl = boost::make_shared>(); + declareProperty("Value", EMPTY_DBL(), nonEmtpyDbl, "The value for the log at the given time", + Direction::Input); + + auto optionsValidator = boost::make_shared>(); + optionsValidator->addAllowedValue("double"); + optionsValidator->addAllowedValue("int"); + declareProperty("Type", "double", optionsValidator, + "An optional type for the given value. A double value with a Type=int will have " + "the fractional part chopped off.", + Direction::Input); + declareProperty("DeleteExisting", false, + "If true and the named log exists then the whole log is removed first.", Direction::Input); + } + + //---------------------------------------------------------------------------------------------- + /** + * Execute the algorithm. + */ + void AddTimeSeriesLog::exec() + { + MatrixWorkspace_sptr logWS = getProperty("Workspace"); + std::string name = getProperty("Name"); + + const bool deleteExisting = getProperty("DeleteExisting"); + auto &run = logWS->mutableRun(); + if(deleteExisting && run.hasProperty(name)) removeExisting(logWS, name); + + createOrUpdate(run, name); + } + + /** + * @param logWS The workspace containing the log + * @param name The name of the log to delete + */ + void AddTimeSeriesLog::removeExisting(API::MatrixWorkspace_sptr &logWS, const std::string & name) + { + auto deleter = createChildAlgorithm("DeleteLog",-1,-1,false); + deleter->setProperty("Workspace", logWS); + deleter->setProperty("Name", name); + deleter->executeAsChildAlg(); + } + + /** + * @param run The run object that either has the log or will store it + * @param name The name of the log to create/update + */ + void AddTimeSeriesLog::createOrUpdate(API::Run &run, const std::string & name) + { + std::string time = getProperty("Time"); + double valueAsDouble = getProperty("Value"); + std::string type = getProperty("Type"); + bool asInt = (type == "int"); + + if(asInt) + { + createOrUpdateValue(run, name, time, static_cast(valueAsDouble)); + } + else + { + createOrUpdateValue(run, name, time, valueAsDouble); + } + + } + + + } // namespace Algorithms +} // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/ApplyDetailedBalance.cpp b/Code/Mantid/Framework/Algorithms/src/ApplyDetailedBalance.cpp index 5d043265f86b..d8ed9143fc01 100644 --- a/Code/Mantid/Framework/Algorithms/src/ApplyDetailedBalance.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ApplyDetailedBalance.cpp @@ -1,16 +1,17 @@ /*WIKI* - The fluctuation dissipation theorem [1,2] relates the dynamic susceptibility to the scattering function +The fluctuation dissipation theorem [1,2] relates the dynamic susceptibility to the scattering function - \left(1-e^{-\frac{E}{k_B T}}\right) S(\mathbf{q}, E) = \frac{1}{\pi} \chi'' (\mathbf{q}, E) +\left(1-e^{-\frac{E}{k_B T}}\right) S(\mathbf{q}, E) = \frac{1}{\pi} \chi'' (\mathbf{q}, E) - where E is the energy transfer to the system. The algorithm assumes that the y axis of the - input workspace contains the scattering function S. The y axis of the output workspace will - contain the dynamic susceptibility. The temperature is extracted from a log attached to the workspace, as the mean - value. Alternatively, the temperature can be directly specified. The algorithm will fail if neither option is - valid. +where E is the energy transfer to the system. The algorithm assumes that the y axis of the +input workspace contains the scattering function S. The y axis of the output workspace will +contain the dynamic susceptibility. The temperature is extracted from a log attached to the workspace, as the mean +value. Alternatively, the temperature can be directly specified. The algorithm will fail if neither option is +valid. - [1] S. W. Lovesey - Theory of Neutron Scattering from Condensed Matter, vol 1 - [2] I. A. Zaliznyak and S. H. Lee - Magnetic Neutron Scattering in "Modern techniques for characterizing magnetic materials" +[1] S. W. Lovesey - Theory of Neutron Scattering from Condensed Matter, vol 1 + +[2] I. A. Zaliznyak and S. H. Lee - Magnetic Neutron Scattering in "Modern techniques for characterizing magnetic materials" *WIKI*/ #include "MantidAlgorithms/ApplyDetailedBalance.h" diff --git a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp index fb67948ccff2..4961882ace02 100644 --- a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp @@ -24,10 +24,37 @@ In the case of [[EventWorkspace]]s, they are checked to hold identical event lis #include "MantidGeometry/MDGeometry/IMDDimension.h" #include +// namespace Mantid { namespace Algorithms { + namespace + { + /** Function which calculates relative error between two values and analyses if this error is within the limits + * requested. When the absolute value of the difference is smaller then the value of the error requested, + * absolute error is used instead of relative error. + + @param x1 -- first value to check difference + @param x2 -- second value to check difference + @param errorVal -- the value of the error, to check against. Should be large then 0 + + @returns true if error or false if the value is within the limits requested + */ + inline bool relErr(const double &x1,const double &x2,const double &errorVal) + { + + double num= std::fabs(x1-x2); + // how to treat x1<0 and x2 > 0 ? probably this way + double den=0.5*(std::fabs(x1)+std::fabs(x2)); + if (denerrorVal); + + return (num/den>errorVal); + + } + + } // Register the algorithm into the AlgorithmFactory DECLARE_ALGORITHM(CheckWorkspacesMatch) @@ -40,7 +67,7 @@ void CheckWorkspacesMatch::initDocs() } /// Constructor -CheckWorkspacesMatch::CheckWorkspacesMatch() : API::Algorithm(), result(), prog(NULL) +CheckWorkspacesMatch::CheckWorkspacesMatch() : API::Algorithm(), result(), prog(NULL),m_ParallelComparison(true) {} /// Virtual destructor @@ -181,6 +208,10 @@ void CheckWorkspacesMatch::exec() { result.clear(); + if (g_log.is(Logger::Priority::PRIO_DEBUG) ) + m_ParallelComparison = false; + + this->doComparison(); if ( result != "") @@ -377,8 +408,9 @@ bool CheckWorkspacesMatch::compareEventWorkspaces(DataObjects::EventWorkspace_co size_t numUnequalBothEvents = 0; std::vector vec_mismatchedwsindex; - - PARALLEL_FOR2(ews1, ews2) + bool condition = m_ParallelComparison && ews1->threadSafe() && ews2->threadSafe() ; + PARALLEL_FOR_IF(condition) + for (int i=0; i(ews1->getNumberHistograms()); ++i) for (int i=0; i(ews1->getNumberHistograms()); i++) { PARALLEL_START_INTERUPT_REGION @@ -420,7 +452,7 @@ bool CheckWorkspacesMatch::compareEventWorkspaces(DataObjects::EventWorkspace_co { // 2 spectra have different number of events ++ numUnequalNumEventsSpectra; - } + } else { // 2 spectra have some events different to each other @@ -428,7 +460,7 @@ bool CheckWorkspacesMatch::compareEventWorkspaces(DataObjects::EventWorkspace_co numUnequalTOFEvents += tempNumTof; numUnequalPulseEvents += tempNumPulses; numUnequalBothEvents += tempNumBoth; - } + } vec_mismatchedwsindex.push_back(i); } // Parallel critical region @@ -514,8 +546,9 @@ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::M bool resultBool = true; // Now check the data itself - PARALLEL_FOR2(ws1, ws2) - for ( int i = 0; i < static_cast(numHists); ++i ) + bool condition = m_ParallelComparison && ws1->threadSafe() && ws2->threadSafe() ; + PARALLEL_FOR_IF(condition) + for ( long i = 0; i < static_cast(numHists); ++i ) { PARALLEL_START_INTERUPT_REGION prog->report("Histograms"); @@ -535,27 +568,10 @@ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::M bool err; if (RelErr) { - double s1=0.5*(X1[j]+X2[j]); - if (s1>tolerance) - err = (std::fabs(X1[j] - X2[j]) > tolerance*s1); - else - err = (std::fabs(X1[j] - X2[j]) > tolerance); - - double s2=0.5*(Y1[j]+Y2[j]); - if (s2>tolerance) - err = ((std::fabs(Y1[j] - Y2[j]) > tolerance*s2)||err); - else - err = ((std::fabs(Y1[j] - Y2[j]) > tolerance)||err); - - - double s3=0.5*(E1[j]+E2[j]); - if (s3>tolerance) - err = ((std::fabs(E1[j] - E2[j]) > tolerance*s3)||err); - else - err = ((std::fabs(E1[j] - E2[j]) > tolerance)||err); + err = (relErr(X1[j],X2[j],tolerance) || relErr(Y1[j],Y2[j],tolerance) || relErr(E1[j],E2[j],tolerance)); } else - err = (std::fabs(X1[j] - X2[j]) > tolerance || std::fabs(Y1[j] - Y2[j]) > tolerance + err = (std::fabs(X1[j] - X2[j]) > tolerance || std::fabs(Y1[j] - Y2[j]) > tolerance || std::fabs(E1[j] - E2[j]) > tolerance); if (err) @@ -573,6 +589,8 @@ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::M // Extra one for histogram data if ( histogram && std::fabs(X1.back() - X2.back()) > tolerance ) { + g_log.debug() << " Data ranges mismatch for spectra N: (" << i << ")\n"; + g_log.debug() << " Last bin ranges (X1_end vs X2_end) = (" << X1.back() << "," <getAxis(0)->unit(); Kernel::Unit_sptr toUnit = UnitFactory::Instance().create(unitTarget); - IObjComponent_const_sptr source = inputWS->getInstrument()->getSource(); - IObjComponent_const_sptr sample = inputWS->getInstrument()->getSample(); + IComponent_const_sptr source = inputWS->getInstrument()->getSource(); + IComponent_const_sptr sample = inputWS->getInstrument()->getSample(); std::vector emptyVector; const double l1 = source->getDistance(*sample); const std::string emodeStr = getProperty("EMode"); diff --git a/Code/Mantid/Framework/Algorithms/src/ConvertSpectrumAxis2.cpp b/Code/Mantid/Framework/Algorithms/src/ConvertSpectrumAxis2.cpp index 9b2c8cb4590a..69cda48dda8b 100644 --- a/Code/Mantid/Framework/Algorithms/src/ConvertSpectrumAxis2.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ConvertSpectrumAxis2.cpp @@ -134,8 +134,8 @@ namespace Algorithms void ConvertSpectrumAxis2::createElasticQMap(const std::string & targetUnit) { - IObjComponent_const_sptr source = m_inputWS->getInstrument()->getSource(); - IObjComponent_const_sptr sample = m_inputWS->getInstrument()->getSample(); + IComponent_const_sptr source = m_inputWS->getInstrument()->getSource(); + IComponent_const_sptr sample = m_inputWS->getInstrument()->getSample(); const std::string emodeStr = getProperty("EMode"); int emode = 0; diff --git a/Code/Mantid/Framework/Algorithms/src/ConvertUnits.cpp b/Code/Mantid/Framework/Algorithms/src/ConvertUnits.cpp index 63310e963413..c391547b186a 100644 --- a/Code/Mantid/Framework/Algorithms/src/ConvertUnits.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ConvertUnits.cpp @@ -394,8 +394,8 @@ void ConvertUnits::convertViaTOF(Kernel::Unit_const_sptr fromUnit, API::MatrixWo Kernel::Unit_const_sptr outputUnit = outputWS->getAxis(0)->unit(); // Get the distance between the source and the sample (assume in metres) - IObjComponent_const_sptr source = instrument->getSource(); - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr sample = instrument->getSample(); if ( source == NULL || sample == NULL ) { throw Exception::InstrumentDefinitionError("Instrubment not sufficiently defined: failed to get source and/or sample"); diff --git a/Code/Mantid/Framework/Algorithms/src/CreateLogTimeCorrection.cpp b/Code/Mantid/Framework/Algorithms/src/CreateLogTimeCorrection.cpp index 0a86c2091084..8fa2379ee1c0 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateLogTimeCorrection.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateLogTimeCorrection.cpp @@ -117,14 +117,14 @@ namespace Algorithms void CreateLogTimeCorrection::getInstrumentSetup() { // 1. Get sample position and source position - IObjComponent_const_sptr sample = m_instrument->getSample(); + IComponent_const_sptr sample = m_instrument->getSample(); if (!sample) { throw runtime_error("No sample has been set."); } V3D samplepos = sample->getPos(); - IObjComponent_const_sptr source = m_instrument->getSource(); + IComponent_const_sptr source = m_instrument->getSource(); if (!source) { throw runtime_error("No source has been set."); diff --git a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp index 7e41dbe0a203..3d672d8c72b0 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateTransmissionWorkspace.cpp @@ -1,6 +1,6 @@ /*WIKI* - Creates a transmission run workspace given one or more TOF workspaces and the original run Workspace. If two workspaces are provided, then - the workspaces are stitched together using [[Stitch1D]]. InputWorkspaces must be in TOF. A single output workspace is generated with x-units of Wavlength in angstroms. +Creates a transmission run workspace given one or more TOF workspaces and the original run Workspace. If two workspaces are provided, then +the workspaces are stitched together using [[Stitch1D]]. InputWorkspaces must be in TOF. A single output workspace is generated with x-units of Wavlength in angstroms. *WIKI*/ #include "MantidAlgorithms/CreateTransmissionWorkspace.h" diff --git a/Code/Mantid/Framework/Algorithms/src/DeleteLog.cpp b/Code/Mantid/Framework/Algorithms/src/DeleteLog.cpp new file mode 100644 index 000000000000..ab0e20f627b6 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/src/DeleteLog.cpp @@ -0,0 +1,66 @@ +/*WIKI* +Removes a named log from the run attached to the input workspace. If the log does not exist then the algorithm simply +emits a warning and does not fail. +*WIKI*/ +#include "MantidAlgorithms/DeleteLog.h" +#include "MantidKernel/MandatoryValidator.h" + +namespace Mantid +{ +namespace Algorithms +{ + using namespace API; + using namespace Kernel; + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(DeleteLog) + + //---------------------------------------------------------------------------------------------- + /// @copydoc Algorithm::name + const std::string DeleteLog::name() const { return "DeleteLog"; } + + /// @copydoc Algorithm::version + int DeleteLog::version() const { return 1; } + + /// @copydoc Algorithm::category + const std::string DeleteLog::category() const { return "DataHandling\\Logs";} + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void DeleteLog::initDocs() + { + this->setWikiSummary("Removes a named log from a run"); + this->setOptionalMessage("Removes a named log from a run"); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void DeleteLog::init() + { + declareProperty(new WorkspaceProperty<>("Workspace","",Direction::InOut), + "In/out workspace containing the logs. The workspace is modified in place"); + declareProperty("Name","", boost::make_shared>(), + "", Direction::Input); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void DeleteLog::exec() + { + MatrixWorkspace_sptr logWS = getProperty("Workspace"); + std::string logName = getProperty("Name"); + auto & run = logWS->mutableRun(); + if(run.hasProperty(logName)) + { + run.removeLogData(logName); + } + else + { + g_log.warning() << "Unable to delete log '" << logName << "' from the given workspace as it does not exist.\n"; + } + } + +} // namespace Algorithms +} // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/src/DiffractionEventCalibrateDetectors.cpp b/Code/Mantid/Framework/Algorithms/src/DiffractionEventCalibrateDetectors.cpp index bfc7a6104494..b1bc5076ace8 100644 --- a/Code/Mantid/Framework/Algorithms/src/DiffractionEventCalibrateDetectors.cpp +++ b/Code/Mantid/Framework/Algorithms/src/DiffractionEventCalibrateDetectors.cpp @@ -409,8 +409,8 @@ namespace Algorithms outfile << "# "<< DateAndTime::getCurrentTime().toFormattedString("%c") <<"\n"; outfile << "#\n"; outfile << "6 L1 T0_SHIFT\n"; - IObjComponent_const_sptr source = inst->getSource(); - IObjComponent_const_sptr sample = inst->getSample(); + IComponent_const_sptr source = inst->getSource(); + IComponent_const_sptr sample = inst->getSample(); outfile << "7 "<getDistance(*sample)*100<<" 0\n"; outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX CenterY CenterZ BaseX BaseY BaseZ UpX UpY UpZ\n"; } diff --git a/Code/Mantid/Framework/Algorithms/src/EditInstrumentGeometry.cpp b/Code/Mantid/Framework/Algorithms/src/EditInstrumentGeometry.cpp index 311836b2c8de..ce069fb394f1 100644 --- a/Code/Mantid/Framework/Algorithms/src/EditInstrumentGeometry.cpp +++ b/Code/Mantid/Framework/Algorithms/src/EditInstrumentGeometry.cpp @@ -207,8 +207,8 @@ namespace Algorithms g_log.error(errmsg); throw std::runtime_error(errmsg); } - Geometry::IObjComponent_const_sptr source = originstrument->getSource(); - Geometry::IObjComponent_const_sptr sample = originstrument->getSample(); + Geometry::IComponent_const_sptr source = originstrument->getSource(); + Geometry::IComponent_const_sptr sample = originstrument->getSample(); l1 = source->getDistance(*sample); g_log.information() << "Retrieve L1 from input data workspace. \n"; } diff --git a/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp b/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp index e475c5cd9afb..b46aafa610d4 100644 --- a/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp +++ b/Code/Mantid/Framework/Algorithms/src/FindPeaks.cpp @@ -1,26 +1,25 @@ /*WIKI* - This algorithm searches the specified spectra in a workspace for peaks, returning a list of the found and successfully fitted peaks. The search algorithm is described in full in reference [1]. In summary: the second difference of each spectrum is computed and smoothed. This smoothed data is then searched for patterns consistent with the presence of a peak. The list of candidate peaks found is passed to a fitting routine and those that are successfully fitted are kept and returned in the output workspace (and logged at information level). +This algorithm searches the specified spectra in a workspace for peaks, returning a list of the found and successfully fitted peaks. The search algorithm is described in full in reference [1]. In summary: the second difference of each spectrum is computed and smoothed. This smoothed data is then searched for patterns consistent with the presence of a peak. The list of candidate peaks found is passed to a fitting routine and those that are successfully fitted are kept and returned in the output workspace (and logged at information level). +The output [[TableWorkspace]] contains the following columns, which reflect the fact that the peak has been fitted to a Gaussian atop a linear background: spectrum, centre, width, height, backgroundintercept & backgroundslope. - The output [[TableWorkspace]] contains the following columns, which reflect the fact that the peak has been fitted to a Gaussian atop a linear background: spectrum, centre, width, height, backgroundintercept & backgroundslope. +=== Subalgorithms used === +FindPeaks uses the [[SmoothData]] algorithm to, well, smooth the data - a necessary step to identify peaks in statistically fluctuating data. The [[Fit]] algorithm is used to fit candidate peaks. - ==== Subalgorithms used ==== - FindPeaks uses the [[SmoothData]] algorithm to, well, smooth the data - a necessary step to identify peaks in statistically fluctuating data. The [[Fit]] algorithm is used to fit candidate peaks. +=== Treating weak peaks vs. high background === +FindPeaks uses a more complicated approach to fit peaks if '''HighBackground''' is flagged. In this case, FindPeak will fit the background first, and then do a Gaussian fit the peak with the fitted background removed. This procedure will be repeated for a couple of times with different guessed peak widths. And the parameters of the best result is selected. The last step is to fit the peak with a combo function including background and Gaussian by using the previously recorded best background and peak parameters as the starting values. - ==== Treating weak peaks vs. high background ==== - FindPeaks uses a more complicated approach to fit peaks if '''HighBackground''' is flagged. In this case, FindPeak will fit the background first, and then do a Gaussian fit the peak with the fitted background removed. This procedure will be repeated for a couple of times with different guessed peak widths. And the parameters of the best result is selected. The last step is to fit the peak with a combo function including background and Gaussian by using the previously recorded best background and peak parameters as the starting values. +=== Criteria To Validate Peaks Found === +FindPeaks finds peaks by fitting a Guassian with background to a certain range in the input histogram. [[Fit]] may not give a correct result even if chi^2 is used as criteria alone. Thus some other criteria are provided as options to validate the result +# Peak position. If peak positions are given, and trustful, then the fitted peak position must be within a short distance to the give one. +# Peak height. In the certain number of trial, peak height can be used to select the best fit among various starting sigma values. - ==== Criteria To Validate Peaks Found ==== - FindPeaks finds peaks by fitting a Guassian with background to a certain range in the input histogram. [[Fit]] may not give a correct result even if chi^2 is used as criteria alone. Thus some other criteria are provided as options to validate the result - 1. Peak position. If peak positions are given, and trustful, then the fitted peak position must be within a short distance to the give one. - 2. Peak height. In the certain number of trial, peak height can be used to select the best fit among various starting sigma values. +=== Fit Window === +If FitWindows is defined, then a peak's range to fit (i.e., x-min and x-max) is confined by this window. - ==== Fit Window ==== - If FitWindows is defined, then a peak's range to fit (i.e., x-min and x-max) is confined by this window. +If FitWindows is defined, starting peak centres are NOT user's input, but found by highest value within peak window. (Is this correct???) - If FitWindows is defined, starting peak centres are NOT user's input, but found by highest value within peak window. (Is this correct???) - - ==== References ==== - # M.A.Mariscotti, ''A method for automatic identification of peaks in the presence of background and its application to spectrum analysis'', NIM '''50''' (1967) 309. +==== References ==== +# M.A.Mariscotti, ''A method for automatic identification of peaks in the presence of background and its application to spectrum analysis'', NIM '''50''' (1967) 309. *WIKI*/ //---------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/Algorithms/src/GeneralisedSecondDifference.cpp b/Code/Mantid/Framework/Algorithms/src/GeneralisedSecondDifference.cpp index 498585ebe382..fd695e3c6988 100644 --- a/Code/Mantid/Framework/Algorithms/src/GeneralisedSecondDifference.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GeneralisedSecondDifference.cpp @@ -1,10 +1,9 @@ /*WIKI* - Compute the generalised second difference of a spectrum or several spectra based on the method - described by M.A. Mariscotti., Nuclear Instruments and Methods 50, 309 (1967). Given a spectrum with value yi (0<=igetInstrument()->getSource(); + const IComponent_const_sptr source = WS->getInstrument()->getSource(); // retrieve a pointer to the first detector and get its distance size_t monWI = 0; diff --git a/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp b/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp index ec8c6f79656a..29d1f0f7e1f6 100644 --- a/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp @@ -295,7 +295,7 @@ double GetEi2::getDistanceFromSource(size_t ws_index) const { g_log.debug() << "Computing distance between spectrum at index '" << ws_index << "' and the source\n"; - const IObjComponent_const_sptr source = m_input_ws->getInstrument()->getSource(); + const IComponent_const_sptr source = m_input_ws->getInstrument()->getSource(); // Retrieve a pointer detector IDetector_const_sptr det = m_input_ws->getDetector(ws_index); if( !det ) diff --git a/Code/Mantid/Framework/Algorithms/src/MaskBins.cpp b/Code/Mantid/Framework/Algorithms/src/MaskBins.cpp index 4ad914cab3c6..25b152b6c8a6 100644 --- a/Code/Mantid/Framework/Algorithms/src/MaskBins.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MaskBins.cpp @@ -1,15 +1,23 @@ /*WIKI* +Masks bins in a workspace. Masked bins should properly be regarded as having been completely removed from the workspace. +Bins falling within the range given (even partially) are masked, i.e. their data and error values are set to zero and the bin is added to the list of masked bins. +This range is masked for all spectra in the workspace (though the workspace does not have to have common X values in all spectra). -Masks bins in a workspace. Masked bins should properly be regarded as having been completely removed from the workspace. Bins falling within the range given (even partially) are masked, i.e. their data and error values are set to zero and the bin is added to the list of masked bins. This range is masked for all spectra in the workspace (though the workspace does not have to have common X values in all spectra). - -At present, although the zeroing of data will obviously be 'seen' by all downstream algorithms, only [[DiffractionFocussing]] (version 2) and [[Q1D]] have been modified to take account of masking. Several algorithms (e.g. [[Rebin]], [[CropWorkspace]]) have been modified to properly propagate the masking. +At present, although the zeroing of data will obviously be 'seen' by all downstream algorithms. +Only [[DiffractionFocussing]] (version 2) and [[Q1D]] have been modified to take account of masking. +Several algorithms (e.g. [[Rebin]], [[CropWorkspace]]) have been modified to properly propagate the masking. ==Related Algorithms== -===RemoveBins== -[[RemoveBins]] can work in several ways, if the bins are at the edges of the workspace they will be removed, and that will in many ways act like Masking the bins. If the bins are in the middle of the workspace then the effect depends on the type of interpolation, but importantly these bins will continue to influence future algorithms as opposed to masked bins. For example, with no interpolation [[RemoveBins]] sets the bin values to 0. This 0 values will be included in the summing performed in DiffractionFocussing, pushing down the values in that region. -MaskBins is more clever. While if you look at the data it will appear that it has simply set the values to 0 it has also set a series of flags inside that mark those bins to not be included in further claculations. This means that when you Focus the data these values are simply missed out of the summing that is performed. - +===RemoveBins=== +[[RemoveBins]] can work in several ways, if the bins are at the edges of the workspace they will be removed, and that will in many ways act like Masking the bins. +If the bins are in the middle of the workspace then the effect depends on the type of interpolation, +but importantly these bins will continue to influence future algorithms as opposed to masked bins. +For example, with no interpolation [[RemoveBins]] sets the bin values to 0. This 0 values will be included in the summing performed in DiffractionFocussing, +pushing down the values in that region. MaskBins is more clever. +While if you look at the data, it will appear that it has simply set the values to 0. +It has also set a series of flags inside that mark those bins to not be included in further claculations. +This means that when you Focus the data these values are simply missed out of the summing that is performed. *WIKI*/ //---------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp b/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp index 7e9adb92f52b..136383d332aa 100644 --- a/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MaskBinsFromTable.cpp @@ -5,9 +5,10 @@ Masks bins in a workspace. The user specified masking parameters, including spe It calls algorithm MaskBins underneath. ==Related Algorithms== -===MaskBins== -[[MaskBins]] Masks bins in a workspace. Masked bins should properly be regarded as having been completely removed from the workspace. Bins falling within the range given (even partially) are masked, i.e. their data and error values are set to zero and the bin is added to the list of masked bins. This range is masked for all spectra in the workspace (though the workspace does not have to have common X values in all spectra). - +===MaskBins=== +[[MaskBins]] masks bins in a workspace. Masked bins should properly be regarded as having been completely removed from the workspace. +Bins falling within the range given (even partially) are masked, i.e. their data and error values are set to zero and the bin is added to the list of masked bins. +This range is masked for all spectra in the workspace (though the workspace does not have to have common X values in all spectra). *WIKI*/ diff --git a/Code/Mantid/Framework/Algorithms/src/ModeratorTzero.cpp b/Code/Mantid/Framework/Algorithms/src/ModeratorTzero.cpp index 55d500ed1396..7acb8319d310 100644 --- a/Code/Mantid/Framework/Algorithms/src/ModeratorTzero.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ModeratorTzero.cpp @@ -223,7 +223,7 @@ void ModeratorTzero::execEvent() } //Get a pointer to the sample - IObjComponent_const_sptr sample = outputWS->getInstrument()->getSample(); + IComponent_const_sptr sample = outputWS->getInstrument()->getSample(); // Loop over the spectra Progress prog(this,0.0,1.0,numHists); //report progress of algorithm @@ -299,7 +299,7 @@ double ModeratorTzero::CalculateL1(Mantid::API::MatrixWorkspace_sptr inputWS, si } else { - IObjComponent_const_sptr sample = m_instrument->getSample(); + IComponent_const_sptr sample = m_instrument->getSample(); try { L1 = m_instrument->getSource()->getDistance(*sample); @@ -335,7 +335,7 @@ double ModeratorTzero::CalculateT2(MatrixWorkspace_sptr inputWS, size_t i) } else { - IObjComponent_const_sptr sample = m_instrument->getSample(); + IComponent_const_sptr sample = m_instrument->getSample(); // Get final energy E_f, final velocity v_f std::vector< double > wsProp=det->getNumberParameter("Efixed"); if ( !wsProp.empty() ) diff --git a/Code/Mantid/Framework/Algorithms/src/ModeratorTzeroLinear.cpp b/Code/Mantid/Framework/Algorithms/src/ModeratorTzeroLinear.cpp index b84306771e19..c1aab587dc01 100644 --- a/Code/Mantid/Framework/Algorithms/src/ModeratorTzeroLinear.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ModeratorTzeroLinear.cpp @@ -277,7 +277,7 @@ void ModeratorTzeroLinear::calculateTfLi(MatrixWorkspace_const_sptr inputWS, siz } else { - IObjComponent_const_sptr sample = m_instrument->getSample(); + IComponent_const_sptr sample = m_instrument->getSample(); try { L_i = m_instrument->getSource()->getDistance(*sample); diff --git a/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp b/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp index fec0868f9835..3ca2311db099 100644 --- a/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp +++ b/Code/Mantid/Framework/Algorithms/src/MultipleScatteringCylinderAbsorption.cpp @@ -144,8 +144,8 @@ void MultipleScatteringCylinderAbsorption::exec() Instrument_const_sptr instrument = in_WS->getInstrument(); if (instrument == NULL) throw std::runtime_error("Failed to find instrument attached to InputWorkspace"); - IObjComponent_const_sptr source = instrument->getSource(); - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr sample = instrument->getSample(); if (source == NULL) throw std::runtime_error("Failed to find source in the instrument for InputWorkspace"); if (sample == NULL) diff --git a/Code/Mantid/Framework/Algorithms/src/PerformIndexOperations.cpp b/Code/Mantid/Framework/Algorithms/src/PerformIndexOperations.cpp index 38bc603ff435..0fe5a1dc9c0b 100644 --- a/Code/Mantid/Framework/Algorithms/src/PerformIndexOperations.cpp +++ b/Code/Mantid/Framework/Algorithms/src/PerformIndexOperations.cpp @@ -1,9 +1,9 @@ /*WIKI* - Performs index operations on a workspace which involve cropping out spectra and summing spectra together. See [[MultiFileLoading]] for similar syntax used during loading, though operations - using step sizes are not supported here. +Performs index operations on a workspace which involve cropping out spectra and summing spectra together. See [[MultiFileLoading]] for similar syntax used during loading, though operations +using step sizes are not supported here. - == Basic Instructions == +== Basic Instructions == {| class="wikitable" !rowspan="2" |Name @@ -40,20 +40,22 @@ |- |} - == Complex Instructions == +== Complex Instructions == - The basic instructions listed above can be used in combination because ''', can be used to separate out sets of instructions as well as indexes to keep'''. For example, ''0-2, 3:6'' will add - spectrum with workspace indexes 0-2 together into a single spectrum and then append spectra that correspond to workspace indexes 3-6 from the original workspace (you will have 4 spectra - in the output workspace). +The basic instructions listed above can be used in combination because ''', can be used to separate out sets of instructions as well as indexes to keep'''. +For example, ''0-2, 3:6'' will add +spectrum with workspace indexes 0-2 together into a single spectrum and then append spectra that correspond to +workspace indexes 3-6 from the original workspace (you will have 4 spectra +in the output workspace). - == Limitations == +== Limitations == - * The ''+'' operator is binary only and works like 0+1, but cannot be used like 0+1+2. Use the Add Range operator ''-'' in these scenarios. - - == Order of operations == - The spectra will appear in the output workspace in the same order that they are defined in the instructions. For example ''1+2, 0'' will have the results of 1+2 as workspace index 0 in the output - workspace and index 0 in the original workspace will be mapped to workspace index 1 in the output workspace. +* The ''+'' operator is binary only and works like 0+1, but cannot be used like 0+1+2. Use the Add Range operator ''-'' in these scenarios. +== Order of operations == +The spectra will appear in the output workspace in the same order that they are defined in the instructions. +For example ''1+2, 0'' will have the results of 1+2 as workspace index 0 in the output +workspace and index 0 in the original workspace will be mapped to workspace index 1 in the output workspace. *WIKI*/ diff --git a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp index 9b0df4cca7d8..deeed8362790 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReflectometryReductionOne.cpp @@ -1,24 +1,26 @@ /*WIKI* - Reduces a single TOF reflectometry run into a mod Q vs I/I0 workspace. Performs transmission corrections. Handles both point detector and multidetector cases. - The algorithm can correct detector locations based on an input theta value. +Reduces a single TOF reflectometry run into a mod Q vs I/I0 workspace. Performs transmission corrections. Handles both point detector and multidetector cases. +The algorithm can correct detector locations based on an input theta value. - Historically the work performed by this algorithm was known as the Quick script. +Historically the work performed by this algorithm was known as the Quick script. - === Analysis Modes === +=== Analysis Modes === - The default analysis mode is ''PointDetectorAnalysis''. Only this mode supports Transmission corrections (see below). For PointAnalysisMode - the analysis can be roughly reduced to IvsLam = DetectorWS / sum(I0) / TransmissionWS / sum(I0). The normalization by tranmission run(s) is optional. - Input workspaces are converted to ''Wavelength'' first via [[ConvertUnits]]. +The default analysis mode is ''PointDetectorAnalysis''. Only this mode supports Transmission corrections (see below). For PointAnalysisMode +the analysis can be roughly reduced to IvsLam = DetectorWS / sum(I0) / TransmissionWS / sum(I0). The normalization by tranmission run(s) is optional. +Input workspaces are converted to ''Wavelength'' first via [[ConvertUnits]]. - IvsQ is calculated via [[ConvertUnits]] into units of ''MomentumTransfer''. Corrections may be applied prior to the transformation to ensure that the detectors are in the correct location according to the input Theta value. - Corrections are only enabled when a Theta input value has been provided. +IvsQ is calculated via [[ConvertUnits]] into units of ''MomentumTransfer''. +Corrections may be applied prior to the transformation to ensure that the detectors are in the correct location according to the input Theta value. +Corrections are only enabled when a Theta input value has been provided. - === Transmission Runs === - Transmission correction is a normalization step, which may be applied to ''PointDetectorAnalysis'' reduction. +=== Transmission Runs === +Transmission correction is a normalization step, which may be applied to ''PointDetectorAnalysis'' reduction. - Transmission runs are expected to be in TOF. The spectra numbers in the Transmission run workspaces must be the same as those in the Input Run workspace. If two Transmission - runs are provided then the Stitching parameters associated with the transmission runs will also be required. If a single Transmission run is provided, then no stitching - parameters will be needed. +Transmission runs are expected to be in TOF. The spectra numbers in the Transmission run workspaces must be the same as those in the Input Run workspace. +If two Transmission runs are provided then the Stitching parameters associated with the transmission runs will also be required. +If a single Transmission run is provided, then no stitching +parameters will be needed. *WIKI*/ diff --git a/Code/Mantid/Framework/Algorithms/src/RemoveBins.cpp b/Code/Mantid/Framework/Algorithms/src/RemoveBins.cpp index 7d49a5dd9d4c..c4f3fca7a670 100644 --- a/Code/Mantid/Framework/Algorithms/src/RemoveBins.cpp +++ b/Code/Mantid/Framework/Algorithms/src/RemoveBins.cpp @@ -1,18 +1,24 @@ /*WIKI* -This algorithm removes bins from a workspace. A minimum and maximum X value to be removed needs to be provided. This can be in a different unit to the workspace, in which case it is transformed internally. +This algorithm removes bins from a workspace. A minimum and maximum X value to be removed needs to be provided. +This can be in a different unit to the workspace, in which case it is transformed internally. The treatment of the removed bins is slightly different, depending on where in the spectrum the bins to be removed lie: ==== Bins at either end of spectrum ==== -If the workspaces has common X binning for all spectra, then the [[CropWorkspace]] algorithm will be called as a child algorithm. This will result in the affected bins (which includes the bin in which the boundary - XMin or XMax - lies) being removed completely, leading to the output workspace having fewer bins than the input one. +If the workspaces has common X binning for all spectra, then the [[CropWorkspace]] algorithm will be called as a child algorithm. +This will result in the affected bins (which includes the bin in which the boundary - XMin or XMax - lies) being removed completely, +leading to the output workspace having fewer bins than the input one. In the case where the X binning varies from spectrum to spectrum, the bin values will be set to zero regardless of the setting of the Interpolation property. ==== Bins in the middle of a spectrum ==== -The Interpolation property is applicable to this situation. If it is set to "Linear" then the bins are set to values calculated from the values of the bins on either side of the range. If set to "None" then bins entirely within the range given are set to zero whilst the bins in which the boundary fall have their values scaled in proportion to the percentage of the bin's width which falls outside XMin or XMax as appropriate. +The Interpolation property is applicable to this situation. +If it is set to "Linear" then the bins are set to values calculated from the values of the bins on either side of the range. +If set to "None" then bins entirely within the range given are set to zero whilst the bins in which the boundary fall have their values scaled +in proportion to the percentage of the bin's width which falls outside XMin or XMax as appropriate. ==== Restrictions on the input workspace ==== @@ -20,8 +26,10 @@ The Interpolation property is applicable to this situation. If it is set to "Lin * The input workspace must contain histogram data ==Related Algorithms== -===MaskBins== -[[MaskBins]] will set the data in the desired bins to 0 and importantly also marks those bins as masked, so that further algorithms should not include this data in their grouping calculations. This is particularly used for Diffraction Focussing. +===MaskBins=== +[[MaskBins]] will set the data in the desired bins to 0 and importantly also marks those bins as masked, +so that further algorithms should not include this data in their grouping calculations. +This is particularly used for Diffraction Focussing. *WIKI*/ //---------------------------------------------------------------------- @@ -298,7 +306,7 @@ void RemoveBins::calculateDetectorPosition(const int& index, double& l1, double& // Get a pointer to the instrument contained in the workspace Geometry::Instrument_const_sptr instrument = m_inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); // Check for valid instrument if (sample == NULL) { diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp index d5ef3a3de003..2bc8b2bc8259 100644 --- a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp @@ -114,8 +114,8 @@ void SofQW::exec() Instrument_const_sptr instrument = inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) - IObjComponent_const_sptr source = instrument->getSource(); - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr sample = instrument->getSample(); V3D beamDir = sample->getPos() - source->getPos(); beamDir.normalize(); diff --git a/Code/Mantid/Framework/Algorithms/src/SolidAngle.cpp b/Code/Mantid/Framework/Algorithms/src/SolidAngle.cpp index 433b833fd6e1..264b2a6caab7 100644 --- a/Code/Mantid/Framework/Algorithms/src/SolidAngle.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SolidAngle.cpp @@ -110,7 +110,7 @@ namespace Mantid Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); // Get the distance between the source and the sample (assume in metres) - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if ( !sample ) { g_log.information( diff --git a/Code/Mantid/Framework/Algorithms/src/UnwrapMonitor.cpp b/Code/Mantid/Framework/Algorithms/src/UnwrapMonitor.cpp index b1abaff12300..7ddca58762fe 100644 --- a/Code/Mantid/Framework/Algorithms/src/UnwrapMonitor.cpp +++ b/Code/Mantid/Framework/Algorithms/src/UnwrapMonitor.cpp @@ -194,7 +194,7 @@ double UnwrapMonitor::getPrimaryFlightpath() const // Get a pointer to the instrument contained in the input workspace Geometry::Instrument_const_sptr instrument = m_inputWS->getInstrument(); // Get the distance between the source and the sample - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); double L1; try { diff --git a/Code/Mantid/Framework/Algorithms/src/UnwrapSNS.cpp b/Code/Mantid/Framework/Algorithms/src/UnwrapSNS.cpp index 67fbc1d40933..aee9d23a9b2a 100644 --- a/Code/Mantid/Framework/Algorithms/src/UnwrapSNS.cpp +++ b/Code/Mantid/Framework/Algorithms/src/UnwrapSNS.cpp @@ -124,7 +124,7 @@ void UnwrapSNS::exec() // without the primary flight path the algorithm cannot work try { Geometry::Instrument_const_sptr instrument = m_inputWS->getInstrument(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); m_L1 = instrument->getSource()->getDistance(*sample); } catch (NotFoundError&) diff --git a/Code/Mantid/Framework/Algorithms/test/AddTimeSeriesLogTest.h b/Code/Mantid/Framework/Algorithms/test/AddTimeSeriesLogTest.h new file mode 100644 index 000000000000..5f9c9e94146c --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/test/AddTimeSeriesLogTest.h @@ -0,0 +1,163 @@ +#ifndef MANTID_ALGORITHMS_ADDTIMESERIESLOGTEST_H_ +#define MANTID_ALGORITHMS_ADDTIMESERIESLOGTEST_H_ + +#include +#include "MantidAlgorithms/AddTimeSeriesLog.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" + +class AddTimeSeriesLogTest : public CxxTest::TestSuite +{ +private: + enum LogType { Double, Integer }; + enum UpdateType { Update, Delete }; + +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static AddTimeSeriesLogTest *createSuite() { return new AddTimeSeriesLogTest(); } + static void destroySuite( AddTimeSeriesLogTest *suite ) { delete suite; } + + void test_defaults_create_a_double_type_series() + { + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:12", 20.0)); + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:12", 20.0, 0); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:19", 40.0)); + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:19", 40.0, 1); + } + + void test_forcing_to_int_creates_int_from_double() + { + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:12", 20.5, Integer)); + + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:12", 20, 0); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:19", 40.0, Integer)); + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:19", 40, 1); + + } + + void test_algorithm_only_accepts_int_or_double_as_Type() + { + Mantid::Algorithms::AddTimeSeriesLog alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + const Mantid::Kernel::Property *prop = alg.getProperty("Type"); + const auto allowedValues = prop->allowedValues(); + + TS_ASSERT_EQUALS(2, allowedValues.size()); + TS_ASSERT_EQUALS(1, allowedValues.count("int")); + TS_ASSERT_EQUALS(1, allowedValues.count("double")); + } + + void test_delete_existing_removes_complete_log_first() + { + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:12", 20.0)); + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:12", 20.0, 0); + TS_ASSERT_THROWS_NOTHING(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:19", 40.0, Double, Delete)); + + checkLogWithEntryExists(ws, "Test Name", "2010-09-14T04:20:19", 40.0, 0); + } + + //-------------------------- Failure cases ------------------------------------ + void test_empty_log_name_not_allowed() + { + Mantid::Algorithms::AddTimeSeriesLog alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + TS_ASSERT_THROWS(alg.setPropertyValue("Name", ""), std::invalid_argument); + } + + void test_empty_time_not_allowed() + { + Mantid::Algorithms::AddTimeSeriesLog alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + TS_ASSERT_THROWS(alg.setPropertyValue("Time", ""), std::invalid_argument); + } + + void test_empty_value_not_allowed() + { + Mantid::Algorithms::AddTimeSeriesLog alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + TS_ASSERT_THROWS(alg.setPropertyValue("Value", ""), std::invalid_argument); + } + + void test_time_as_non_iso_formatted_string_throws_invalid_argument() + { + Mantid::Algorithms::AddTimeSeriesLog alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + TS_ASSERT_THROWS(alg.setPropertyValue("Time", "NotATime"), std::invalid_argument); + TS_ASSERT_THROWS(alg.setPropertyValue("Time", "2014 03 31 09 30"), std::invalid_argument); + TS_ASSERT_THROWS(alg.setPropertyValue("Time", "09:30:00"), std::invalid_argument); + } + + void test_algorithm_fails_if_log_exists_but_is_not_a_time_series() + { + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + auto & run = ws->mutableRun(); + run.addProperty("Test Name", 1.0); + TS_ASSERT_THROWS(executeAlgorithm(ws, "Test Name", "2010-09-14T04:20:12", 20.0), std::invalid_argument); + } + + void test_algorithm_fails_if_time_series_exists_but_it_is_incorrect_type() + { + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + auto & run = ws->mutableRun(); + const std::string logName = "DoubleSeries"; + auto *timeSeries = new Mantid::Kernel::TimeSeriesProperty(logName); + timeSeries->addValue("2010-09-14T04:20:12", 20.0); + run.addLogData(timeSeries); + TS_ASSERT_THROWS(executeAlgorithm(ws, logName, "2010-09-14T04:20:30", 30, Integer), std::invalid_argument); + } + +private: + + void executeAlgorithm(Mantid::API::MatrixWorkspace_sptr testWS, const std::string & logName, const std::string & logTime, + const double logValue, const LogType type = Double, const UpdateType update = Update) + { + //execute algorithm + Mantid::Algorithms::AddTimeSeriesLog alg; + alg.setChild(true); // not in ADS + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized() ) + + alg.setProperty("Workspace", testWS); + alg.setPropertyValue("Name", logName); + alg.setPropertyValue("Time", logTime); + alg.setProperty("Value", logValue); + if(type == Integer) alg.setProperty("Type", "int"); + if(update == Delete) alg.setProperty("DeleteExisting", true); + alg.setRethrows(true); + alg.execute(); + } + + template + void checkLogWithEntryExists(Mantid::API::MatrixWorkspace_sptr testWS, const std::string & logName, const std::string & logTime, + const T logValue, const size_t position) + { + using Mantid::Kernel::DateAndTime; + using Mantid::Kernel::TimeSeriesProperty; + + const auto & run = testWS->run(); + TSM_ASSERT("Run does not contain the expected log entry", run.hasProperty(logName)); + + auto *prop = run.getLogData(logName); + auto *timeSeries = dynamic_cast*>(prop); + TSM_ASSERT("A log entry with the given name exists but it is not a time series", timeSeries); + auto times = timeSeries->timesAsVector(); + TS_ASSERT(times.size() >= position + 1); + auto values = timeSeries->valuesAsVector(); + TS_ASSERT_EQUALS(DateAndTime(logTime), times[position]); + + TS_ASSERT(values.size() >= position + 1); + TS_ASSERT_EQUALS(logValue, values[position]); + } +}; + + +#endif /* MANTID_ALGORITHMS_ADDTIMESERIESLOGTEST_H_ */ diff --git a/Code/Mantid/Framework/Algorithms/test/DeleteLogTest.h b/Code/Mantid/Framework/Algorithms/test/DeleteLogTest.h new file mode 100644 index 000000000000..972b04161fa1 --- /dev/null +++ b/Code/Mantid/Framework/Algorithms/test/DeleteLogTest.h @@ -0,0 +1,90 @@ +#ifndef MANTID_ALGORITHMS_DELETELOGTEST_H_ +#define MANTID_ALGORITHMS_DELETELOGTEST_H_ + +#include + +#include "MantidAlgorithms/DeleteLog.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" + + +class DeleteLogTest : 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 DeleteLogTest *createSuite() { return new DeleteLogTest(); } + static void destroySuite( DeleteLogTest *suite ) { delete suite; } + + // -------------------------- Success tests -------------------------- + + void test_Init() + { + Mantid::Algorithms::DeleteLog alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_non_existant_log_does_not_throw_error() + { + Mantid::Algorithms::DeleteLog alg; + alg.initialize(); + alg.setChild(true); // no ADS storage + alg.setRethrows(true); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Name", "NotALog")); + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + alg.setProperty("Workspace", ws); + TS_ASSERT_THROWS_NOTHING(alg.execute()); + } + + void test_single_value_log_is_deleted() + { + Mantid::Algorithms::DeleteLog alg; + alg.initialize(); + alg.setChild(true); // no ADS storage + alg.setRethrows(true); + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + std::string logName("SingleValue"); + ws->mutableRun().addProperty(logName, 1.0); + alg.setProperty("Workspace", ws); + + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Name", logName)); + TS_ASSERT_THROWS_NOTHING(alg.execute()); + + TS_ASSERT(!ws->run().hasProperty(logName)); + } + + void test_time_series_log_is_deleted() + { + Mantid::Algorithms::DeleteLog alg; + alg.initialize(); + alg.setChild(true); // no ADS storage + alg.setRethrows(true); + auto ws = WorkspaceCreationHelper::Create2DWorkspace(10,10); + std::string logName("TimeSeries"); + + auto *tsp = new Mantid::Kernel::TimeSeriesProperty(logName); + tsp->addValue("2010-09-14T04:20:12", 20.0); + ws->mutableRun().addProperty(tsp); + alg.setProperty("Workspace", ws); + + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Name", logName)); + TS_ASSERT_THROWS_NOTHING(alg.execute()); + + TS_ASSERT(!ws->run().hasProperty(logName)); + } + + + // -------------------------- Failure tests -------------------------- + + void test_empty_log_name_throws_invalid_argument() + { + Mantid::Algorithms::DeleteLog alg; + alg.initialize(); + TS_ASSERT_THROWS(alg.setProperty("Name", ""), std::invalid_argument); + } + +}; + + +#endif /* MANTID_ALGORITHMS_DELETELOGTEST_H_ */ diff --git a/Code/Mantid/Framework/Crystal/CMakeLists.txt b/Code/Mantid/Framework/Crystal/CMakeLists.txt index 3792cfb33636..3eaaafa4f2dc 100644 --- a/Code/Mantid/Framework/Crystal/CMakeLists.txt +++ b/Code/Mantid/Framework/Crystal/CMakeLists.txt @@ -21,6 +21,7 @@ set ( SRC_FILES src/IndexPeaks.cpp src/IndexSXPeaks.cpp src/IntegratePeakTimeSlices.cpp + src/IntegratePeaksUsingClusters.cpp src/LatticeErrors.cpp src/LoadHKL.cpp src/LoadIsawPeaks.cpp @@ -31,6 +32,7 @@ set ( SRC_FILES src/OptimizeCrystalPlacement.cpp src/OptimizeExtinctionParameters.cpp src/OptimizeLatticeForCellType.cpp + src/PeakBackground.cpp src/PeakHKLErrors.cpp src/PeakIntegration.cpp src/PeakIntensityVsRadius.cpp @@ -83,6 +85,7 @@ set ( INC_FILES inc/MantidCrystal/IndexPeaks.h inc/MantidCrystal/IndexSXPeaks.h inc/MantidCrystal/IntegratePeakTimeSlices.h + inc/MantidCrystal/IntegratePeaksUsingClusters.h inc/MantidCrystal/LatticeErrors.h inc/MantidCrystal/LoadHKL.h inc/MantidCrystal/LoadIsawPeaks.h @@ -93,6 +96,7 @@ set ( INC_FILES inc/MantidCrystal/OptimizeCrystalPlacement.h inc/MantidCrystal/OptimizeExtinctionParameters.h inc/MantidCrystal/OptimizeLatticeForCellType.h + inc/MantidCrystal/PeakBackground.h inc/MantidCrystal/PeakHKLErrors.h inc/MantidCrystal/PeakIntegration.h inc/MantidCrystal/PeakIntensityVsRadius.h @@ -142,14 +146,16 @@ set ( TEST_FILES IndexPeaksTest.h IndexSXPeaksTest.h IntegratePeakTimeSlicesTest.h + IntegratePeaksUsingClustersTest.h LoadHKLTest.h LoadIsawPeaksTest.h - LoadIsawSpectrumTest.h + LoadIsawSpectrumTest.h LoadIsawUBTest.h MaskPeaksWorkspaceTest.h NormaliseVanadiumTest.h OptimizeCrystalPlacementTest.h OptimizeLatticeForCellTypeTest.h + PeakBackgroundTest.h PeakHKLErrorsTest.h PeakIntegrationTest.h PeakIntensityVsRadiusTest.h diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/BackgroundStrategy.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/BackgroundStrategy.h index 84d745d3dcb5..dce9474c8a41 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/BackgroundStrategy.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/BackgroundStrategy.h @@ -36,6 +36,7 @@ namespace Mantid public: virtual bool isBackground(Mantid::API::IMDIterator* const iterator) const = 0; virtual void configureIterator(Mantid::API::IMDIterator* const iterator) const = 0; + virtual BackgroundStrategy* clone() const = 0; virtual ~BackgroundStrategy() { } diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h index 0c5141545f4e..39efdadb9cf9 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h @@ -3,50 +3,107 @@ #include "MantidKernel/System.h" #include "MantidAPI/IMDHistoWorkspace.h" +#include "MantidCrystal/DisjointElement.h" #include +#include +#include namespace Mantid { -namespace Crystal -{ - class BackgroundStrategy; - /** ConnectedComponentLabelling : Implements connected component labeling on MDHistoWorkspaces. - - Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + namespace API + { + class Progress; + } + + namespace Crystal + { + /** + * Namespace containing useful typedefs + */ + namespace ConnectedComponentMappingTypes + { + typedef boost::tuple SignalErrorSQPair; + typedef std::map LabelIdIntensityMap; + typedef std::map PositionToLabelIdMap; + typedef std::vector VecIndexes; + typedef std::vector VecElements; + typedef std::set SetIds; + } - This file is part of Mantid. + class BackgroundStrategy; - 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. + /** ConnectedComponentLabelling : Implements connected component labeling on MDHistoWorkspaces. - 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. + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - You should have received a copy of the GNU General Public License - along with this program. If not, see . + This file is part of Mantid. - File change history is stored at: - Code Documentation is available at: - */ - class DLLExport ConnectedComponentLabeling - { - public: - ConnectedComponentLabeling(); - void startLabelingId(const size_t& id); - boost::shared_ptr execute(Mantid::API::IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy) const; - virtual ~ConnectedComponentLabeling(); - private: - size_t m_startId; - - }; - - -} // namespace Crystal + 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 ConnectedComponentLabeling + { + + public: + + /// Constructor + ConnectedComponentLabeling(const size_t&id = 1, const bool runMultiThreaded = true); + + /// Getter for the start label id + size_t getStartLabelId() const; + + /// Setter for the label id + void startLabelingId(const size_t& id); + + /// Execute and return clusters + boost::shared_ptr execute(Mantid::API::IMDHistoWorkspace_sptr ws, + BackgroundStrategy * const strategy, Mantid::API::Progress& progress) const; + + /// Execute and return clusters, as well as maps to integrated label values + boost::shared_ptr executeAndIntegrate( + Mantid::API::IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, + ConnectedComponentMappingTypes::LabelIdIntensityMap& labelMap, + ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap, + Mantid::API::Progress& progress) const; + + /// Destructor + virtual ~ConnectedComponentLabeling(); + + private: + + /// Get the number of threads to use. + int getNThreads() const; + + /// Calculate the disjoint element tree across the image. + void calculateDisjointTree(Mantid::API::IMDHistoWorkspace_sptr ws, + BackgroundStrategy * const strategy, std::vector& neighbourElements, + ConnectedComponentMappingTypes::LabelIdIntensityMap& labelMap, + ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap, + Mantid::API::Progress& progress) const; + + /// Start labeling index + size_t m_startId; + + /// Run multithreaded + const bool m_runMultiThreaded; + + }; + + } // namespace Crystal } // namespace Mantid #endif /* MANTID_CRYSTAL_CONNECTEDCOMPONENTLABELING_H_ */ diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h index a6a59b66ccdd..0b28badf01e6 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h @@ -57,6 +57,17 @@ namespace Crystal DisjointElement(const DisjointElement& other); /// Assignment operator. DisjointElement& operator=(const DisjointElement& other); + /// Less than + inline bool operator<(const DisjointElement& other) const + { + return m_id < other.getId(); + } + /// Greater than + inline bool operator>(const DisjointElement& other) const + { + return m_id > other.getId(); + } + private: bool hasParent() const; int compress(); diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/HardThresholdBackground.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/HardThresholdBackground.h index fcf8223077b9..4040e8e7f1e1 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/HardThresholdBackground.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/HardThresholdBackground.h @@ -35,15 +35,31 @@ namespace Crystal class DLLExport HardThresholdBackground : public BackgroundStrategy { public: + /// Contructor HardThresholdBackground(const double thresholdSignal, const Mantid::API::MDNormalization normalisation); + + /// Copy constructor + HardThresholdBackground(const HardThresholdBackground& other); + + /// Assignment operator + HardThresholdBackground& operator=(const HardThresholdBackground& other); + + /// Overriden isBackground virtual bool isBackground(Mantid::API::IMDIterator* iterator) const; + + /// Overriden configureIterator. void configureIterator(Mantid::API::IMDIterator* const iterator) const; + + /// Virtual constructor + virtual HardThresholdBackground* clone() const; + + /// Destructor virtual ~HardThresholdBackground(); private: /// Cutoff - const double m_thresholdSignal; + double m_thresholdSignal; /// Normalization - const Mantid::API::MDNormalization m_normalization; + Mantid::API::MDNormalization m_normalization; }; diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/IntegratePeaksUsingClusters.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/IntegratePeaksUsingClusters.h new file mode 100644 index 000000000000..87f970edd3c9 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/IntegratePeaksUsingClusters.h @@ -0,0 +1,56 @@ +#ifndef MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERS_H_ +#define MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERS_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ +namespace Crystal +{ + + /** IntegratePeaksUsingClusters : Uses clustering to integrate peaks. + + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport IntegratePeaksUsingClusters : public API::Algorithm + { + public: + IntegratePeaksUsingClusters(); + virtual ~IntegratePeaksUsingClusters(); + + 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 Crystal +} // namespace Mantid + +#endif /* MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERS_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h new file mode 100644 index 000000000000..97027b7fdaa3 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h @@ -0,0 +1,87 @@ +#ifndef MANTID_CRYSTAL_PEAKBACKGROUND_H_ +#define MANTID_CRYSTAL_PEAKBACKGROUND_H_ + +#include "MantidKernel/System.h" +#include "MantidKernel/V3D.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidAPI/IMDIterator.h" +#include "MantidAPI/IMDWorkspace.h" +#include "MantidCrystal/HardThresholdBackground.h" +#include + + + +namespace Mantid +{ +namespace API +{ + class IPeak; +} +namespace Crystal +{ + + /** PeakBackground : Extension of HardThresholdBackground to consider regions of the image as background if they are outside + the peaks radius limits (no mater what their theshold is). For pixels inside the radius, they must also be above the threshold value. + + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + + class DLLExport PeakBackground : public HardThresholdBackground + { + private: + + /// Peak workspace containing peaks of interest + Mantid::API::IPeaksWorkspace_const_sptr m_peaksWS; + /// Radius estimate + double m_radiusEstimate; + /// MD coordinates to use + Mantid::API::SpecialCoordinateSystem m_mdCoordinates; + /// Pointer to member function used for coordinate determination. + boost::function m_coordFunction; + + public: + /// Constructor + PeakBackground(Mantid::API::IPeaksWorkspace_const_sptr peaksWS, const double& radiusEstimate, const double& thresholdSignal, const Mantid::API::MDNormalization normalisation, const Mantid::API::SpecialCoordinateSystem coordinates); + + /// Copy constructor + PeakBackground(const PeakBackground& other); + + /// Assignment operator + PeakBackground& operator=(const PeakBackground& other); + + /// Overriden is background function + virtual bool isBackground(Mantid::API::IMDIterator* iterator) const; + + /// Overriden configure iterator function. + virtual void configureIterator(Mantid::API::IMDIterator* const iterator) const; + + /// Virutal constructor + virtual PeakBackground* clone() const; + + /// Destructor + virtual ~PeakBackground(); + }; + + +} // namespace Crystal +} // namespace Mantid + +#endif /* MANTID_CRYSTAL_PEAKBACKGROUND_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h index 4667e9f93720..6e31948d9640 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h @@ -197,7 +197,7 @@ namespace Crystal * */ static void updateSourceParams( - boost::shared_ptr bank_const, + boost::shared_ptr bank_const, boost::shared_ptr pmap, boost::shared_ptr pmapSv); diff --git a/Code/Mantid/Framework/Crystal/src/AnvredCorrection.cpp b/Code/Mantid/Framework/Crystal/src/AnvredCorrection.cpp index d418ce007d49..07ab8381d11e 100644 --- a/Code/Mantid/Framework/Crystal/src/AnvredCorrection.cpp +++ b/Code/Mantid/Framework/Crystal/src/AnvredCorrection.cpp @@ -1,20 +1,23 @@ /*WIKI* Following A.J.Schultz's anvred, the weight factors should be: -sin^2(theta) / (lamda^4 * spec * eff * trans) -where theta = scattering_angle/2 -lamda = wavelength (in angstroms?) -spec = incident spectrum correction -eff = pixel efficiency -trans = absorption correction + sin^2(theta) / (lamda^4 * spec * eff * trans) +where +* theta = scattering_angle/2 +* lamda = wavelength (in angstroms?) +* spec = incident spectrum correction +* eff = pixel efficiency +* trans = absorption correction The quantity: sin^2(theta) / eff depends only on the pixel and can be pre-calculated for each pixel. It could be saved in array pix_weight[]. + For now, pix_weight[] is calculated by the method: BuildPixWeights() and just holds the sin^2(theta) values. The wavelength dependent portion of the correction is saved in the array lamda_weight[]. + The time-of-flight is converted to wave length by multiplying by tof_to_lamda[id], then (int)STEPS_PER_ANGSTROM * lamda gives an index into the table lamda_weight[]. @@ -26,11 +29,10 @@ for the power should be determined when a good incident spectrum has been determined. Currently, power=3 when used with an incident spectrum and power=2.4 when used without an incident spectrum. + The pixel efficiency and incident spectrum correction are NOT CURRENTLY USED. The absorption correction, trans, depends on both lamda and the pixel, Which is a fairly expensive calulation when done for each event. --- - *WIKI*/ //---------------------------------------------------------------------- @@ -404,6 +406,11 @@ void AnvredCorrection::retrieveBaseProperties() Material mat("SetInAnvredCorrection", neutron, 1.0); m_inputWS->mutableSample().setMaterial(mat); } + if (smu != EMPTY_DBL() && amu != EMPTY_DBL()) + g_log.notice() << "LinearScatteringCoef = " << smu << " 1/cm\n" + << "LinearAbsorptionCoef = " << amu << " 1/cm\n" + << "Radius = " << radius << " cm\n" + << "Power Lorentz corrections = " << power_th << " \n"; // Call the virtual function for any further properties retrieveProperties(); } diff --git a/Code/Mantid/Framework/Crystal/src/ClearUB.cpp b/Code/Mantid/Framework/Crystal/src/ClearUB.cpp index 70481835be69..67a89e499efc 100644 --- a/Code/Mantid/Framework/Crystal/src/ClearUB.cpp +++ b/Code/Mantid/Framework/Crystal/src/ClearUB.cpp @@ -1,6 +1,6 @@ /*WIKI* - Clears the OrientedLattice of each ExperimentInfo attached to the intput [[Workspace]]. Works with both single ExperimentInfos and MultipleExperimentInfo instances. +Clears the OrientedLattice of each ExperimentInfo attached to the intput [[Workspace]]. Works with both single ExperimentInfos and MultipleExperimentInfo instances. *WIKI*/ diff --git a/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp b/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp index caf78d5a73ee..27ace0fcd6ce 100644 --- a/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp +++ b/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp @@ -1,14 +1,24 @@ -#include "MantidAPI/IMDHistoWorkspace.h" +#include "MantidKernel/MultiThreaded.h" +#include "MantidKernel/V3D.h" #include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/IMDHistoWorkspace.h" #include "MantidAPI/IMDIterator.h" +#include "MantidAPI/Progress.h" #include "MantidCrystal/ConnectedComponentLabeling.h" #include "MantidCrystal/BackgroundStrategy.h" #include "MantidCrystal/DisjointElement.h" #include +#include +#include #include #include +#include +#include using namespace Mantid::API; +using namespace Mantid::Kernel; +using namespace Mantid::Crystal::ConnectedComponentMappingTypes; namespace Mantid { @@ -16,140 +26,354 @@ namespace Mantid { namespace { - typedef std::vector VecIndexes; - typedef std::vector VecElements; - typedef std::set SetIds; + /** + * Perform integer power to determine the maximum number of face and edge connected + * neighbours for a given dimensionality + * @param ws : Workspace with dimensionality + * @return : Maximum number of possible neighbours + */ + size_t calculateMaxNeighbours(IMDHistoWorkspace const * const ws) + { + const size_t ndims = ws->getNumDims(); + size_t maxNeighbours = 3; + for(size_t i = 1; i < ndims; ++i) + { + maxNeighbours *= 3; + } + maxNeighbours -= 1; + return maxNeighbours; + } + + /** + * Helper non-member to clone the input workspace + * @param inWS: To clone + * @return : Cloned MDHistoWorkspace + */ + boost::shared_ptr cloneInputWorkspace(IMDHistoWorkspace_sptr& inWS) + { + auto alg = AlgorithmManager::Instance().createUnmanaged("CloneWorkspace"); + alg->initialize(); + alg->setChild(true); + alg->setProperty("InputWorkspace", inWS); + alg->setPropertyValue("OutputWorkspace", "out_ws"); + alg->execute(); + Mantid::API::IMDHistoWorkspace_sptr outWS; + { + Mantid::API::Workspace_sptr temp = alg->getProperty("OutputWorkspace"); + outWS = boost::dynamic_pointer_cast(temp); + } + return outWS; + } + + /** + * Helper function to calculate report frequecny + * @param maxReports : Maximum number of reports wanted + * @param maxIterations : Maximum number of possible iterations + * @return + */ + template + T reportEvery(const T& maxReports, const T& maxIterations) + { + T frequency = maxReports; + if (maxIterations >= maxReports) + { + frequency = maxIterations/maxReports; + } + return frequency; + } } - //---------------------------------------------------------------------------------------------- - /** Constructor + /** + * Constructor + * @param startId : Start Id to use for labeling + * @param runMultiThreaded : Run multi threaded. Defaults to true. */ - ConnectedComponentLabeling::ConnectedComponentLabeling() : m_startId(1) + ConnectedComponentLabeling::ConnectedComponentLabeling(const size_t& startId, const bool runMultiThreaded) + : m_startId(startId), m_runMultiThreaded(runMultiThreaded) { } /** - * Set a custom start id. This has no bearing on the output of the process other than - * the initial id used. - * @param id: Id to start with - */ + * Set a custom start id. This has no bearing on the output of the process other than + * the initial id used. + * @param id: Id to start with + */ void ConnectedComponentLabeling::startLabelingId(const size_t& id) { m_startId = id; } + /** + @return: The start label id. + */ + size_t ConnectedComponentLabeling::getStartLabelId() const + { + return m_startId; + } + //---------------------------------------------------------------------------------------------- /** Destructor - */ + */ ConnectedComponentLabeling::~ConnectedComponentLabeling() { } - boost::shared_ptr ConnectedComponentLabeling::execute( - IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy) const + /** + * Get the number of threads available + * @return : Number of available threads + */ + int ConnectedComponentLabeling::getNThreads() const { + return m_runMultiThreaded ? API::FrameworkManager::Instance().getNumOMPThreads() : 1; + } - auto alg = AlgorithmManager::Instance().create("CloneWorkspace"); - alg->initialize(); - alg->setChild(true); - alg->setProperty("InputWorkspace", ws); - alg->setPropertyValue("OutputWorkspace", "out_ws"); - alg->execute(); + /** + * Perform the work of the CCL algorithm + * - Pre filtering of background + * - Labeling using DisjointElements + * + * @param ws : MDHistoWorkspace to run CCL algorithm on + * @param strategy : Background strategy + * @param neighbourElements : Neighbour elements containing DisjointElements + * @param labelMap : Map of label id to signal, error_sq pair for integration purposes to fill + * @param positionLabelMap : Map of label ids to position in workspace coordinates to fill + * @param progress : Progress object + */ + void ConnectedComponentLabeling::calculateDisjointTree(IMDHistoWorkspace_sptr ws, + BackgroundStrategy * const strategy, VecElements& neighbourElements, + LabelIdIntensityMap& labelMap, + PositionToLabelIdMap& positionLabelMap, + Progress& progress + ) const + { + + VecIndexes allNonBackgroundIndexes; + allNonBackgroundIndexes.reserve(ws->getNPoints()); - Mantid::API::IMDHistoWorkspace_sptr out_ws; + progress.doReport("Pre-processing to filter background out"); + progress.resetNumSteps(100000, 0.0, 0.25); + if(m_runMultiThreaded) { - Mantid::API::Workspace_sptr temp = alg->getProperty("OutputWorkspace"); - out_ws = boost::dynamic_pointer_cast(temp); + std::vector iterators = ws->createIterators(getNThreads()); + const int nthreads = getNThreads(); + std::vector manyNonBackgroundIndexes(nthreads); + + PARALLEL_FOR_NO_WSP_CHECK() + for(int i = 0; i < nthreads; ++i) + { + boost::scoped_ptr strategyCopy(strategy->clone()); + API::IMDIterator *iterator = iterators[i]; + VecIndexes& nonBackgroundIndexes = manyNonBackgroundIndexes[i]; + do + { + if(!strategyCopy->isBackground(iterator)) + { + nonBackgroundIndexes.push_back( iterator->getLinearIndex() ); + progress.report(); + } + } + while(iterator->next()); + } + // Consolidate work from individual threads. + for(int i = 0; i < nthreads; ++i) + { + VecIndexes& source = manyNonBackgroundIndexes[i]; + allNonBackgroundIndexes.insert(allNonBackgroundIndexes.end(), source.begin(), source.end()); + } } - // zero-out output data. - for(size_t i = 0; i < out_ws->getNPoints(); ++i) + else { - out_ws->setSignalAt(i, 0); - out_ws->setErrorSquaredAt(i, 0); + progress.resetNumSteps(1, 0.0, 0.5); + API::IMDIterator *iterator = ws->createIterator(NULL); + do + { + if(!strategy->isBackground(iterator)) + { + allNonBackgroundIndexes.push_back( iterator->getLinearIndex() ); + progress.report(); + } + + } + while(iterator->next()); } + // -------- Perform labeling ----------- + progress.doReport("Perform connected component labeling"); + + const size_t maxNeighbours = calculateMaxNeighbours(ws.get()); IMDIterator* iterator = ws->createIterator(NULL); - - VecElements neighbourElements; - for(size_t i = 0; i < ws->getNPoints(); ++i) - { - neighbourElements.push_back(DisjointElement()); - } - size_t currentLabelCount = m_startId; - size_t currentIndex = 0; // We assume current index in the image can be kept in sync with the iterator. - do + const size_t nIndexesToProcess= allNonBackgroundIndexes.size(); + const size_t maxReports = 100; + const size_t frequency = reportEvery(maxReports, nIndexesToProcess); + progress.resetNumSteps(100, 0.25, 0.5); + for(size_t ii = 0; ii < nIndexesToProcess ; ++ii) { - if (!strategy->isBackground(iterator)) + if(ii % frequency == 0) { - // Linear indexes of neighbours - VecIndexes neighbourIndexes = iterator->findNeighbourIndexes(); - VecIndexes nonEmptyNeighbourIndexes; - SetIds neighbourIds; - // Discover non-empty neighbours - for (size_t i = 0; i < neighbourIndexes.size(); ++i) - { - size_t neighIndex = neighbourIndexes[i]; - const DisjointElement& neighbourElement = neighbourElements[neighIndex]; + progress.doReport(); + } + size_t& currentIndex = allNonBackgroundIndexes[ii]; + iterator->jumpTo(currentIndex); - if (!neighbourElement.isEmpty()) - { - nonEmptyNeighbourIndexes.push_back(neighIndex); - neighbourIds.insert(neighbourElement.getId()); - } - } + // Linear indexes of neighbours + VecIndexes neighbourIndexes = iterator->findNeighbourIndexes(); + VecIndexes nonEmptyNeighbourIndexes; + nonEmptyNeighbourIndexes.reserve(maxNeighbours); + SetIds neighbourIds; + // Discover non-empty neighbours + for (size_t i = 0; i < neighbourIndexes.size(); ++i) + { + size_t neighIndex = neighbourIndexes[i]; + const DisjointElement& neighbourElement = neighbourElements[neighIndex]; - if (nonEmptyNeighbourIndexes.empty()) + if (!neighbourElement.isEmpty()) { - neighbourElements[currentIndex] = DisjointElement(static_cast(currentLabelCount)); // New leaf - ++currentLabelCount; + nonEmptyNeighbourIndexes.push_back(neighIndex); + neighbourIds.insert(neighbourElement.getId()); } - else if (neighbourIds.size() == 1) // Do we have a single unique id amongst all neighbours. - { - neighbourElements[currentIndex] = neighbourElements[nonEmptyNeighbourIndexes.front()]; // Copy non-empty neighbour - } - else + } + + if (nonEmptyNeighbourIndexes.empty()) + { + neighbourElements[currentIndex] = DisjointElement(static_cast(currentLabelCount)); // New leaf + labelMap[currentLabelCount] = 0; // Pre-fill the currentlabelcount. + const VMD& center = iterator->getCenter(); + positionLabelMap[V3D(center[0], center[1], center[2])] = currentLabelCount; // Get the position at this label. + ++currentLabelCount; + } + else if (neighbourIds.size() == 1) // Do we have a single unique id amongst all neighbours. + { + neighbourElements[currentIndex] = neighbourElements[nonEmptyNeighbourIndexes.front()]; // Copy non-empty neighbour + } + else + { + // Choose the lowest neighbour index as the parent. + size_t parentIndex = nonEmptyNeighbourIndexes[0]; + for (size_t i = 1; i < nonEmptyNeighbourIndexes.size(); ++i) { - // Choose the lowest neighbour index as the parent. - size_t parentIndex = nonEmptyNeighbourIndexes[0]; - for (size_t i = 1; i < nonEmptyNeighbourIndexes.size(); ++i) + size_t neighIndex = nonEmptyNeighbourIndexes[i]; + if (neighbourElements[neighIndex].getId() < neighbourElements[parentIndex].getId()) { - size_t neighIndex = nonEmptyNeighbourIndexes[i]; - if (neighbourElements[neighIndex].getId() < neighbourElements[parentIndex].getId()) - { - parentIndex = i; - } + parentIndex = i; } - // Get the chosen parent - DisjointElement& parentElement = neighbourElements[parentIndex]; - // Make this element a copy of the parent - neighbourElements[currentIndex] = parentElement; - // Union remainder parents with the chosen parent - for (size_t i = 0; i < nonEmptyNeighbourIndexes.size(); ++i) + } + // Get the chosen parent + DisjointElement& parentElement = neighbourElements[parentIndex]; + // Union remainder parents with the chosen parent + for (size_t i = 0; i < nonEmptyNeighbourIndexes.size(); ++i) + { + size_t neighIndex = nonEmptyNeighbourIndexes[i]; + if (neighIndex != parentIndex) { - size_t neighIndex = nonEmptyNeighbourIndexes[i]; - if (neighIndex != parentIndex) - { - neighbourElements[neighIndex].unionWith(&parentElement); - } + neighbourElements[neighIndex].unionWith(&parentElement); } - } + + } + } + + } + + /** + * Execute CCL to produce a cluster output workspace containing labels + * @param ws : Workspace to perform CCL on + * @param strategy : Background strategy + * @param progress : Progress object + * @return Cluster output workspace of results + */ + boost::shared_ptr ConnectedComponentLabeling::execute( + IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, Progress& progress) const + { + VecElements neighbourElements(ws->getNPoints()); + + // Perform the bulk of the connected component analysis, but don't collapse the elements yet. + LabelIdIntensityMap labelMap; // This will not get used. + PositionToLabelIdMap positionLabelMap; // This will not get used. + calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap, progress); + + // Create the output workspace from the input workspace + IMDHistoWorkspace_sptr outWS = cloneInputWorkspace(ws); + + progress.doReport("Generating cluster image"); + const int nIndexesToProcess = static_cast(neighbourElements.size()); + progress.resetNumSteps(nIndexesToProcess, 0.5, 0.75); + // Set each pixel to the root of each disjointed element. + PARALLEL_FOR_NO_WSP_CHECK() + for (int i = 0; i < nIndexesToProcess; ++i) + { + if(!neighbourElements[i].isEmpty()) + { + outWS->setSignalAt(i, neighbourElements[i].getRoot()); + progress.doReport(); } - ++currentIndex; - } while (iterator->next()); + else + { + outWS->setSignalAt(i, 0); + } + outWS->setErrorSquaredAt(i, 0); + + } + return outWS; + } + + /** + * Execute and integrate + * @param ws : Image workspace to integrate + * @param strategy : Background strategy + * @param labelMap : Label map to fill. Label ids to integrated signal and errorsq for that label + * @param positionLabelMap : Label ids to position in workspace coordinates. This is filled as part of the work. + * @param progress : Progress object + * @return Image Workspace containing clusters. + */ + boost::shared_ptr ConnectedComponentLabeling::executeAndIntegrate( + IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, LabelIdIntensityMap& labelMap, + PositionToLabelIdMap& positionLabelMap, Progress& progress) const + { + VecElements neighbourElements(ws->getNPoints()); + + // Perform the bulk of the connected component analysis, but don't collapse the elements yet. + calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap, progress); + + // Create the output workspace from the input workspace + IMDHistoWorkspace_sptr outWS = cloneInputWorkspace(ws); + + progress.doReport("Integrating clusters and generating cluster image"); + const size_t nIterations = neighbourElements.size(); + const size_t maxReports = 1000; + const size_t frequency = reportEvery(maxReports, nIterations); + progress.resetNumSteps(maxReports, 0.5, 0.75); // Set each pixel to the root of each disjointed element. - for (size_t i = 0; i < neighbourElements.size(); ++i) + for (size_t i = 0; i < nIterations; ++i) { - //std::cout << "Element\t" << i << " Id: \t" << neighbourElements[i].getId() << " This location:\t"<< &neighbourElements[i] << " Root location:\t" << neighbourElements[i].getParent() << " Root Id:\t" << neighbourElements[i].getRoot() << std::endl; if(!neighbourElements[i].isEmpty()) { - out_ws->setSignalAt(i, neighbourElements[i].getRoot()); + const double& signal = ws->getSignalAt(i); // Intensity value at index + double errorSQ = ws->getErrorAt(i); + errorSQ *=errorSQ; // Error squared at index + const size_t& labelId = neighbourElements[i].getRoot(); + // Set the output cluster workspace signal value + outWS->setSignalAt(i, static_cast(labelId)); + + SignalErrorSQPair current = labelMap[labelId]; + // Sum labels. This is integration! + labelMap[labelId] = SignalErrorSQPair(current.get<0>() + signal, current.get<1>() + errorSQ); + + outWS->setSignalAt(i, neighbourElements[i].getRoot()); + } + else + { + outWS->setSignalAt(i, 0); + } + outWS->setErrorSquaredAt(i, 0); + if(i % frequency == 0) + { + progress.doReport(); } } - return out_ws; + return outWS; } } // namespace Crystal diff --git a/Code/Mantid/Framework/Crystal/src/DisjointElement.cpp b/Code/Mantid/Framework/Crystal/src/DisjointElement.cpp index 7bbc6cca6d6d..3e4c03848f2f 100644 --- a/Code/Mantid/Framework/Crystal/src/DisjointElement.cpp +++ b/Code/Mantid/Framework/Crystal/src/DisjointElement.cpp @@ -37,11 +37,7 @@ namespace Mantid DisjointElement::DisjointElement(const DisjointElement& other) : m_parent(other.m_parent), m_rank(other.m_rank), m_id(other.m_id) { - if (m_rank > 0) - { - throw std::logic_error( - "This is a parent node. Children cannot be copied, leading to possible inconsistencies."); - } + // Don't point to copy object as parent if copy object is it's own parent. if (other.m_parent == &other) { @@ -59,11 +55,6 @@ namespace Mantid if (this != &other) { - if (other.m_rank > 0) - { - throw std::logic_error( - "This is a parent node. Children cannot be copied, leading to possible inconsistencies."); - } m_parent = other.m_parent; m_rank = other.m_rank; @@ -183,10 +174,7 @@ namespace Mantid void DisjointElement::unionWith(DisjointElement* other) { - if (this->getId() == other->getId()) - { - throw std::logic_error("Trying to union two elements with the same Id"); - } + if (other->getRoot() != this->getRoot()) // Check sets do not already have the same root before continuing { diff --git a/Code/Mantid/Framework/Crystal/src/GoniometerAnglesFromPhiRotation.cpp b/Code/Mantid/Framework/Crystal/src/GoniometerAnglesFromPhiRotation.cpp index 8806257d2192..d5bd9a555995 100644 --- a/Code/Mantid/Framework/Crystal/src/GoniometerAnglesFromPhiRotation.cpp +++ b/Code/Mantid/Framework/Crystal/src/GoniometerAnglesFromPhiRotation.cpp @@ -1,11 +1,11 @@ /*WIKI* - This algorithm is used for finding Goniometer angles when instrument readings are basically unknown. - The inputs are two PeaksWorkspaces corresponding to sample orientations of the SAME crystal - that differ only in their phi rotation. +This algorithm is used for finding Goniometer angles when instrument readings are basically unknown. +The inputs are two PeaksWorkspaces corresponding to sample orientations of the SAME crystal +that differ only in their phi rotation. - If the phi angles are known, this algorithm attempts to find the common chi and omega rotations. +If the phi angles are known, this algorithm attempts to find the common chi and omega rotations. *WIKI*/ diff --git a/Code/Mantid/Framework/Crystal/src/HardThresholdBackground.cpp b/Code/Mantid/Framework/Crystal/src/HardThresholdBackground.cpp index 3a0a5afb7638..128ce0cb0c4b 100644 --- a/Code/Mantid/Framework/Crystal/src/HardThresholdBackground.cpp +++ b/Code/Mantid/Framework/Crystal/src/HardThresholdBackground.cpp @@ -21,6 +21,27 @@ namespace Crystal HardThresholdBackground::~HardThresholdBackground() { } + + HardThresholdBackground::HardThresholdBackground(const HardThresholdBackground& other) : + m_thresholdSignal(other.m_thresholdSignal), m_normalization(other.m_normalization) + { + } + + HardThresholdBackground* HardThresholdBackground::clone() const + { + return new HardThresholdBackground(*this); + } + + + HardThresholdBackground& HardThresholdBackground::operator=(const HardThresholdBackground& other) + { + if(&other != this) + { + m_thresholdSignal = other.m_thresholdSignal; + m_normalization = other.m_normalization; + } + return *this; + } void HardThresholdBackground::configureIterator(Mantid::API::IMDIterator* const iterator) const { diff --git a/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp b/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp index b412e5ed280b..273211ee5a43 100644 --- a/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp +++ b/Code/Mantid/Framework/Crystal/src/IntegratePeakTimeSlices.cpp @@ -850,7 +850,7 @@ namespace Mantid Q = peak.getQLabFrame().norm(); Geometry::Instrument_const_sptr instr = peak.getInstrument(); - const Geometry::IObjComponent_const_sptr sample = instr->getSample(); + const Geometry::IComponent_const_sptr sample = instr->getSample(); V3D pos = peak.getDetPos()-sample->getPos(); ScatAngle = acos(pos.Z() / pos.norm()); diff --git a/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp new file mode 100644 index 000000000000..065563200818 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp @@ -0,0 +1,208 @@ +/*WIKI* +Integrates arbitary shaped single crystal peaks defined on an [[MDHistoWorkspace]] using connected component analysis to determine +regions of interest around each peak of the [[PeaksWorkspace]]. The output is an integrated [[PeaksWorkspace]] as well as an image +containing the labels assigned to each cluster for diagnostic and visualisation purposes. + +A threshold for the Peak should be defined below which, parts of the image are treated as background. In addition, a radius estimate +is required to dispose of those clusters which are not to do with peaks, and also to associate clusters in the image with a peak center. +You can view the radius estimate as a radius cut-off. + +This algorithm uses an imaging technique, and it is therefore important that the MDHistoWorkspace you are using is binned to a sufficient +resolution via [[BinMD]]. You can overlay the intergrated peaks workspace in the [[MantidPlot:_SliceViewer#Viewing_Peaks_Workspaces|Slice Viewer]] over +the generated Cluster Labeled OutputWorkspaceMD to see what the interation region used for each peak amounts to. +*WIKI*/ + +#include "MantidCrystal/IntegratePeaksUsingClusters.h" +#include "MantidCrystal/ConnectedComponentLabeling.h" +#include "MantidCrystal/PeakBackground.h" +#include "MantidAPI/IMDHistoWorkspace.h" +#include "MantidAPI/WorkspaceProperty.h" +#include "MantidAPI/IMDIterator.h" +#include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/Progress.h" +#include "MantidKernel/MultiThreaded.h" +#include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/MandatoryValidator.h" +#include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/ListValidator.h" +#include "MantidKernel/Utils.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include +#include +#include +#include + +using namespace Mantid::API; +using namespace Mantid::Kernel; +using namespace Mantid::DataObjects; +using namespace Mantid::Crystal::ConnectedComponentMappingTypes; + +namespace +{ + + + class IsNearPeak + { + public: + IsNearPeak(const V3D& coordinates, const double& thresholdDistance ) : m_coordinates(coordinates), m_thresholdDistance(thresholdDistance) + {} + bool operator()( const PositionToLabelIdMap::value_type& v ) const + { + return v.first.distance(m_coordinates) < m_thresholdDistance; + } + private: + const V3D m_coordinates; + const double m_thresholdDistance; + }; + +} + +namespace Mantid +{ + namespace Crystal + { + + // Register the algorithm into the AlgorithmFactory + DECLARE_ALGORITHM(IntegratePeaksUsingClusters) + + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + IntegratePeaksUsingClusters::IntegratePeaksUsingClusters() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + IntegratePeaksUsingClusters::~IntegratePeaksUsingClusters() + { + } + + + //---------------------------------------------------------------------------------------------- + /// Algorithm's name for identification. @see Algorithm::name + const std::string IntegratePeaksUsingClusters::name() const { return "IntegratePeaksUsingClusters";}; + + /// Algorithm's version for identification. @see Algorithm::version + int IntegratePeaksUsingClusters::version() const { return 1;}; + + /// Algorithm's category for identification. @see Algorithm::category + const std::string IntegratePeaksUsingClusters::category() const { return "MDAlgorithms";} + + //---------------------------------------------------------------------------------------------- + /// Sets documentation strings for this algorithm + void IntegratePeaksUsingClusters::initDocs() + { + this->setWikiSummary("Integrate single crystal peaks using connected component analysis"); + this->setOptionalMessage(this->getWikiSummary()); + } + + //---------------------------------------------------------------------------------------------- + /** Initialize the algorithm's properties. + */ + void IntegratePeaksUsingClusters::init() + { + declareProperty(new WorkspaceProperty("InputWorkspace","",Direction::Input), "Input md workspace."); + declareProperty(new WorkspaceProperty("PeaksWorkspace","", Direction::Input),"A PeaksWorkspace containing the peaks to integrate."); + + auto positiveValidator = boost::make_shared >(); + positiveValidator->setLower(0); + + auto compositeValidator = boost::make_shared(); + compositeValidator->add(positiveValidator); + compositeValidator->add(boost::make_shared >()); + + declareProperty(new PropertyWithValue("RadiusEstimate", 0.0, compositeValidator, Direction::Input), "Estimate of Peak Radius. Points beyond this radius will not be considered, so caution towards the larger end."); + + declareProperty(new PropertyWithValue("Threshold", 0, positiveValidator->clone(), Direction::Input), "Threshold signal above which to consider peaks"); + declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), "An output integrated peaks workspace."); + declareProperty(new WorkspaceProperty("OutputWorkspaceMD","",Direction::Output), "MDHistoWorkspace containing the labeled clusters used by the algorithm."); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. + */ + void IntegratePeaksUsingClusters::exec() + { + IMDHistoWorkspace_sptr mdWS = getProperty("InputWorkspace"); + IPeaksWorkspace_sptr inPeakWS = getProperty("PeaksWorkspace"); + IPeaksWorkspace_sptr peakWS = getProperty("OutputWorkspace"); + if (peakWS != inPeakWS) + { + auto cloneAlg = createChildAlgorithm("CloneWorkspace"); + cloneAlg->setProperty("InputWorkspace", inPeakWS); + cloneAlg->setPropertyValue("OutputWorkspace", "out_ws"); + cloneAlg->execute(); + { + Workspace_sptr temp = cloneAlg->getProperty("OutputWorkspace"); + peakWS = boost::dynamic_pointer_cast(temp); + } + } + + const SpecialCoordinateSystem mdCoordinates = mdWS->getSpecialCoordinateSystem(); + if(mdCoordinates == None) + { + throw std::invalid_argument("The coordinate system of the input MDWorkspace cannot be established. Run SetSpecialCoordinates on InputWorkspace."); + } + + const double threshold = getProperty("Threshold"); + const double radiusEstimate = getProperty("RadiusEstimate"); + PeakBackground backgroundStrategy(peakWS, radiusEstimate, threshold, NoNormalization, mdCoordinates); + //HardThresholdBackground backgroundStrategy(threshold,NoNormalization); + + ConnectedComponentLabeling analysis; + LabelIdIntensityMap labelMap; + PositionToLabelIdMap positionMap; + + Progress progress(this, 0, 1, 1); + IMDHistoWorkspace_sptr clusters = analysis.executeAndIntegrate(mdWS, &backgroundStrategy, labelMap, positionMap, progress); + + // Link integrated values up with peaks. + const int nPeaks = peakWS->getNumberPeaks(); + progress.resetNumSteps(nPeaks, 0, 1); + progress.doReport("Writing out PeaksWorkspace"); + PARALLEL_FOR1(peakWS) + for(int i =0; i < nPeaks; ++i) + { + PARALLEL_START_INTERUPT_REGION + IPeak& peak = peakWS->getPeak(i); + V3D coords; + if(mdCoordinates==QLab) + { + coords= peakWS->getPeak(i).getQLabFrame(); + } + else if(mdCoordinates==QSample) + { + coords= peakWS->getPeak(i).getQSampleFrame(); + } + else if(mdCoordinates==Mantid::API::HKL) + { + coords= peakWS->getPeak(i).getHKL(); + } + + /* Now find the label corresponding to these coordinates. Use the characteristic coordinates of the coordinates + recorded earlier to do this. A better implemention would be a direct lookup. + */ + IsNearPeak nearPeak(coords, radiusEstimate); + auto iterator = std::find_if(positionMap.begin(), positionMap.end(), nearPeak); + if(iterator != positionMap.end()) + { + peak.setIntensity(labelMap[ iterator->second ].get<0>()); + peak.setSigmaIntensity(labelMap[ iterator->second ].get<1>()); + } + progress.report(); + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + + setProperty("OutputWorkspace", peakWS); + setProperty("OutputWorkspaceMD", clusters); + } + + + + } // namespace Crystal +} // namespace Mantid diff --git a/Code/Mantid/Framework/Crystal/src/OptimizeCrystalPlacement.cpp b/Code/Mantid/Framework/Crystal/src/OptimizeCrystalPlacement.cpp index d0e6555a976a..80c45424052a 100644 --- a/Code/Mantid/Framework/Crystal/src/OptimizeCrystalPlacement.cpp +++ b/Code/Mantid/Framework/Crystal/src/OptimizeCrystalPlacement.cpp @@ -17,12 +17,12 @@ that slowly build a UB with corrected sample orientations may be needed. -The parameters for the tilt are GonRotx, GonRoty, and GonRotz in degrees. The usage for this information is as follows: rotate('x',GonRotx)*rotate('y',GonRoty)*rotate('z',GonRotz)* SampleOrientation( i.e. omegaRot*chiRot*phiRot)). - -Note: To optimize by the tilt in the goniometer and then by the angles or by the sample position, it is possible to - run with one optimization, then using the resultant PeaksWorkspace for input, run another optimization. +-Note: To optimize by the tilt in the goniometer and then by the angles or by the sample position, it is possible to +run with one optimization, then using the resultant PeaksWorkspace for input, run another optimization. - Rerunning the same optimization with the result is also a good idea. If the first guess is very close, the optimize algorithm - does try cases far away and may not get back to the best value. Check the chisquared values. If they increase, that optimization - should probably not be used. +Rerunning the same optimization with the result is also a good idea. If the first guess is very close, the optimize algorithm +does try cases far away and may not get back to the best value. Check the chisquared values. If they increase, that optimization +should probably not be used. *WIKI*/ /* diff --git a/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp b/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp new file mode 100644 index 000000000000..4c935e4e851c --- /dev/null +++ b/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp @@ -0,0 +1,101 @@ +#include "MantidCrystal/PeakBackground.h" +#include "MantidAPI/IPeak.h" +#include +#include + +using namespace Mantid::API; +using namespace Mantid::Kernel; +using Mantid::API::IPeak; + +namespace Mantid +{ + namespace Crystal + { + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + PeakBackground::PeakBackground(IPeaksWorkspace_const_sptr peaksWS, const double& radiusEstimate, const double& thresholdSignal, const Mantid::API::MDNormalization normalisation, const SpecialCoordinateSystem coordinates) + : HardThresholdBackground(thresholdSignal, normalisation), m_peaksWS(peaksWS), m_radiusEstimate(radiusEstimate), m_mdCoordinates(coordinates) + { + + if(m_mdCoordinates==QLab) + { + m_coordFunction = &IPeak::getQLabFrame; + } + else if(m_mdCoordinates==QSample) + { + m_coordFunction = &IPeak::getQSampleFrame; + } + else if(m_mdCoordinates==Mantid::API::HKL) + { + m_coordFunction = &IPeak::getHKL; + } + else + { + throw std::invalid_argument("Unknown CoordinateSystem provided to PeakBackground"); + } + } + + PeakBackground::PeakBackground(const PeakBackground& other) + : HardThresholdBackground(other), m_peaksWS(other.m_peaksWS), m_radiusEstimate(other.m_radiusEstimate) + , m_mdCoordinates(other.m_mdCoordinates), m_coordFunction(other.m_coordFunction) + { + } + + PeakBackground& PeakBackground::operator=(const PeakBackground& other) + { + if(this != &other) + { + HardThresholdBackground::operator=(other); + m_peaksWS = other.m_peaksWS; + m_radiusEstimate = other.m_radiusEstimate; + m_mdCoordinates = other.m_mdCoordinates; + m_coordFunction = other.m_coordFunction; + } + return *this; + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + PeakBackground::~PeakBackground() + { + } + + /// Virutal constructor + PeakBackground* PeakBackground::clone() const + { + return new PeakBackground(*this); + } + + + bool PeakBackground::isBackground(Mantid::API::IMDIterator* iterator) const + { + if(!HardThresholdBackground::isBackground(iterator) ) + { + const VMD& center = iterator->getCenter(); + V3D temp(center[0], center[1], center[2]); // This assumes dims 1, 2, and 3 in the workspace correspond to positions. + + for(int i = 0; i < m_peaksWS->getNumberPeaks(); ++i) + { + const IPeak& peak = m_peaksWS->getPeak(i); + V3D coords = m_coordFunction(&peak); + if(coords.distance(temp) < m_radiusEstimate) + { + return false; + } + + } + + } + return true; + } + + void PeakBackground::configureIterator(Mantid::API::IMDIterator* const ) const + { + } + +} // namespace Crystal +} // namespace Mantid \ No newline at end of file diff --git a/Code/Mantid/Framework/Crystal/src/PeakHKLErrors.cpp b/Code/Mantid/Framework/Crystal/src/PeakHKLErrors.cpp index 7b571a31c02b..28ade44086e0 100644 --- a/Code/Mantid/Framework/Crystal/src/PeakHKLErrors.cpp +++ b/Code/Mantid/Framework/Crystal/src/PeakHKLErrors.cpp @@ -65,6 +65,7 @@ using namespace Mantid::API; using namespace Mantid::Kernel; using Mantid::Geometry::CompAssembly; using Mantid::Geometry::IObjComponent_const_sptr; +using Mantid::Geometry::IComponent_const_sptr; namespace Mantid { @@ -263,7 +264,7 @@ namespace Mantid //------------------"clone" orig instruments pmap ------------------- cLone( pmap, instSave, pmapSv ); - IObjComponent_const_sptr sample = instChange->getSample(); + IComponent_const_sptr sample = instChange->getSample(); V3D sampPos = sample->getRelativePos(); V3D sampOffsets( getParameter( "SampleXOffset" ), getParameter( "SampleYOffset" ), getParameter( "SampleZOffset" ) ); diff --git a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp index 76ede26f04b1..0e7ff0b27a74 100644 --- a/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp +++ b/Code/Mantid/Framework/Crystal/src/SCDCalibratePanels.cpp @@ -1143,7 +1143,7 @@ namespace Mantid double mL1; stringstream(line) >> count >> mL1 >> T0; double scaleL0= .01*mL1/beamlineLen; - const IObjComponent_const_sptr source=instrument->getSource(); + const IComponent_const_sptr source=instrument->getSource(); V3D NewSourcePos= samplePos-beamline*scaleL0*2.0;//beamLine is 2*length. L0=beamline.norm()*scaleL0*2.0; V3D RelSourcePos = source->getRelativePos()+NewSourcePos-source->getPos(); @@ -1615,7 +1615,7 @@ namespace Mantid } - void SCDCalibratePanels::updateSourceParams(boost::shared_ptr bank_const, + void SCDCalibratePanels::updateSourceParams(boost::shared_ptr bank_const, boost::shared_ptr pmap, boost::shared_ptr pmapSv) { vector< V3D > posv = pmapSv->getV3D(bank_const->getName(), "pos"); @@ -1640,10 +1640,10 @@ namespace Mantid boost::shared_ptr const pmapOld) { boost::shared_ptr pmap = NewInstrument->getParameterMap(); - IObjComponent_const_sptr source = NewInstrument->getSource(); + IComponent_const_sptr source = NewInstrument->getSource(); updateSourceParams(source, pmap, pmapOld); - IObjComponent_const_sptr sample = NewInstrument->getSample(); + IComponent_const_sptr sample = NewInstrument->getSample(); V3D SamplePos = sample->getPos(); if( SamplePos != newSampPos) { @@ -1799,10 +1799,10 @@ namespace Mantid } // for each group // write out the source - IObjComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr source = instrument->getSource(); oss3 << "getName() << "\">" << endl; - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr sample = instrument->getSample(); V3D sourceRelPos = source->getRelativePos(); writeXmlParameter(oss3, "x", sourceRelPos.X()); diff --git a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp index 34309d799a65..edb7d4fe4308 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp @@ -341,7 +341,7 @@ namespace Crystal double mu = (9.614 * lambda) + 0.266; // mu for GS20 glass double depth = 0.2; double eff_center = 1.0 - std::exp(-mu * depth); // efficiency at center of detector - IObjComponent_const_sptr sample = ws->getInstrument()->getSample(); + IComponent_const_sptr sample = ws->getInstrument()->getSample(); double cosA = ws->getInstrument()->getComponentByName(p.getBankName())->getDistance(*sample) / p.getL2(); double pathlength = depth / cosA; double eff_R = 1.0 - exp(-mu * pathlength); // efficiency at point R diff --git a/Code/Mantid/Framework/Crystal/src/ShowPeakHKLOffsets.cpp b/Code/Mantid/Framework/Crystal/src/ShowPeakHKLOffsets.cpp index 473e82bfb0c7..146afed5768c 100644 --- a/Code/Mantid/Framework/Crystal/src/ShowPeakHKLOffsets.cpp +++ b/Code/Mantid/Framework/Crystal/src/ShowPeakHKLOffsets.cpp @@ -1,9 +1,9 @@ /*WIKI* - Creates a TableWorkspace with offsets of h,k,and l from an integer along with bank and run number. +Creates a TableWorkspace with offsets of h,k,and l from an integer along with bank and run number. - The maximum of these offsets is also included. +The maximum of these offsets is also included. - Histograms, scatterplots, etc. of this data can be used to detect problems. +Histograms, scatterplots, etc. of this data can be used to detect problems. *WIKI*/ #include "MantidDataObjects/PeaksWorkspace.h" diff --git a/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h b/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h index 390d573d7b56..0311f9eb19c7 100644 --- a/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h +++ b/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h @@ -10,6 +10,7 @@ #include "MantidAPI/IMDIterator.h" #include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/Progress.h" #include "MantidCrystal/ConnectedComponentLabeling.h" #include "MantidCrystal/BackgroundStrategy.h" #include "MantidCrystal/HardThresholdBackground.h" @@ -61,6 +62,10 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite public: MOCK_CONST_METHOD1(configureIterator, void(Mantid::API::IMDIterator* const)); MOCK_CONST_METHOD1(isBackground, bool(Mantid::API::IMDIterator* const)); + MockBackgroundStrategy* clone() const + { + throw std::runtime_error("Cannot clone the mock object"); + } virtual ~MockBackgroundStrategy() {} }; @@ -80,6 +85,20 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite FrameworkManager::Instance(); } + void test_default_start_label_id() + { + ConnectedComponentLabeling ccl; + TSM_ASSERT_EQUALS("Start Label Id should be 1 by default", 1, ccl.getStartLabelId()); + } + + void test_set_get_start_label_id() + { + ConnectedComponentLabeling ccl; + const size_t startLabelId = 10; + ccl.startLabelingId(startLabelId); + TS_ASSERT_EQUALS(startLabelId, ccl.getStartLabelId()) + } + void test_1d_one_node() { IMDHistoWorkspace_sptr inWS = MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1, 1); // Single node. Simpliest possible test case @@ -87,10 +106,13 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite MockBackgroundStrategy mockStrategy; EXPECT_CALL(mockStrategy, isBackground(_)).Times(static_cast(inWS->getNPoints())).WillRepeatedly(Return(false));// A filter that passes everything. - ConnectedComponentLabeling ccl; size_t labelingId = 1; + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); auto uniqueValues = connection_workspace_to_set_of_labels(outWS.get()); TS_ASSERT_EQUALS(1, uniqueValues.size()); @@ -106,10 +128,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite MockBackgroundStrategy mockStrategy; EXPECT_CALL(mockStrategy, isBackground(_)).Times(static_cast(inWS->getNPoints())).WillRepeatedly(Return(false));// A filter that passes everything. - ConnectedComponentLabeling ccl; size_t labelingId = 2; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); /* * Because all the signal values are identical, and none are below any threshold. We assume that there will only be a single component. All @@ -137,10 +160,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite .WillOnce(Return(true)) // is background .WillRepeatedly(Return(false)); - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + Progress prog; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("2 objects so should have 3 unique entries", 3, uniqueEntries.size()); @@ -167,10 +191,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite .WillOnce(Return(true))// is background .WillOnce(Return(false)); - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("3 objects so should have 4 unique entries", 4, uniqueEntries.size()); @@ -189,10 +214,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite MockBackgroundStrategy mockStrategy; EXPECT_CALL(mockStrategy, isBackground(_)).WillRepeatedly(Return(false));// Nothing is treated as background - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object", 1, uniqueEntries.size()); @@ -220,10 +246,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite .WillOnce(Return(false)) .WillOnce(Return(true)); - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object, but we have some 'empty' entries too", 2, uniqueEntries.size()); @@ -252,10 +279,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite .WillOnce(Return(false)).WillOnce(Return(true)).WillOnce(Return(false)) .WillOnce(Return(true)).WillOnce(Return(false)).WillOnce(Return(true)); - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object, but we have some 'empty' entries too", 2, uniqueEntries.size()); @@ -312,10 +340,11 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite // ---------- Run the cluster finding HardThresholdBackground strategy(backgroundSignal, NoNormalization); - ConnectedComponentLabeling ccl; size_t labelingId = 1; - ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &strategy); + bool multiThreaded = false; + ConnectedComponentLabeling ccl(labelingId, multiThreaded); + Progress prog; + auto outWS = ccl.execute(inWS, &strategy, prog); // ----------- Basic cluster checks @@ -399,7 +428,8 @@ class ConnectedComponentLabelingTestPerformance: public CxxTest::TestSuite ConnectedComponentLabeling ccl; size_t labelingId = 1; ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(m_inWS, m_backgroundStrategy.get()); + Progress prog; + auto outWS = ccl.execute(m_inWS, m_backgroundStrategy.get(), prog); // ----------- Basic cluster checks diff --git a/Code/Mantid/Framework/Crystal/test/DisjointElementTest.h b/Code/Mantid/Framework/Crystal/test/DisjointElementTest.h index a9aab6f67b42..43ce3b8d5cdc 100644 --- a/Code/Mantid/Framework/Crystal/test/DisjointElementTest.h +++ b/Code/Mantid/Framework/Crystal/test/DisjointElementTest.h @@ -40,15 +40,6 @@ class DisjointElementTest : public CxxTest::TestSuite TS_ASSERT_DIFFERS(item.getParent(), copy.getParent()); } - void test_copy_throws() - { - DisjointElement item1(1); - DisjointElement item2(2); - item1.unionWith(&item2); - - TSM_ASSERT_THROWS("Cannot copy parent",DisjointElement copy = item2, std::logic_error&) - } - void test_assign() { DisjointElement a(1); @@ -58,16 +49,6 @@ class DisjointElementTest : public CxxTest::TestSuite TS_ASSERT_DIFFERS(a.getParent(), b.getParent()); } - void test_assign_throws() - { - DisjointElement item1(1); - DisjointElement item2(2); - DisjointElement toAssignTo; - item1.unionWith(&item2); - - TSM_ASSERT_THROWS("Cannot assign from parent", toAssignTo = item2, std::logic_error&) - } - void test_increment_rank() { DisjointElement item(0); @@ -78,13 +59,6 @@ class DisjointElementTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(2, item.getRank()); } - void test_union_same_id_throws() - { - DisjointElement item1(0); - DisjointElement item2(0); - TS_ASSERT_THROWS(item1.unionWith(&item2), std::logic_error&); - } - void test_union_two_singleton_sets() { DisjointElement item1(0); diff --git a/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h b/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h new file mode 100644 index 000000000000..892041e29f1b --- /dev/null +++ b/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h @@ -0,0 +1,427 @@ +#ifndef MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERSTEST_H_ +#define MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERSTEST_H_ + +#include + +#include "MantidCrystal/IntegratePeaksUsingClusters.h" +#include "MantidTestHelpers/MDEventsTestHelper.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidTestHelpers/ComponentCreationHelper.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/Workspace.h" +#include "MantidKernel/V3D.h" +#include "MantidDataObjects/PeaksWorkspace.h" + +#include +#include +#include + +using namespace Mantid::Crystal; +using namespace Mantid::API; +using namespace Mantid::Kernel; +using namespace Mantid::MDEvents; +using namespace Mantid::Geometry; +using namespace Mantid::DataObjects; + +namespace +{ + // Helper typedef + typedef boost::tuple MDHistoPeaksWSTuple; + + // Helper to determine if container holds a value. + template + bool does_contain(const Container& container, const typename Container::value_type & value) + { + return container.end() != std::find(container.begin(), container.end(), value); + } + + // Add a fake peak to an MDEventWorkspace + void add_fake_md_peak(Workspace_sptr mdws, const size_t& nEvents, const double& h, const double& k, const double& l, const double& radius) + { + auto fakeMDEventDataAlg = AlgorithmManager::Instance().createUnmanaged("FakeMDEventData"); + fakeMDEventDataAlg->setChild(true); + fakeMDEventDataAlg->initialize(); + fakeMDEventDataAlg->setProperty("InputWorkspace", mdws); + std::stringstream peakstream; + peakstream << nEvents << ", " << h << ", " << k << ", " << l << ", " << radius; + fakeMDEventDataAlg->setPropertyValue("PeakParams", peakstream.str()); + fakeMDEventDataAlg->execute(); + } + + // Make a fake peaks workspace and corresponding mdhistoworkspace and return both + MDHistoPeaksWSTuple make_peak_and_md_ws(const std::vector& hklValuesVec, + const double& min, const double& max, const std::vector& peakRadiusVec, + const std::vector& nEventsInPeakVec, const size_t& nBins=20) + { + Instrument_sptr inst = ComponentCreationHelper::createTestInstrumentRectangular(1, 100, 0.05); + + // --- Make a fake md histo workspace --- + auto mdworkspaceAlg = AlgorithmManager::Instance().createUnmanaged("CreateMDWorkspace"); + mdworkspaceAlg->setChild(true); + mdworkspaceAlg->initialize(); + mdworkspaceAlg->setProperty("Dimensions", 3); + std::vector extents = boost::assign::list_of(min)(max)(min)(max)(min)(max).convert_to_container >(); + mdworkspaceAlg->setProperty("Extents", extents); + mdworkspaceAlg->setPropertyValue("Names", "H,K,L"); + mdworkspaceAlg->setPropertyValue("Units", "-,-,-"); + mdworkspaceAlg->setPropertyValue("OutputWorkspace", "IntegratePeaksMDTest_MDEWS"); + mdworkspaceAlg->execute(); + Workspace_sptr mdws = mdworkspaceAlg->getProperty("OutputWorkspace"); + + // --- Set speical coordinates on fake mdworkspace -- + auto coordsAlg = AlgorithmManager::Instance().createUnmanaged("SetSpecialCoordinates"); + coordsAlg->setChild(true); + coordsAlg->initialize(); + coordsAlg->setProperty("InputWorkspace", mdws); + coordsAlg->setProperty("SpecialCoordinates", "HKL"); + coordsAlg->execute(); + + // --- Make a fake PeaksWorkspace --- + IPeaksWorkspace_sptr peakWS(new PeaksWorkspace()); + peakWS->setInstrument(inst); + + // --- Set speical coordinates on fake PeaksWorkspace -- + coordsAlg = AlgorithmManager::Instance().createUnmanaged("SetSpecialCoordinates"); + coordsAlg->setChild(true); + coordsAlg->initialize(); + coordsAlg->setProperty("InputWorkspace", peakWS); + coordsAlg->setProperty("SpecialCoordinates", "HKL"); + coordsAlg->execute(); + + for(size_t i = 0; iaddPeak(peak); + + add_fake_md_peak(mdws, nEventsInPeakVec[i], h, k, l, peakRadiusVec[i]); + } + + auto binMDAlg = AlgorithmManager::Instance().createUnmanaged("BinMD"); + binMDAlg->setChild(true); + binMDAlg->initialize(); + binMDAlg->setProperty("InputWorkspace", mdws); + binMDAlg->setPropertyValue("OutputWorkspace", "output_ws"); + binMDAlg->setProperty("AxisAligned", true); + + std::stringstream dimensionstring; + dimensionstring << "," << min << ", " << max << "," << nBins ; + + binMDAlg->setPropertyValue("AlignedDim0", "H" + dimensionstring.str()); + binMDAlg->setPropertyValue("AlignedDim1", "K" + dimensionstring.str()); + binMDAlg->setPropertyValue("AlignedDim2", "L" + dimensionstring.str()); + binMDAlg->execute(); + + Workspace_sptr temp = binMDAlg->getProperty("OutputWorkspace"); + IMDHistoWorkspace_sptr outMDWS = boost::dynamic_pointer_cast(temp); + return MDHistoPeaksWSTuple(outMDWS, peakWS); + } + + // Make a fake peaks workspace and corresponding mdhistoworkspace and return both + MDHistoPeaksWSTuple make_peak_and_md_ws(const std::vector& hklValues, + const double& min, const double& max, const double& peakRadius=1, + const size_t nEventsInPeak=1000, const size_t& nBins=20) + { + std::vector nEventsInPeakVec(hklValues.size(), nEventsInPeak); + std::vector peakRadiusVec(hklValues.size(), peakRadius); + return make_peak_and_md_ws(hklValues, min, max, peakRadiusVec, nEventsInPeakVec, nBins); + } + + // Execute the clustering integration algorithm + MDHistoPeaksWSTuple execute_integration(const MDHistoPeaksWSTuple& inputWorkspaces, const double& peakRadius, const double& threshold) + { + auto mdWS = inputWorkspaces.get<0>(); + auto peaksWS = inputWorkspaces.get<1>(); + // ------- Integrate the fake data + IntegratePeaksUsingClusters alg; + alg.initialize(); + alg.setRethrows(true); + alg.setChild(true); + alg.setProperty("InputWorkspace", mdWS); + alg.setProperty("PeaksWorkspace", peaksWS); + alg.setProperty("Threshold", threshold); + alg.setProperty("RadiusEstimate", peakRadius + 0.1); + alg.setPropertyValue("OutputWorkspace", "out_ws"); + alg.setPropertyValue("OutputWorkspaceMD", "out_ws_md"); + alg.execute(); + // ------- Get the integrated results + IPeaksWorkspace_sptr outPeaksWS = alg.getProperty("OutputWorkspace"); + IMDHistoWorkspace_sptr outClustersWS = alg.getProperty("OutputWorkspaceMD"); + return MDHistoPeaksWSTuple(outClustersWS, outPeaksWS); + } +} + +//===================================================================================== +// Functional Tests +//===================================================================================== +class IntegratePeaksUsingClustersTest : 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 IntegratePeaksUsingClustersTest *createSuite() { return new IntegratePeaksUsingClustersTest(); } + static void destroySuite( IntegratePeaksUsingClustersTest *suite ) { delete suite; } + + IntegratePeaksUsingClustersTest() + { + FrameworkManager::Instance(); + } + + void test_Init() + { + IntegratePeaksUsingClusters alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + } + + void test_peaks_workspace_mandatory() + { + IMDHistoWorkspace_sptr mdws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1,1); + + IntegratePeaksUsingClusters alg; + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", mdws); + alg.setPropertyValue("OutputWorkspaceMD", "out_md"); + alg.setPropertyValue("OutputWorkspace", "out_peaks"); + TSM_ASSERT_THROWS("PeaksWorkspace required", alg.execute(), std::runtime_error&); + } + + void test_input_md_workspace_mandatory() + { + auto peaksws = WorkspaceCreationHelper::createPeaksWorkspace(); + + IntegratePeaksUsingClusters alg; + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("PeaksWorkspace", peaksws); + alg.setPropertyValue("OutputWorkspaceMD", "out_md"); + alg.setPropertyValue("OutputWorkspace", "out_peaks"); + TSM_ASSERT_THROWS("InputWorkspace required", alg.execute(), std::runtime_error&); + } + + void test_throw_if_special_coordinates_unknown() + { + auto peaksws = WorkspaceCreationHelper::createPeaksWorkspace(); + IMDHistoWorkspace_sptr mdws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1,1); + + IntegratePeaksUsingClusters alg; + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", mdws); + alg.setProperty("PeaksWorkspace", peaksws); + alg.setPropertyValue("OutputWorkspaceMD", "out_md"); + alg.setPropertyValue("OutputWorkspace", "out_peaks"); + TSM_ASSERT_THROWS("Unknown special coordinates", alg.execute(), std::invalid_argument&); + } + + void test_threshold_too_high_gives_no_peaks() + { + // ------- Make the fake input + std::vector hklValues; + // Add a single peak. + hklValues.push_back(V3D(2,2,2)); + const double peakRadius = 1; + const double threshold = 10000; // Threshold will filter out everything given the nEventsInPeak restriction. + const size_t nEventsInPeak = 10000; + MDHistoPeaksWSTuple inputWorkspaces = make_peak_and_md_ws(hklValues, -10, 10, peakRadius, nEventsInPeak); + //-------- Execute the integratioin + MDHistoPeaksWSTuple integratedWorkspaces = execute_integration(inputWorkspaces, peakRadius, threshold); + // ------- Get the integrated results + IMDHistoWorkspace_sptr outClustersWS = integratedWorkspaces.get<0>(); + IPeaksWorkspace_sptr outPeaksWS = integratedWorkspaces.get<1>(); + + std::set labelIds; + for(size_t i = 0; i < outClustersWS->getNPoints(); ++i) + { + labelIds.insert(outClustersWS->getSignalAt(i)); + } + TSM_ASSERT_EQUALS("Should only have one type of label", 1, labelIds.size()); + TSM_ASSERT("Should have 'empy' label", does_contain(labelIds, 0)); + + TSM_ASSERT_EQUALS("Integrated intensity should be zero since no integration has occured", 0, outPeaksWS->getPeak(0).getIntensity()); + TSM_ASSERT_EQUALS("Integrated intensity should be zero since no integration has occured", 0, outPeaksWS->getPeak(0).getSigmaIntensity()); + } + + void test_integrate_single_peak() + { + // ------- Make the fake input + std::vector hklValues; + // Add a single peak. + hklValues.push_back(V3D(2,2,2)); + const double peakRadius = 1; + const double threshold = 100; + const size_t nEventsInPeak = 10000; + MDHistoPeaksWSTuple inputWorkspaces = make_peak_and_md_ws(hklValues, -10, 10, peakRadius, nEventsInPeak); + //-------- Execute the integratioin + MDHistoPeaksWSTuple integratedWorkspaces = execute_integration(inputWorkspaces, peakRadius, threshold); + // ------- Get the integrated results + IMDHistoWorkspace_sptr outClustersWS = integratedWorkspaces.get<0>(); + IPeaksWorkspace_sptr outPeaksWS = integratedWorkspaces.get<1>(); + + // ------- Check the results. + // Basic checks + auto mdWS = inputWorkspaces.get<0>(); + auto peaksWS = inputWorkspaces.get<1>(); + TS_ASSERT_EQUALS(outPeaksWS->getNumberPeaks(), peaksWS->getNumberPeaks()); + TS_ASSERT_EQUALS(mdWS->getNPoints(), outClustersWS->getNPoints()); + // Check clusters by extracting unique label ids. + std::set labelIds; + for(size_t i = 0; i < outClustersWS->getNPoints(); ++i) + { + labelIds.insert(outClustersWS->getSignalAt(i)); + } + TSM_ASSERT_EQUALS("Only one peak present, so should only have two unique label ids", 2, labelIds.size()); + + TSM_ASSERT("Should have 'empy' label", does_contain(labelIds, 0)); + TSM_ASSERT("Should have non-empy label", does_contain(labelIds, 1)); + } + + void test_integrate_two_separte_but_identical_peaks() + { + // ------- Make the fake input + std::vector hklValues; + // Add several peaks. These are NOT overlapping. + hklValues.push_back(V3D(1,1,1)); + hklValues.push_back(V3D(6,6,6)); + const double peakRadius = 1; + const double threshold = 100; + const size_t nEventsInPeak = 10000; + MDHistoPeaksWSTuple inputWorkspaces = make_peak_and_md_ws(hklValues, -10, 10, peakRadius, nEventsInPeak); + //-------- Execute the integratioin + MDHistoPeaksWSTuple integratedWorkspaces = execute_integration(inputWorkspaces, peakRadius, threshold); + // ------- Get the integrated results + IMDHistoWorkspace_sptr outClustersWS = integratedWorkspaces.get<0>(); + IPeaksWorkspace_sptr outPeaksWS = integratedWorkspaces.get<1>(); + + // ------- Check the results. + // Basic checks + auto mdWS = inputWorkspaces.get<0>(); + auto peaksWS = inputWorkspaces.get<1>(); + TS_ASSERT_EQUALS(outPeaksWS->getNumberPeaks(), peaksWS->getNumberPeaks()); + TS_ASSERT_EQUALS(mdWS->getNPoints(), outClustersWS->getNPoints()); + // Check clusters by extracting unique label ids. + std::set labelIds; + for(size_t i = 0; i < outClustersWS->getNPoints(); ++i) + { + labelIds.insert(outClustersWS->getSignalAt(i)); + } + TSM_ASSERT_EQUALS("N peaks present, so should only have n+1 unique label ids", 3, labelIds.size()); + + TSM_ASSERT("Should have 'empy' label", does_contain(labelIds, 0)); + TSM_ASSERT("Should have non-empy label", does_contain(labelIds, 1)); + TSM_ASSERT("Should have non-empy label", does_contain(labelIds, 2)); + + // Two peaks are identical, so integrated values should be the same. + TSM_ASSERT("Integrated intensity should be greater than zero", outPeaksWS->getPeak(0).getIntensity() > 0); + TSM_ASSERT("Integrated error should be greater than zero", outPeaksWS->getPeak(0).getSigmaIntensity() > 0); + TSM_ASSERT_EQUALS("Peaks are identical, so integrated values should be identical", outPeaksWS->getPeak(0).getIntensity(), outPeaksWS->getPeak(1).getIntensity()); + TSM_ASSERT_EQUALS("Peaks are identical, so integrated error values should be identical", outPeaksWS->getPeak(0).getSigmaIntensity(), outPeaksWS->getPeak(1).getSigmaIntensity()); + } + + void test_integrate_two_peaks_of_different_magnitude() + { + // ------- Make the fake input + std::vector hklValues; + // Add several peaks. These are NOT overlapping. + hklValues.push_back(V3D(1,1,1)); + hklValues.push_back(V3D(6,6,6)); + const double peakRadius = 1; + const double threshold = 100; + std::vector nEventsInPeakVec; + nEventsInPeakVec.push_back(10000); + nEventsInPeakVec.push_back(20000); // Second peak has DOUBLE the intensity of the firse one. + + MDHistoPeaksWSTuple inputWorkspaces = make_peak_and_md_ws(hklValues, -10, 10, std::vector(hklValues.size(), peakRadius), nEventsInPeakVec); + //-------- Execute the integratioin + MDHistoPeaksWSTuple integratedWorkspaces = execute_integration(inputWorkspaces, peakRadius, threshold); + // ------- Get the integrated results + IMDHistoWorkspace_sptr outClustersWS = integratedWorkspaces.get<0>(); + IPeaksWorkspace_sptr outPeaksWS = integratedWorkspaces.get<1>(); + + // ------- Check the results. + // Basic checks + auto mdWS = inputWorkspaces.get<0>(); + auto peaksWS = inputWorkspaces.get<1>(); + TS_ASSERT_EQUALS(outPeaksWS->getNumberPeaks(), peaksWS->getNumberPeaks()); + TS_ASSERT_EQUALS(mdWS->getNPoints(), outClustersWS->getNPoints()); + // Check clusters by extracting unique label ids. + std::set labelIds; + for(size_t i = 0; i < outClustersWS->getNPoints(); ++i) + { + labelIds.insert(outClustersWS->getSignalAt(i)); + } + TSM_ASSERT_EQUALS("N peaks present, so should only have n+1 unique label ids", 3, labelIds.size()); + + TSM_ASSERT("Should have 'empy' label", does_contain(labelIds, 0)); + TSM_ASSERT("Should have non-empy label", does_contain(labelIds, 1)); + TSM_ASSERT("Should have non-empy label", does_contain(labelIds, 2)); + + // Two peaks are identical, so integrated values should be the same. + TSM_ASSERT("Integrated intensity should be greater than zero", outPeaksWS->getPeak(0).getIntensity() > 0); + TSM_ASSERT("Integrated error should be greater than zero", outPeaksWS->getPeak(0).getSigmaIntensity() > 0); + TSM_ASSERT_EQUALS("Second peak is twice as 'bright'", outPeaksWS->getPeak(0).getIntensity() * 2, outPeaksWS->getPeak(1).getIntensity()); + TSM_ASSERT_EQUALS("Second peak is twice as 'bright'", outPeaksWS->getPeak(0).getSigmaIntensity() * 2, outPeaksWS->getPeak(1).getSigmaIntensity()); + } + +}; + +//===================================================================================== +// Performance Tests +//===================================================================================== +class IntegratePeaksUsingClustersTestPerformance : public CxxTest::TestSuite +{ + +private: + + // Input data + MDHistoPeaksWSTuple m_inputWorkspaces; + double m_peakRadius; + double m_threshold; + +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static IntegratePeaksUsingClustersTestPerformance *createSuite() { return new IntegratePeaksUsingClustersTestPerformance(); } + static void destroySuite( IntegratePeaksUsingClustersTestPerformance *suite ) { delete suite; } + + IntegratePeaksUsingClustersTestPerformance() + { + FrameworkManager::Instance(); + + std::vector hklValues; + for(double i = -10; i < 10; i+=4) + { + for(double j = -10; j < 10; j+=4) + { + for(double k = -10; k < 10; k+=4) + { + hklValues.push_back(V3D(i,j,k)); + } + } + } + + m_peakRadius = 1; + m_threshold = 10; + const size_t nEventsInPeak = 1000; + m_inputWorkspaces = make_peak_and_md_ws(hklValues, -10, 10, m_peakRadius, nEventsInPeak, 50); + + } + + void test_execute() + { + // Just run the integration. Functional tests handled in separate suite. + execute_integration(m_inputWorkspaces, m_peakRadius, m_threshold); + } + +}; + + +#endif /* MANTID_CRYSTAL_INTEGRATEPEAKSUSINGCLUSTERSTEST_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/Crystal/test/OptimizeCrystalPlacementTest.h b/Code/Mantid/Framework/Crystal/test/OptimizeCrystalPlacementTest.h index 8c4c22962ff3..8d8e8b67c110 100644 --- a/Code/Mantid/Framework/Crystal/test/OptimizeCrystalPlacementTest.h +++ b/Code/Mantid/Framework/Crystal/test/OptimizeCrystalPlacementTest.h @@ -239,7 +239,7 @@ class OptimizeCrystalPlacementTest: public CxxTest::TestSuite Kernel::V3D SampPos(.0003, -.00025, .00015); boost::shared_ptr pmap = Inst->getParameterMap();//check if parameterized. - Geometry::IObjComponent_const_sptr sample = Inst->getSample(); + Geometry::IComponent_const_sptr sample = Inst->getSample(); Kernel::V3D oldSampPos = sample->getPos();// Should reset Inst pmap->addPositionCoordinate(sample.get(), "x", SampPos.X()); diff --git a/Code/Mantid/Framework/Crystal/test/PeakBackgroundTest.h b/Code/Mantid/Framework/Crystal/test/PeakBackgroundTest.h new file mode 100644 index 000000000000..b8b1abbd001e --- /dev/null +++ b/Code/Mantid/Framework/Crystal/test/PeakBackgroundTest.h @@ -0,0 +1,166 @@ +#ifndef MANTID_CRYSTAL_PEAKBACKGROUNDTEST_H_ +#define MANTID_CRYSTAL_PEAKBACKGROUNDTEST_H_ + +#include +#include +#include "MantidCrystal/PeakBackground.h" +#include "MantidGeometry/Instrument.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidTestHelpers/ComponentCreationHelper.h" + +using Mantid::Crystal::PeakBackground; +using namespace Mantid::API; +using namespace Mantid::Geometry; +using namespace Mantid::DataObjects; +using namespace Mantid::Kernel; +using namespace Mantid; +using namespace testing; + +namespace +{ + // Make a peaks workspace with a single HKL peak. + IPeaksWorkspace_sptr make_peaks_workspace(const V3D& hklPeak) + { + Instrument_sptr inst = ComponentCreationHelper::createTestInstrumentRectangular(1, 100, 0.05); + + // --- Make a fake PeaksWorkspace --- + IPeaksWorkspace_sptr peakWS(new PeaksWorkspace()); + peakWS->setInstrument(inst); + + Peak peak(inst, 15050, 1.0); + peak.setHKL(hklPeak[0], hklPeak[1], hklPeak[2]); + peakWS->addPeak(peak); + return peakWS; + } + + // Mock Background strategy + class MockIMDIterator : public IMDIterator { + public: + MOCK_CONST_METHOD0(getDataSize, + size_t()); + MOCK_METHOD0(next, + bool()); + MOCK_CONST_METHOD0(valid, + bool()); + MOCK_METHOD1(jumpTo, + void(size_t index)); + MOCK_METHOD1(next, + bool(size_t skip)); + MOCK_CONST_METHOD0(getNormalizedSignal, + signal_t()); + MOCK_CONST_METHOD0(getNormalizedError, + signal_t()); + MOCK_CONST_METHOD0(getSignal, + signal_t()); + MOCK_CONST_METHOD0(getError, + signal_t()); + MOCK_CONST_METHOD1(getVertexesArray, + coord_t*(size_t & numVertices)); + MOCK_CONST_METHOD3(getVertexesArray, + coord_t*(size_t & numVertices, const size_t outDimensions, const bool * maskDim)); + MOCK_CONST_METHOD0(getCenter, + Mantid::Kernel::VMD()); + MOCK_CONST_METHOD0(getNumEvents, + size_t()); + MOCK_CONST_METHOD1(getInnerRunIndex, + uint16_t(size_t index)); + MOCK_CONST_METHOD1(getInnerDetectorID, + int32_t(size_t index)); + MOCK_CONST_METHOD2(getInnerPosition, + coord_t(size_t index, size_t dimension)); + MOCK_CONST_METHOD1(getInnerSignal, + signal_t(size_t index)); + MOCK_CONST_METHOD1(getInnerError, + signal_t(size_t index)); + MOCK_CONST_METHOD0(getIsMasked, + bool()); + MOCK_CONST_METHOD0(findNeighbourIndexes, std::vector()); + MOCK_CONST_METHOD0(getLinearIndex, size_t()); + + }; + + +} + +class PeakBackgroundTest : 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 PeakBackgroundTest *createSuite() { return new PeakBackgroundTest(); } + static void destroySuite( PeakBackgroundTest *suite ) { delete suite; } + + void test_within_range() + { + const V3D hklPeak(1,1,1); + IPeaksWorkspace_const_sptr peaksWS = make_peaks_workspace(hklPeak); + const double radius = 1; + const double threshold = 100; + PeakBackground strategy(peaksWS, radius, threshold, NoNormalization, Mantid::API::HKL); + + MockIMDIterator mockIterator; + EXPECT_CALL(mockIterator, getNormalizedSignal()).WillOnce(Return(threshold+1)); // Returns above the threshold. + EXPECT_CALL(mockIterator, getCenter()).WillOnce(Return(hklPeak)); // Returns center as being on the peak. Thefore within range. + + TSM_ASSERT("MD data in this peak region is not background", !strategy.isBackground(&mockIterator)); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockIterator)); + } + + void test_too_far_from_peak_center() + { + const V3D hklPeak(1,1,1); + IPeaksWorkspace_const_sptr peaksWS = make_peaks_workspace(hklPeak); + const double radius = 1; + const double threshold = 100; + PeakBackground strategy(peaksWS, radius, threshold, NoNormalization, Mantid::API::HKL); + + MockIMDIterator mockIterator; + V3D iteratorCenter(hklPeak[0] + radius, hklPeak[1], hklPeak[2]); // Offset so to be outside of peak radius. + EXPECT_CALL(mockIterator, getNormalizedSignal()).WillOnce(Return(threshold+1e-4)); // Returns above the threshold. + EXPECT_CALL(mockIterator, getCenter()).WillOnce(Return(iteratorCenter)); // Return offset iterator center. + + TSM_ASSERT("Data too far from peak. Should be considered background.", strategy.isBackground(&mockIterator)); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockIterator)); + } + + void test_just_close_enough_to_peak_center() + { + const V3D hklPeak(1,1,1); + IPeaksWorkspace_const_sptr peaksWS = make_peaks_workspace(hklPeak); + const double radius = 1; + const double threshold = 100; + PeakBackground strategy(peaksWS, radius, threshold, NoNormalization, Mantid::API::HKL); + + MockIMDIterator mockIterator; + V3D iteratorCenter(hklPeak[0] + radius - 1e-4, hklPeak[1], hklPeak[2]); // Offset so to be outside of peak radius. + EXPECT_CALL(mockIterator, getNormalizedSignal()).WillOnce(Return(threshold+1e-4)); // Returns above the threshold. + EXPECT_CALL(mockIterator, getCenter()).WillOnce(Return(iteratorCenter)); // Return offset iterator center. + + TSM_ASSERT("Data is within peak radius. Should NOT be considered background.", !strategy.isBackground(&mockIterator)); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockIterator)); + } + + void test_below_threshold() + { + const V3D hklPeak(1,1,1); + IPeaksWorkspace_const_sptr peaksWS = make_peaks_workspace(hklPeak); + const double radius = 1; + const double threshold = 100; + PeakBackground strategy(peaksWS, radius, threshold, NoNormalization, Mantid::API::HKL); + + MockIMDIterator mockIterator; + EXPECT_CALL(mockIterator, getNormalizedSignal()).WillOnce(Return(threshold)); // Returns equal to the threshold. Exclusive checking. + + TSM_ASSERT("MD data signal is below the allowed threshold. Should be background.", strategy.isBackground(&mockIterator)); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockIterator)); + } + + +}; + + +#endif /* MANTID_CRYSTAL_PEAKBACKGROUNDTEST_H_ */ \ No newline at end of file diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/FitMW.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/FitMW.h index 76c528e67168..6f059e1ca0e6 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/FitMW.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/FitMW.h @@ -64,11 +64,12 @@ namespace Mantid virtual void createDomain( boost::shared_ptr& domain, boost::shared_ptr& values, size_t i0 = 0); - void createOutputWorkspace( + boost::shared_ptr createOutputWorkspace( const std::string& baseName, API::IFunction_sptr function, boost::shared_ptr domain, - boost::shared_ptr values + boost::shared_ptr values, + const std::string& outputWorkspacePropertyName ); /// Return the size of the domain to be created. virtual size_t getDomainSize() const; diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/MultiDomainCreator.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/MultiDomainCreator.h index 62fa2011921f..630e08ebb376 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/MultiDomainCreator.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/MultiDomainCreator.h @@ -53,6 +53,14 @@ namespace Mantid virtual void createDomain( boost::shared_ptr& domain, boost::shared_ptr& values, size_t i0 = 0); + /// Create the output workspace + boost::shared_ptr createOutputWorkspace( + const std::string& baseName, + API::IFunction_sptr function, + boost::shared_ptr domain, + boost::shared_ptr values, + const std::string& outputWorkspacePropertyName + ); /// Return the size of the domain to be created. virtual size_t getDomainSize() const{return 0;} @@ -61,6 +69,8 @@ namespace Mantid bool hasCreator(size_t i) const; /// Get number of creators size_t getNCreators() const {return m_creators.size();} + /// Initialize the function + void initFunction(API::IFunction_sptr function); protected: /// Vector of creators. diff --git a/Code/Mantid/Framework/CurveFitting/src/FitMW.cpp b/Code/Mantid/Framework/CurveFitting/src/FitMW.cpp index 1d31d834ac27..d9f9ecf85f76 100644 --- a/Code/Mantid/Framework/CurveFitting/src/FitMW.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/FitMW.cpp @@ -280,18 +280,20 @@ namespace * @param function :: A Pointer to the fitting function * @param domain :: The domain containing x-values for the function * @param ivalues :: A API::FunctionValues instance containing the fitting data + * @param outputWorkspacePropertyName :: The property name */ - void FitMW::createOutputWorkspace( + boost::shared_ptr FitMW::createOutputWorkspace( const std::string& baseName, API::IFunction_sptr function, boost::shared_ptr domain, - boost::shared_ptr ivalues + boost::shared_ptr ivalues, + const std::string& outputWorkspacePropertyName ) { auto values = boost::dynamic_pointer_cast(ivalues); if (!values) { - return; + throw std::logic_error("FunctionValues expected"); } // Compile list of functions to output. The top-level one is first @@ -331,10 +333,14 @@ namespace Diff[i] = values->getFitData(i) - Ycal[i]; } - declareProperty(new API::WorkspaceProperty("OutputWorkspace","",Direction::Output), - "Name of the output Workspace holding resulting simulated spectrum"); - m_manager->setPropertyValue("OutputWorkspace",baseName+"Workspace"); - m_manager->setProperty("OutputWorkspace",ws); + if ( !outputWorkspacePropertyName.empty() ) + { + declareProperty(new API::WorkspaceProperty(outputWorkspacePropertyName,"",Direction::Output), + "Name of the output Workspace holding resulting simulated spectrum"); + m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspace"); + m_manager->setProperty(outputWorkspacePropertyName,ws); + } + return ws; } /** diff --git a/Code/Mantid/Framework/CurveFitting/src/IkedaCarpenterPV.cpp b/Code/Mantid/Framework/CurveFitting/src/IkedaCarpenterPV.cpp index f922174ef991..ee9e394f368f 100644 --- a/Code/Mantid/Framework/CurveFitting/src/IkedaCarpenterPV.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/IkedaCarpenterPV.cpp @@ -178,7 +178,7 @@ void IkedaCarpenterPV::calWavelengthAtEachDataPoint(const double* xValues, const { API::MatrixWorkspace_const_sptr mws = getMatrixWorkspace(); Instrument_const_sptr instrument = mws->getInstrument(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if (sample != NULL) { convertValue(m_waveLength, wavelength, mws, m_workspaceIndex); diff --git a/Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp b/Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp index 8e2a39405d10..743e4e8f0019 100644 --- a/Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp @@ -3,12 +3,25 @@ //---------------------------------------------------------------------- #include "MantidCurveFitting/MultiDomainCreator.h" #include "MantidAPI/JointDomain.h" +#include "MantidAPI/MultiDomainFunction.h" +#include "MantidAPI/WorkspaceGroup.h" +#include "MantidAPI/WorkspaceProperty.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidKernel/Logger.h" + +#include +#include namespace Mantid { namespace CurveFitting { + namespace + { + Kernel::Logger g_log("MultiDomainCreator"); + } + void MultiDomainCreator::setCreator(size_t i, IDomainCreator* creator) { m_creators[i] = boost::shared_ptr(creator); @@ -51,6 +64,112 @@ namespace CurveFitting ivalues = values; } + /** + * Initialize the function with the workspace(s). + * @param function :: A function to initialize. + */ + void MultiDomainCreator::initFunction(API::IFunction_sptr function) + { + auto mdFunction = boost::dynamic_pointer_cast(function); + if ( mdFunction ) + { + // loop over member functions and init them + for(size_t iFun = 0; iFun < mdFunction->nFunctions(); ++iFun) + { + std::vector domainIndices; + // get domain indices for this function + mdFunction->getDomainIndices(iFun,m_creators.size(),domainIndices); + if ( !domainIndices.empty() ) + { + if ( domainIndices.size() != 1 ) + { + g_log.warning() << "Function #" << iFun << " applies to multiple domains." << std::endl; + g_log.warning() << "Only one of the domains is used to set workspace." << std::endl; + } + size_t index = domainIndices[0]; + if ( index >= m_creators.size() ) + { + std::stringstream msg; + msg << "Domain index is out of range. (Function #" << iFun << ")"; + throw std::runtime_error(msg.str()); + } + m_creators[index]->initFunction( mdFunction->getFunction(iFun) ); + } + else + { + g_log.warning() << "Function #" << iFun << " doesn't apply to any domain" << std::endl; + } + } + } + else + { + IDomainCreator::initFunction(function); + } + } + + /** + * Create the output workspace group. + * @param baseName :: The base name for the output workspace. Suffix "Workspace" will be added to it. + * @param function :: A function to calculate the values. Must be of the MultiDomainFunction type. + * @param domain :: Domain created earlier with this creator (unused) + * @param values :: Values created earlier with this creator (unused) + * @param outputWorkspacePropertyName :: Name for the property to hold the output workspace. If + * empty the property won't be created. + * @return A shared pointer to the created workspace. + */ + boost::shared_ptr MultiDomainCreator::createOutputWorkspace( + const std::string& baseName, + API::IFunction_sptr function, + boost::shared_ptr domain, + boost::shared_ptr values, + const std::string& outputWorkspacePropertyName + ) + { + UNUSED_ARG(domain); + UNUSED_ARG(values); + + auto mdFunction = boost::dynamic_pointer_cast(function); + if ( !mdFunction ) + { + throw std::runtime_error("A MultiDomainFunction is expected to be used with MultiDomainCreator."); + } + + // split the function into independent parts + std::vector functions = mdFunction->createEquivalentFunctions(); + // there must be as many parts as there are domains + if ( functions.size() != m_creators.size() ) + { + throw std::runtime_error("Number of functions and domains don't match"); + } + + API::WorkspaceGroup_sptr outWS = API::WorkspaceGroup_sptr( new API::WorkspaceGroup() ); + + for(size_t i = 0; i < functions.size(); ++i) + { + std::string localName = baseName + "Workspace_" + boost::lexical_cast(i); + auto fun = functions[i]; + auto creator = m_creators[i]; + boost::shared_ptr localDomain; + boost::shared_ptr localValues; + fun->setUpForFit(); + creator->createDomain(localDomain,localValues); + creator->initFunction(fun); + auto ws = creator->createOutputWorkspace(localName,fun,localDomain,localValues,""); + API::AnalysisDataService::Instance().addOrReplace(localName,ws); + outWS->addWorkspace( ws ); + } + + if ( !outputWorkspacePropertyName.empty() ) + { + declareProperty(new API::WorkspaceProperty(outputWorkspacePropertyName,"",Kernel::Direction::Output), + "Name of the output Workspace holding resulting simulated spectrum"); + m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspaces"); + m_manager->setProperty(outputWorkspacePropertyName,outWS); + } + + return outWS; + } + } // namespace Algorithm } // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/test/FitMWTest.h b/Code/Mantid/Framework/CurveFitting/test/FitMWTest.h index 5e5ef0ce5e62..c5eee2aa468e 100644 --- a/Code/Mantid/Framework/CurveFitting/test/FitMWTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/FitMWTest.h @@ -328,7 +328,7 @@ class FitMWTest : public CxxTest::TestSuite // Create Output const std::string baseName("TestOutput_"); - fitmw.createOutputWorkspace(baseName, composite, domain, values); + fitmw.createOutputWorkspace(baseName, composite, domain, values, "OutputWorkspace"); MatrixWorkspace_sptr outputWS; @@ -551,7 +551,7 @@ class FitMWTest : public CxxTest::TestSuite // Create Output const std::string baseName("TestOutput_"); - fitmw.createOutputWorkspace(baseName, conv, domain, values); + fitmw.createOutputWorkspace(baseName, conv, domain, values, "OutputWorkspace"); MatrixWorkspace_sptr outputWS; diff --git a/Code/Mantid/Framework/CurveFitting/test/MultiDomainCreatorTest.h b/Code/Mantid/Framework/CurveFitting/test/MultiDomainCreatorTest.h index dceed75ffb67..ac4b4f7f387c 100644 --- a/Code/Mantid/Framework/CurveFitting/test/MultiDomainCreatorTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/MultiDomainCreatorTest.h @@ -6,8 +6,13 @@ #include "MantidAPI/JointDomain.h" #include "MantidAPI/FrameworkManager.h" #include "MantidAPI/WorkspaceProperty.h" +#include "MantidAPI/MultiDomainFunction.h" +#include "MantidAPI/WorkspaceGroup.h" +#include "MantidAPI/IFunction1D.h" +#include "MantidAPI/ParamFunction.h" #include "MantidCurveFitting/MultiDomainCreator.h" #include "MantidCurveFitting/FitMW.h" +#include "MantidCurveFitting/UserFunction.h" #include "MantidKernel/PropertyManager.h" #include "MantidTestHelpers/FakeObjects.h" @@ -21,6 +26,32 @@ using namespace Mantid; using namespace Mantid::API; using namespace Mantid::CurveFitting; +class MultiDomainCreatorTest_Fun: public IFunction1D, public ParamFunction +{ +public: + size_t m_wsIndex; + boost::shared_ptr m_workspace; + std::string name()const {return "MultiDomainCreatorTest_Fun";} + void function1D(double* , const double* , const size_t )const{} + void setMatrixWorkspace(boost::shared_ptr,size_t wi,double, double) + { + m_wsIndex = wi; + } + void setWorkspace(boost::shared_ptr ws) + { + m_workspace = boost::dynamic_pointer_cast(ws); + } +}; + +class MultiDomainCreatorTest_Manager: public Kernel::PropertyManager +{ +public: + void store(const std::string& propName) + { + dynamic_cast(getPointerToProperty(propName))->store(); + } +}; + class MultiDomainCreatorTest : public CxxTest::TestSuite { public: @@ -31,7 +62,6 @@ class MultiDomainCreatorTest : public CxxTest::TestSuite MultiDomainCreatorTest() { - //FrameworkManager::Instance(); ws1.reset(new WorkspaceTester); ws1->initialize(1,10,10); { @@ -137,10 +167,162 @@ class MultiDomainCreatorTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(d3->size() , 10); TS_ASSERT_EQUALS(values->size() , 30); + + } + + void test_output_workspace() + { + MultiDomainCreatorTest_Manager manager; + manager.declareProperty(new WorkspaceProperty("WS1","",Direction::Input)); + manager.declareProperty(new WorkspaceProperty("WS2","",Direction::Input)); + manager.declareProperty(new WorkspaceProperty("WS3","",Direction::Input)); + + std::vector propNames; + propNames.push_back("WS1"); + propNames.push_back("WS2"); + propNames.push_back("WS3"); + MultiDomainCreator multi( &manager, propNames ); + + manager.setProperty("WS1", ws1); + manager.setProperty("WS2", ws2); + manager.setProperty("WS3", ws3); + + FitMW* creator = new FitMW( &manager, "WS1" ); + creator->declareDatasetProperties("1"); + multi.setCreator(0, creator); + creator = new FitMW( &manager, "WS2" ); + creator->declareDatasetProperties("2"); + multi.setCreator(1, creator); + creator = new FitMW( &manager, "WS3" ); + creator->declareDatasetProperties("3"); + multi.setCreator(2, creator); + + manager.setProperty("WorkspaceIndex1", 0); + manager.setProperty("WorkspaceIndex2", 0); + manager.setProperty("WorkspaceIndex3", 0); + + FunctionDomain_sptr domain; + IFunctionValues_sptr values; + + auto mdfun = boost::make_shared(); + + auto f1 = boost::make_shared(); + f1->setAttributeValue("Formula","1.1 + 0*x"); + mdfun->addFunction(f1); + mdfun->setDomainIndex(0,0); + + auto f2 = boost::make_shared(); + f2->setAttributeValue("Formula","2.1 + 0*x"); + mdfun->addFunction(f2); + mdfun->setDomainIndex(1,1); + + auto f3 = boost::make_shared(); + f3->setAttributeValue("Formula","3.1 + 0*x"); + mdfun->addFunction(f3); + mdfun->setDomainIndex(2,2); + + auto ws = multi.createOutputWorkspace("out_",mdfun,FunctionDomain_sptr(),IFunctionValues_sptr(),"OUT_WS"); + TS_ASSERT( ws ); + + auto group = boost::dynamic_pointer_cast(ws); + TS_ASSERT( group ); + + TS_ASSERT_EQUALS( group->size(), 3 ); + + auto ows1 = boost::dynamic_pointer_cast(group->getItem(0)); + doTestOutputSpectrum( ows1, 0); + auto ows2 = boost::dynamic_pointer_cast(group->getItem(1)); + doTestOutputSpectrum( ows2, 1 ); + auto ows3 = boost::dynamic_pointer_cast(group->getItem(2)); + doTestOutputSpectrum( ows3, 2 ); + + WorkspaceGroup_sptr outWS = manager.getProperty("OUT_WS"); + TS_ASSERT( outWS ); + TS_ASSERT_EQUALS( outWS->getItem(0)->name(), "out_Workspace_0" ); + TS_ASSERT_EQUALS( outWS->getItem(1)->name(), "out_Workspace_1" ); + TS_ASSERT_EQUALS( outWS->getItem(2)->name(), "out_Workspace_2" ); + manager.store("OUT_WS"); + TS_ASSERT_EQUALS( outWS->name(), "out_Workspaces" ); + AnalysisDataService::Instance().clear(); } + void test_setMatrixWorkspace_and_setWorkspace() + { + Mantid::Kernel::PropertyManager manager; + manager.declareProperty(new WorkspaceProperty("WS1","",Direction::Input)); + manager.declareProperty(new WorkspaceProperty("WS2","",Direction::Input)); + manager.declareProperty(new WorkspaceProperty("WS3","",Direction::Input)); + + std::vector propNames; + propNames.push_back("WS1"); + propNames.push_back("WS2"); + propNames.push_back("WS3"); + MultiDomainCreator multi( &manager, propNames ); + + manager.setProperty("WS1", ws1); + manager.setProperty("WS2", ws2); + manager.setProperty("WS3", ws3); + + FitMW* creator = new FitMW( &manager, "WS1" ); + creator->declareDatasetProperties("1"); + multi.setCreator(0, creator); + creator = new FitMW( &manager, "WS2" ); + creator->declareDatasetProperties("2"); + multi.setCreator(1, creator); + creator = new FitMW( &manager, "WS3" ); + creator->declareDatasetProperties("3"); + multi.setCreator(2, creator); + + manager.setProperty("WorkspaceIndex1", 0); + manager.setProperty("WorkspaceIndex2", 1); + manager.setProperty("WorkspaceIndex3", 2); + + FunctionDomain_sptr domain; + IFunctionValues_sptr values; + + auto mdfun = boost::make_shared(); + + auto f1 = boost::make_shared(); + mdfun->addFunction(f1); + mdfun->setDomainIndex(0,0); + + auto f2 = boost::make_shared(); + mdfun->addFunction(f2); + mdfun->setDomainIndex(1,1); + + auto f3 = boost::make_shared(); + mdfun->addFunction(f3); + mdfun->setDomainIndex(2,2); + + multi.initFunction( mdfun ); + TS_ASSERT_EQUALS(f1->m_wsIndex, 0); + TS_ASSERT_EQUALS(f2->m_wsIndex, 1); + TS_ASSERT_EQUALS(f3->m_wsIndex, 2); + + TS_ASSERT_EQUALS(f1->m_workspace, ws1); + TS_ASSERT_EQUALS(f2->m_workspace, ws2); + TS_ASSERT_EQUALS(f3->m_workspace, ws3); + } private: + + void doTestOutputSpectrum(MatrixWorkspace_sptr ws, size_t index) + { + TS_ASSERT( ws ); + TS_ASSERT_EQUALS( ws->getNumberHistograms(), 3 ); + auto &data = ws->readY(0); + auto &calc = ws->readY(1); + auto &diff = ws->readY(2); + + for(size_t i = 0; i < data.size(); ++i) + { + TS_ASSERT_EQUALS( data[i], static_cast(index+1) ); + TS_ASSERT_EQUALS( data[i] - calc[i], diff[i] ); + TS_ASSERT_DELTA( -0.1, diff[i], 1e-10 ); + } + + } + MatrixWorkspace_sptr ws1,ws2,ws3; }; diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h index c7c4fc2a8b04..3a59fa43ab02 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h @@ -67,11 +67,11 @@ namespace DataHandling int getProfNumber( const std::vector& lines ); /// Scan imported file for bank information - void scanBanks(const std::vector& lines, std::vector& banks, - std::map &bankstartindexmap, std::map &bankendindexmap); + void scanBanks(const std::vector& lines, const bool useBankIDsInFile, std::vector& banks, + std::map &bankstartindexmap, std::map &bankendindexmap ); /// Parse .irf file to a map - void parseResolutionStrings(std::map& parammap, const std::vector& lines, int bankid, int startlineindex, int endlineindex, int nProf); + void parseResolutionStrings(std::map& parammap, const std::vector& lines, const bool useBankIDsInFile, int bankid, int startlineindex, int endlineindex, int nProf); void parseBankLine(std::string line, double& cwl, int& bankid); diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h index 8781f56e4f8e..e34d51e3fd77 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadSassena.h @@ -78,11 +78,11 @@ namespace Mantid /// Read dataset data to a buffer ot type double void dataSetDouble( const hid_t& h5file, const std::string setName, double *buf ); /// Load qvectors dataset, calculate modulus of vectors - const MantidVec loadQvectors(const hid_t& h5file, API::WorkspaceGroup_sptr gws); + const MantidVec loadQvectors(const hid_t& h5file, API::WorkspaceGroup_sptr gws, std::vector &sorting_indexes); /// Load structure factor asa function of q-vector modulus - void loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod); + void loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod, const std::vector &sorting_indexes); /// Load time-dependent structure factor - void loadFQT(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod); + void loadFQT(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod, const std::vector &sorting_indexes); private: /// Sets documentation strings for this algorithm diff --git a/Code/Mantid/Framework/DataHandling/src/AppendGeometryToSNSNexus.cpp b/Code/Mantid/Framework/DataHandling/src/AppendGeometryToSNSNexus.cpp index 00b97f019831..0bbfdf883024 100644 --- a/Code/Mantid/Framework/DataHandling/src/AppendGeometryToSNSNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/AppendGeometryToSNSNexus.cpp @@ -192,9 +192,9 @@ namespace DataHandling Geometry::Instrument_const_sptr instrument = ws->getInstrument(); // Get the sample (needed to calculate distances) - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); // Get the source (moderator) - Geometry::IObjComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr source = instrument->getSource(); // Open the NeXus file ::NeXus::File nxfile(m_filename, NXACC_RDWR); diff --git a/Code/Mantid/Framework/DataHandling/src/FindDetectorsPar.cpp b/Code/Mantid/Framework/DataHandling/src/FindDetectorsPar.cpp index 057f0f120102..c0d9fdb4d5ee 100644 --- a/Code/Mantid/Framework/DataHandling/src/FindDetectorsPar.cpp +++ b/Code/Mantid/Framework/DataHandling/src/FindDetectorsPar.cpp @@ -511,7 +511,7 @@ FindDetectorsPar::populate_values_from_file(const API::MatrixWorkspace_sptr & in else { - Geometry::IObjComponent_const_sptr sample =inputWS->getInstrument()->getSample(); + Geometry::IComponent_const_sptr sample =inputWS->getInstrument()->getSample(); secondaryFlightpath.resize(nHist); // Loop over the spectra for (size_t i = 0; i < nHist; i++){ diff --git a/Code/Mantid/Framework/DataHandling/src/LoadDetectorInfo.cpp b/Code/Mantid/Framework/DataHandling/src/LoadDetectorInfo.cpp index 0caab2863755..d5c02c6dba66 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadDetectorInfo.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadDetectorInfo.cpp @@ -363,7 +363,7 @@ namespace Mantid // Cache base instrument m_baseInstrument = m_workspace->getInstrument()->baseInstrument(); - Geometry::IObjComponent_const_sptr sample = m_workspace->getInstrument()->getSample(); + Geometry::IComponent_const_sptr sample = m_workspace->getInstrument()->getSample(); if( sample ) m_samplePos = sample->getPos(); // cache values of instrument level parameters so we only change then if they are different diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index 5287aa8dd31f..cb2484811404 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -73,8 +73,10 @@ namespace DataHandling */ void LoadFullprofResolution::initDocs() { - setWikiSummary("Load Fullprof's resolution (.irf) file to one or multiple TableWorkspace(s) and/or where this is supported, see description section, translate fullprof resolution fitting parameter into Mantid equivalent fitting parameters."); - setOptionalMessage("Load Fullprof's resolution (.irf) file to one or multiple TableWorkspace(s) and/or where this is supported, see description section, translate fullprof resolution fitting parameter into Mantid equivalent fitting parameters."); + setWikiSummary("Load Fullprof's resolution (.irf) file to one or multiple TableWorkspace(s) and/or where this is supported." + " See description section, translate fullprof resolution fitting parameter into Mantid equivalent fitting parameters."); + setOptionalMessage("Load Fullprof's resolution (.irf) file to one or multiple TableWorkspace(s) and/or where this is supported." + " See description section, translate fullprof resolution fitting parameter into Mantid equivalent fitting parameters."); return; } @@ -94,10 +96,15 @@ namespace DataHandling auto wsprop = new WorkspaceProperty("OutputTableWorkspace", "", Direction::Output, PropertyMode::Optional); declareProperty(wsprop, "Name of the output TableWorkspace containing profile parameters or bank information. "); + // Use bank numbers as given in file + declareProperty( + new PropertyWithValue("UseBankIDsInFile", true, Direction::Input), + "Use bank IDs as given in file rather than ordinal number of bank." + "If the bank IDs in the file are not unique, it is advised to set this to false." ); + // Bank to import declareProperty(new ArrayProperty("Banks"), "ID(s) of specified bank(s) to load, " - "and this point the ID refers to the Bank label number in the .irf file. Hence, for now please ensure that " - "these label ID are unique. " + "The IDs are as specified by UseBankIDsInFile." "Default is all banks contained in input .irf file."); // Workspace to put parameters into. It must be a workspace group with one workpace per bank from the IRF file @@ -122,6 +129,7 @@ namespace DataHandling { // Get input string datafile = getProperty("Filename"); + const bool useBankIDsInFile = getProperty("UseBankIDsInFile"); vector outputbankids = getProperty("Banks"); WorkspaceGroup_sptr wsg = getProperty("Workspace"); vector outputwsids = getProperty("WorkspacesForBanks"); @@ -136,8 +144,8 @@ namespace DataHandling // Examine bank information vector vec_bankinirf; map bankstartindexmap, bankendindexmap; - scanBanks(lines, vec_bankinirf, bankstartindexmap, bankendindexmap); - sort(vec_bankinirf.begin(), vec_bankinirf.end()); + scanBanks(lines, useBankIDsInFile, vec_bankinirf, bankstartindexmap, bankendindexmap); + if(useBankIDsInFile) sort(vec_bankinirf.begin(), vec_bankinirf.end()); for (size_t i = 0; i < vec_bankinirf.size(); ++i) g_log.debug() << "Irf containing bank " << vec_bankinirf[i] << ".\n"; @@ -209,7 +217,7 @@ namespace DataHandling int bankid = vec_bankids[i]; g_log.debug() << "Parse bank " << bankid << " of total " << vec_bankids.size() << ".\n"; map parammap; - parseResolutionStrings(parammap, lines, bankid, bankstartindexmap[bankid], bankendindexmap[bankid], nProf); + parseResolutionStrings(parammap, lines, useBankIDsInFile , bankid, bankstartindexmap[bankid], bankendindexmap[bankid], nProf); bankparammap.insert(make_pair(bankid, parammap)); } @@ -323,20 +331,22 @@ namespace DataHandling //---------------------------------------------------------------------------------------------- /** Scan lines for bank IDs * @param lines :: vector of string of all non-empty lines in input file; + * @param useFileBankIDs :: use bank IDs as given in file rather than ordinal number of bank * @param banks :: [output] vector of integers for existing banks in .irf file; * @param bankstartindexmap :: [output] map to indicate the first line of each bank in vector lines. * @param bankendindexmap :: [output] map to indicate the last line of each bank in vector lines */ - void LoadFullprofResolution::scanBanks(const vector& lines, vector& banks, - map& bankstartindexmap, map& bankendindexmap) + void LoadFullprofResolution::scanBanks(const vector& lines, const bool useFileBankIDs, vector& banks, + map& bankstartindexmap, map& bankendindexmap ) { int startindex = -1; int endindex = -1; + int bankid = 0; for (size_t i = 0; i < lines.size(); ++i) { string line = lines[i]; if (line.find("Bank") != string::npos) - { + { // A new line found if (startindex >= 0) { @@ -350,14 +360,21 @@ namespace DataHandling startindex = static_cast(i); endindex = -1; - // Split Bank - vector level1s; - boost::split(level1s, line, boost::is_any_of("Bank")); - vector level2s; - string bankterm = level1s.back(); - boost::algorithm::trim(bankterm); - boost::split(level2s, bankterm, boost::is_any_of(" ")); - int bankid = atoi(level2s[0].c_str()); + // Get bank ID + if( useFileBankIDs) + { // Get bank ID from line + vector level1s; + boost::split(level1s, line, boost::is_any_of("Bank")); + vector level2s; + string bankterm = level1s.back(); + boost::algorithm::trim(bankterm); + boost::split(level2s, bankterm, boost::is_any_of(" ")); + bankid = atoi(level2s[0].c_str()); + } + else + { // Get bank ID as ordinal number of bank + bankid++; + } banks.push_back(bankid); } } @@ -383,13 +400,14 @@ namespace DataHandling /** Parse one bank in a .irf file to a map of parameter name and value * @param parammap :: [output] parameter name and value map * @param lines :: [input] vector of lines from .irf file; + * @param useFileBankIDs :: use bank IDs as given in file rather than ordinal number of bank * @param bankid :: [input] ID of the bank to get parsed * @param startlineindex :: [input] index of the first line of the bank in vector of lines * @param endlineindex :: [input] index of the last line of the bank in vector of lines * @param profNumber :: [input] index of the profile number */ - void LoadFullprofResolution::parseResolutionStrings(map& parammap, const vector& lines, - int bankid, int startlineindex, int endlineindex, int profNumber) + void LoadFullprofResolution::parseResolutionStrings(map& parammap, const vector& lines, + const bool useFileBankIDs, int bankid, int startlineindex, int endlineindex, int profNumber) { string bankline = lines[startlineindex]; double cwl; @@ -404,13 +422,13 @@ namespace DataHandling g_log.warning() << "No CWL found for bank " << bankid; tmpbankid = bankid; } - if (bankid != tmpbankid) - { - stringstream errss; - errss << "Input bank ID (" << bankid << ") is not same as the bank ID (" << tmpbankid - << ") found in the specified region from input. "; - throw runtime_error(errss.str()); + if( useFileBankIDs && (bankid != tmpbankid)) { + stringstream errss; + errss << "Input bank ID (" << bankid << ") is not same as the bank ID (" << tmpbankid + << ") found in the specified region from input. "; + throw runtime_error(errss.str()); } + parammap["NPROF"] = profNumber; parammap["CWL"] = cwl; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadHelper.cpp b/Code/Mantid/Framework/DataHandling/src/LoadHelper.cpp index 59b45f25b227..85f6376f7ea0 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadHelper.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadHelper.cpp @@ -104,7 +104,7 @@ double LoadHelper::calculateTOF(double distance,double wavelength) { double LoadHelper::getL1(const API::MatrixWorkspace_sptr& workspace) { Geometry::Instrument_const_sptr instrument = workspace->getInstrument(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); double l1 = instrument->getSource()->getDistance(*sample); return l1; } @@ -114,7 +114,7 @@ double LoadHelper::getL2(const API::MatrixWorkspace_sptr& workspace, int detId) Geometry::Instrument_const_sptr instrument = workspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); // Get the sample-detector distance for this detector (in metres) double l2 = workspace->getDetector(detId)->getPos().distance( sample->getPos()); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp index 930417459bf8..8122f9e75abc 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp @@ -1,5 +1,7 @@ /*WIKI* +Some Nexus files contain an instrument definition. This algorithm loads the instrument from this definition. +You may need to tell this algorithm where in the Nexus file to find the Instrument folder, which contains the instrument definition. *WIKI*/ //---------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/DataHandling/src/LoadILLSANS.cpp b/Code/Mantid/Framework/DataHandling/src/LoadILLSANS.cpp index 76bc503a8669..3c60a6b7089e 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadILLSANS.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadILLSANS.cpp @@ -1,7 +1,6 @@ /*WIKI* - Loads an ILL D33 nexus file into a [[Workspace2D]] with the given name. - +Loads an ILL D33 nexus file into a [[Workspace2D]] with the given name. *WIKI*/ diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSINQFocus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSINQFocus.cpp index 200ad6f38789..566c6e764e79 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSINQFocus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSINQFocus.cpp @@ -1,8 +1,8 @@ /*WIKI* - Loads a SINQ (PSI) nexus file into a [[Workspace2D]] with the given name. +Loads a SINQ (PSI) nexus file into a [[Workspace2D]] with the given name. - To date this algorithm only supports: FOCUS +To date this algorithm only supports: FOCUS *WIKI*/ diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp index cbfc6466ed77..704b8470553e 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSassena.cpp @@ -30,6 +30,7 @@ Dataset '''fqt''' is split into two workspaces, one for the real part and the ot #include "MantidAPI/NumericAxis.h" #include "MantidAPI/FileProperty.h" #include "MantidAPI/RegisterFileLoader.h" +#include "MantidAPI/IAlgorithm.h" #include "MantidDataObjects/Workspace2D.h" #include "MantidKernel/Exception.h" #include "MantidKernel/Unit.h" @@ -114,6 +115,10 @@ void LoadSassena::dataSetDouble( const hid_t& h5file, const std::string setName, } } +/* Helper object and function to sort modulus of Q-vectors + */ +typedef std::pair mypair; +bool compare( const mypair& left, const mypair& right){ return left.first < right.first; } /** * load vectors onto a Workspace2D with 3 bins (the three components of the vectors) * dataX for the origin of the vector (assumed (0,0,0) ) @@ -121,9 +126,11 @@ void LoadSassena::dataSetDouble( const hid_t& h5file, const std::string setName, * dataE is assumed (0,0,0), no errors * @param h5file file identifier * @param gws pointer to WorkspaceGroup being filled + * @param sorting_indexes permutation of qvmod indexes to render it in increasing order of momemtum transfer */ -const MantidVec LoadSassena::loadQvectors(const hid_t& h5file, API::WorkspaceGroup_sptr gws) +const MantidVec LoadSassena::loadQvectors(const hid_t& h5file, API::WorkspaceGroup_sptr gws, std::vector &sorting_indexes) { + const std::string gwsName = this->getPropertyValue("OutputWorkspace"); const std::string setName("qvectors"); @@ -143,11 +150,29 @@ const MantidVec LoadSassena::loadQvectors(const hid_t& h5file, API::WorkspaceGro MantidVec qvmod; //store the modulus of the vector double* curr = buf; for(int iq=0; iqdataY(iq); - Y.assign(curr,curr+3); qvmod.push_back( sqrt( curr[0]*curr[0] + curr[1]*curr[1] + curr[2]*curr[2] ) ); curr += 3; } + + if(getProperty("SortByQVectors")) + { + std::vector qvmodpair; + for(int iq=0; iqdataY(index); + Y.assign(curr,curr+3); + curr += 3; + } delete[] buf; // Set the Units @@ -165,8 +190,10 @@ const MantidVec LoadSassena::loadQvectors(const hid_t& h5file, API::WorkspaceGro * @param gws pointer to WorkspaceGroup being filled * @param setName string name of dataset * @param qvmod vector of Q-vectors' moduli + * @param sorting_indexes permutation of qvmod indexes to render it in increasing order of momemtum transfer */ -void LoadSassena::loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod){ +void LoadSassena::loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod, const std::vector &sorting_indexes) +{ const std::string gwsName = this->getPropertyValue("OutputWorkspace"); int nq = static_cast( qvmod.size() ); //number of q-vectors @@ -180,11 +207,12 @@ void LoadSassena::loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, cons ws->dataX(0) = qvmod; //X-axis values are the modulus of the q vector MantidVec& im = ws->dataY(1); // store the imaginary part ws->dataX(1) = qvmod; - double* curr = buf; + double *curr = buf; for(int iq=0; iq &sorting_indexes) { const std::string gwsName = this->getPropertyValue("OutputWorkspace"); int nq = static_cast( qvmod.size() ); //number of q-vectors @@ -231,10 +260,11 @@ void LoadSassena::loadFQT(const hid_t& h5file, API::WorkspaceGroup_sptr gws, con double* curr = buf; for(int iq=0; iqdataX(iq); - MantidVec& imX = wsIm->dataX(iq); - MantidVec& reY = wsRe->dataY(iq); - MantidVec& imY = wsIm->dataY(iq); + const int index=sorting_indexes[iq]; + MantidVec& reX = wsRe->dataX(index); + MantidVec& imX = wsIm->dataX(index); + MantidVec& reY = wsRe->dataY(index); + MantidVec& imY = wsIm->dataY(index); for(int it=0; it("OutputWorkspace","",Kernel::Direction::Output), "The name of the group workspace to be created."); declareProperty(new Kernel::PropertyWithValue("TimeUnit", 1.0, Kernel::Direction::Input),"The Time unit in between data points, in picoseconds. Default is 1.0 picosec."); + declareProperty(new Kernel::PropertyWithValue("SortByQVectors", true, Kernel::Direction::Input),"Sort structure factors by increasing momentum transfer?"); + } /** @@ -351,8 +383,8 @@ void LoadSassena::exec() //const std::string version(cversion); //determine which loader protocol to use based on the version //to be done at a later time, maybe implement a Version class - - const MantidVec qvmod = this->loadQvectors( h5file, gws ); + std::vector sorting_indexes; + const MantidVec qvmod = this->loadQvectors( h5file, gws, sorting_indexes); //iterate over the valid sets std::string setName; for(std::vector::const_iterator it=this->m_validSets.begin(); it!=this->m_validSets.end(); ++it){ @@ -360,9 +392,9 @@ void LoadSassena::exec() if(H5LTfind_dataset(h5file,setName.c_str())==1) { if(setName == "fq" || setName == "fq0" || setName == "fq2") - this->loadFQ( h5file, gws, setName, qvmod ); + this->loadFQ( h5file, gws, setName, qvmod, sorting_indexes); else if(setName == "fqt") - this->loadFQT( h5file, gws, setName, qvmod ); + this->loadFQT( h5file, gws, setName, qvmod, sorting_indexes); } else this->g_log.information("Dataset "+setName+" not present in file"); diff --git a/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp b/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp index f63fc7aec748..2fceb14a3115 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveFocusedXYE.cpp @@ -333,8 +333,8 @@ void SaveFocusedXYE::getFocusedPos(Mantid::API::MatrixWorkspace_const_sptr wksp, tth = 0.; return; } - Geometry::IObjComponent_const_sptr source = instrument->getSource(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if (source == NULL || sample == NULL) { l1 = 0.; diff --git a/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp b/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp index 7c6933c0e623..40da87bb76fd 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp @@ -93,8 +93,8 @@ namespace Mantid tth = 0.; return; } - Geometry::IObjComponent_const_sptr source = instrument->getSource(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if (source == NULL || sample == NULL) { l1 = 0.; @@ -143,8 +143,8 @@ namespace Mantid Progress p(this, 0.0, 1.0, nHist); double l1, l2, tth; Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); - Geometry::IObjComponent_const_sptr source; - Geometry::IObjComponent_const_sptr sample; + Geometry::IComponent_const_sptr source; + Geometry::IComponent_const_sptr sample; if (instrument != NULL) { source = instrument->getSource(); diff --git a/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp b/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp index e2653648f78e..934c46a17692 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp @@ -107,7 +107,8 @@ namespace Mantid this->nBins = inputWS->blocksize(); // Get a pointer to the sample - Geometry::IObjComponent_const_sptr sample = inputWS->getInstrument()->getSample(); + Geometry::IComponent_const_sptr sample = + inputWS->getInstrument()->getSample(); // Retrieve the filename from the properties this->filename = getPropertyValue("Filename"); diff --git a/Code/Mantid/Framework/DataHandling/src/SavePAR.cpp b/Code/Mantid/Framework/DataHandling/src/SavePAR.cpp index 0fde193a2f10..3c2b5a7dff26 100644 --- a/Code/Mantid/Framework/DataHandling/src/SavePAR.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SavePAR.cpp @@ -76,7 +76,7 @@ void SavePAR::exec() { const std::string filename = getProperty("Filename"); // Get a pointer to the sample - IObjComponent_const_sptr sample = + IComponent_const_sptr sample = inputWorkspace->getInstrument()->getSample(); std::ofstream outPAR_file(filename.c_str()); diff --git a/Code/Mantid/Framework/DataHandling/src/SavePHX.cpp b/Code/Mantid/Framework/DataHandling/src/SavePHX.cpp index c9fdf2eb64ab..7f115144ec20 100644 --- a/Code/Mantid/Framework/DataHandling/src/SavePHX.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SavePHX.cpp @@ -76,7 +76,7 @@ void SavePHX::exec() { const std::string filename = getProperty("Filename"); // Get a pointer to the sample - IObjComponent_const_sptr sample = + IComponent_const_sptr sample = inputWorkspace->getInstrument()->getSample(); std::ofstream outPHX_file(filename.c_str()); diff --git a/Code/Mantid/Framework/DataHandling/src/SaveToSNSHistogramNexus.cpp b/Code/Mantid/Framework/DataHandling/src/SaveToSNSHistogramNexus.cpp index bdaeee555172..d3204af35df5 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveToSNSHistogramNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveToSNSHistogramNexus.cpp @@ -1,16 +1,10 @@ /*WIKI* +The algorithm essentially copies the InputFilename into OutputFilename, except that it replaces the data field with whatever the specified workspace contains. +The histograms do not need to be the same size (in number of bins), but the number of pixels needs to be the same. - - -The algorithm essentially copies the InputFilename into OutputFilename, except that it replaces the data field with whatever the specified workspace contains. The histograms do not need to be the same size (in number of bins), but the number of pixels needs to be the same. - -In addition, this only works for instruments that use [[RectangularDetector]]s (SNAP, TOPAZ, POWGEN, for example); in addition, the name in the instrument definition file must match the name in the NXS file. - - - - - +In addition, this only works for instruments that use [[RectangularDetector]]s (SNAP, TOPAZ, POWGEN, for example); in addition, +the name in the instrument definition file must match the name in the NXS file. *WIKI*/ // SaveToSNSHistogramNexus @@ -54,7 +48,7 @@ namespace DataHandling /// Sets documentation strings for this algorithm void SaveToSNSHistogramNexus::initDocs() { - this->setWikiSummary(" Saves a workspace into SNS histogrammed NeXus format, using an original file as the starting point. This only works for instruments with Rectangular Detectors. "); + this->setWikiSummary("Saves a workspace into SNS histogrammed NeXus format, using an original file as the starting point. This only works for instruments with Rectangular Detectors. "); this->setOptionalMessage("Saves a workspace into SNS histogrammed NeXus format, using an original file as the starting point. This only works for instruments with Rectangular Detectors."); } diff --git a/Code/Mantid/Framework/DataHandling/src/SaveVTK.cpp b/Code/Mantid/Framework/DataHandling/src/SaveVTK.cpp index 913dfe93a4aa..78aa90d53d97 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveVTK.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveVTK.cpp @@ -1,7 +1,8 @@ /*WIKI* -Saves a workspace out to a VTK file that can be loaded with Paraview or any other software supporting the VTK file format. This is a very basic algorithm that simple creates a 3D view of the data as a series of histograms. It should only be used for relatively small data sets as the resulting file can become quite large relatively quickly. - +Saves a workspace out to a VTK file that can be loaded with Paraview or any other software supporting the VTK file format. +This is a very basic algorithm that simple creates a 3D view of the data as a series of histograms. +It should only be used for relatively small data sets as the resulting file can become quite large relatively quickly. *WIKI*/ //--------------------------------------------------- @@ -26,7 +27,7 @@ namespace Mantid /// Sets documentation strings for this algorithm void SaveVTK::initDocs() { - this->setWikiSummary(" Save a workspace out to a VTK file format for use with 3D visualisation tools such as Paraview. "); + this->setWikiSummary("Save a workspace out to a VTK file format for use with 3D visualisation tools such as Paraview. "); this->setOptionalMessage("Save a workspace out to a VTK file format for use with 3D visualisation tools such as Paraview."); } diff --git a/Code/Mantid/Framework/DataHandling/src/SetSampleMaterial.cpp b/Code/Mantid/Framework/DataHandling/src/SetSampleMaterial.cpp index 8f842fca5193..0cb7bb577205 100644 --- a/Code/Mantid/Framework/DataHandling/src/SetSampleMaterial.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SetSampleMaterial.cpp @@ -333,6 +333,10 @@ namespace Mantid setProperty("AbsorptionXSectionResult",mat->absorbXSection()); // in barns setProperty("ReferenceWavelength",NeutronAtom::ReferenceLambda); // in Angstroms + double smu = mat->totalScatterXSection(NeutronAtom::ReferenceLambda) * rho; + double amu = mat->absorbXSection(NeutronAtom::ReferenceLambda) * rho; + g_log.notice() << "Anvred LinearScatteringCoef = " << smu << " 1/cm\n" + << "Anvred LinearAbsorptionCoef = " << amu << " 1/cm\n"; // Done! progress(1); } diff --git a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h index f5376e212ef7..878ab8807fec 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h @@ -125,7 +125,8 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite //---------------------------------------------------------------------------------------------- /** Test import all banks from a 2-bank irf file - */ + ** Also test UseBankIDsInFile property + */ void test_LoadAllBankCase() { // Generate file @@ -146,7 +147,7 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite // Check output workspace TableWorkspace_sptr outws = boost::dynamic_pointer_cast( - AnalysisDataService::Instance().retrieve("TestBank4Table")); + AnalysisDataService::Instance().retrieve("TestBank4Table")); TS_ASSERT(outws); // Check table workspace size @@ -169,16 +170,63 @@ class LoadFullprofResolutionTest : public CxxTest::TestSuite TS_ASSERT_DELTA(parammap2["Alph0t"], 86.059, 0.00001); + // Test bank ID with UseBankIDsInFile set false + alg.setProperty("OutputTableWorkspace", "TestBank4TableFalse"); + alg.setProperty("UseBankIDsInFile", false); + + // Execute + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(alg.isExecuted()); + + // Check output workspace + TableWorkspace_sptr outwsFalse = boost::dynamic_pointer_cast( + AnalysisDataService::Instance().retrieve("TestBank4TableFalse")); + TS_ASSERT(outwsFalse); + + // Check table workspace size + TS_ASSERT_EQUALS(outwsFalse->columnCount(), 3); + TS_ASSERT_EQUALS(outwsFalse->rowCount(), getExpectedNumberOfRows()); + + // Verify ID of second bank + map parammapFalse; + parseTableWorkspace2(outwsFalse, parammapFalse); + TS_ASSERT_DELTA(parammapFalse["BANK"], 2.0, 0.0001); + + + // Test bank ID with UseBankIDsInFile set true + alg.setProperty("OutputTableWorkspace", "TestBank4TableTrue"); + alg.setProperty("UseBankIDsInFile", true); + + // Execute + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(alg.isExecuted()); + + // Check output workspace + TableWorkspace_sptr outwsTrue = boost::dynamic_pointer_cast( + AnalysisDataService::Instance().retrieve("TestBank4TableTrue")); + TS_ASSERT(outwsTrue); + + // Check table workspace size + TS_ASSERT_EQUALS(outwsTrue->columnCount(), 3); + TS_ASSERT_EQUALS(outwsTrue->rowCount(), getExpectedNumberOfRows()); + + // Verify ID of second bank + map parammapTrue; + parseTableWorkspace2(outwsTrue, parammapTrue); + TS_ASSERT_DELTA(parammapTrue["BANK"], 3.0, 0.0001); + // Clean AnalysisDataService::Instance().remove("TestBank4Table"); + AnalysisDataService::Instance().remove("TestBank4TableFalse"); + AnalysisDataService::Instance().remove("TestBank4TableTrue"); Poco::File("Test2Bank.irf").remove(); return; } //---------------------------------------------------------------------------------------------- - /** Test import all banks from a 2-bank irf file + /** Test import all banks from a 3-bank irf file */ void test_Load3BankCase() { diff --git a/Code/Mantid/Framework/DataHandling/test/LoadInstrumentTest.h b/Code/Mantid/Framework/DataHandling/test/LoadInstrumentTest.h index b26e24826b65..b9b6561bdd5d 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadInstrumentTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadInstrumentTest.h @@ -178,11 +178,11 @@ class LoadInstrumentTest : public CxxTest::TestSuite void evaluate_GEM(MatrixWorkspace_sptr output) { boost::shared_ptr i = output->getInstrument(); - boost::shared_ptr source = i->getSource(); + boost::shared_ptr source = i->getSource(); TS_ASSERT_EQUALS( source->getName(), "undulator"); TS_ASSERT_DELTA( source->getPos().Z(), -17.0,0.01); - boost::shared_ptr samplepos = i->getSample(); + boost::shared_ptr samplepos = i->getSample(); TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); TS_ASSERT_DELTA( samplepos->getPos().Y(), 0.0,0.01); @@ -292,11 +292,11 @@ class LoadInstrumentTest : public CxxTest::TestSuite TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieveWS(wsName)); boost::shared_ptr i = output->getInstrument(); - boost::shared_ptr source = i->getSource(); + boost::shared_ptr source = i->getSource(); TS_ASSERT_EQUALS( source->getName(), "undulator"); TS_ASSERT_DELTA( source->getPos().Z(), -11.016,0.01); - boost::shared_ptr samplepos = i->getSample(); + boost::shared_ptr samplepos = boost::dynamic_pointer_cast(i->getSample()); TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); TS_ASSERT_DELTA( samplepos->getPos().Y(), 0.0,0.01); diff --git a/Code/Mantid/Framework/DataObjects/src/Peak.cpp b/Code/Mantid/Framework/DataObjects/src/Peak.cpp index a536f4a294d3..8d79736cc78f 100644 --- a/Code/Mantid/Framework/DataObjects/src/Peak.cpp +++ b/Code/Mantid/Framework/DataObjects/src/Peak.cpp @@ -319,10 +319,10 @@ namespace DataObjects if (!inst) throw std::runtime_error("Peak::setInstrument(): No instrument is set!"); // Cache some positions - const Geometry::IObjComponent_const_sptr sourceObj = m_inst->getSource(); + const Geometry::IComponent_const_sptr sourceObj = m_inst->getSource(); if (sourceObj == NULL) throw Exception::InstrumentDefinitionError("Peak::setInstrument(): Failed to get source component from instrument"); - const Geometry::IObjComponent_const_sptr sampleObj = m_inst->getSample(); + const Geometry::IComponent_const_sptr sampleObj = m_inst->getSample(); if (sampleObj == NULL) throw Exception::InstrumentDefinitionError("Peak::setInstrument(): Failed to get sample component from instrument"); diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument.h index b4964063e11a..33dbfb0bf12d 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument.h @@ -74,10 +74,10 @@ namespace Mantid Instrument* clone() const; - IObjComponent_const_sptr getSource() const; + IComponent_const_sptr getSource() const; IObjComponent_const_sptr getChopperPoint(const size_t index = 0) const; size_t getNumberOfChopperPoints() const; - IObjComponent_const_sptr getSample() const; + IComponent_const_sptr getSample() const; Kernel::V3D getBeamDirection() const; IDetector_const_sptr getDetector(const detid_t &detector_id) const; @@ -98,7 +98,7 @@ namespace Mantid /// mark a Component which has already been added to the Instrument (as a child comp.) /// to be 'the' samplePos Component. For now it is assumed that we have /// at most one of these. - void markAsSamplePos(const ObjComponent*); + void markAsSamplePos(const IComponent*); /// Marks a Component which already exists in the instrument to the chopper cache void markAsChopperPoint(const ObjComponent *comp); @@ -106,7 +106,7 @@ namespace Mantid /// mark a Component which has already been added to the Instrument (as a child comp.) /// to be 'the' source Component. For now it is assumed that we have /// at most one of these. - void markAsSource(const ObjComponent*); + void markAsSource(const IComponent*); /// mark a Component which has already been added to the Instrument (as a child comp.) /// to be a Detector component by adding it to _detectorCache @@ -241,14 +241,14 @@ namespace Mantid std::map m_detectorCache; /// Purpose to hold copy of source component. For now assumed to be just one component - const ObjComponent* m_sourceCache; + const IComponent* m_sourceCache; /// Hold a list of places where a chopper can be situated /// A pointer so that parameterized intruments are still fast to create. std::vector * m_chopperPoints; /// Purpose to hold copy of samplePos component. For now assumed to be just one component - const ObjComponent* m_sampleCache; + const IComponent* m_sampleCache; /// To store info about the parameters defined in IDF. Indexed according to logfile-IDs, which equals logfile filename minus the run number and file extension InstrumentParameterCache m_logfileCache; diff --git a/Code/Mantid/Framework/Geometry/src/Instrument.cpp b/Code/Mantid/Framework/Geometry/src/Instrument.cpp index 02720418061a..24f578c0ad87 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument.cpp @@ -331,20 +331,32 @@ namespace Mantid /** Gets a pointer to the source * @returns a pointer to the source */ - IObjComponent_const_sptr Instrument::getSource() const + IComponent_const_sptr Instrument::getSource() const { if ( !m_sourceCache ) { g_log.warning("In Instrument::getSource(). No source has been set."); - return IObjComponent_const_sptr(m_sourceCache,NoDeleting()); + return IComponent_const_sptr(m_sourceCache,NoDeleting()); } else if (m_isParametrized) { - return IObjComponent_const_sptr(new ObjComponent(static_cast(m_base)->m_sourceCache,m_map)); + auto sourceCache = static_cast(m_base)->m_sourceCache; + if ( dynamic_cast(sourceCache) ) + return IComponent_const_sptr(new ObjComponent(sourceCache,m_map)); + else if ( dynamic_cast(sourceCache) ) + return IComponent_const_sptr(new CompAssembly(sourceCache,m_map)); + else if ( dynamic_cast(sourceCache) ) + return IComponent_const_sptr(new Component(sourceCache,m_map)); + else + { + g_log.error("In Instrument::getSource(). Source is not a recognised component type."); + g_log.error("Try to assume it is a Component."); + return IComponent_const_sptr(new ObjComponent(sourceCache,m_map)); + } } else { - return IObjComponent_const_sptr(m_sourceCache,NoDeleting()); + return IComponent_const_sptr(m_sourceCache,NoDeleting()); } } @@ -378,20 +390,32 @@ namespace Mantid /** Gets a pointer to the Sample Position * @returns a pointer to the Sample Position */ - IObjComponent_const_sptr Instrument::getSample() const + IComponent_const_sptr Instrument::getSample() const { if ( !m_sampleCache ) { g_log.warning("In Instrument::getSamplePos(). No SamplePos has been set."); - return IObjComponent_const_sptr(m_sampleCache,NoDeleting()); + return IComponent_const_sptr(m_sampleCache,NoDeleting()); } else if (m_isParametrized) { - return IObjComponent_const_sptr(new ObjComponent(static_cast(m_base)->m_sampleCache,m_map)); + auto sampleCache = static_cast(m_base)->m_sampleCache; + if ( dynamic_cast(sampleCache) ) + return IComponent_const_sptr(new ObjComponent(sampleCache,m_map)); + else if ( dynamic_cast(sampleCache) ) + return IComponent_const_sptr(new CompAssembly(sampleCache,m_map)); + else if ( dynamic_cast(sampleCache) ) + return IComponent_const_sptr(new Component(sampleCache,m_map)); + else + { + g_log.error("In Instrument::getSamplePos(). SamplePos is not a recognised component type."); + g_log.error("Try to assume it is a Component."); + return IComponent_const_sptr(new ObjComponent(sampleCache,m_map)); + } } else { - return IObjComponent_const_sptr(m_sampleCache,NoDeleting()); + return IComponent_const_sptr(m_sampleCache,NoDeleting()); } } @@ -643,7 +667,7 @@ namespace Mantid { throw std::invalid_argument("Instrument::markAsChopper - Chopper component must have a name"); } - IObjComponent_const_sptr source = getSource(); + IComponent_const_sptr source = getSource(); if(!source) { throw Exception::InstrumentDefinitionError("Instrument::markAsChopper - No source is set, cannot defined chopper positions."); @@ -668,7 +692,7 @@ namespace Mantid * * @param comp :: Component to be marked (stored for later retrieval) as a "SamplePos" Component */ - void Instrument::markAsSamplePos(const ObjComponent* comp) + void Instrument::markAsSamplePos(const IComponent* comp) { if (m_isParametrized) throw std::runtime_error("Instrument::markAsSamplePos() called on a parametrized Instrument object."); @@ -694,7 +718,7 @@ namespace Mantid * * @param comp :: Component to be marked (stored for later retrieval) as a "source" Component */ - void Instrument::markAsSource(const ObjComponent* comp) + void Instrument::markAsSource(const IComponent* comp) { if (m_isParametrized) throw std::runtime_error("Instrument::markAsSource() called on a parametrized Instrument object."); @@ -1014,7 +1038,7 @@ namespace Mantid double & beamline_norm, Kernel::V3D & samplePos) const { // Get some positions - const IObjComponent_const_sptr sourceObj = this->getSource(); + const IComponent_const_sptr sourceObj = this->getSource(); if (sourceObj == NULL) { throw Exception::InstrumentDefinitionError("Failed to get source component from instrument"); @@ -1025,7 +1049,7 @@ namespace Mantid beamline_norm=2.0*beamline.norm(); // Get the distance between the source and the sample (assume in metres) - IObjComponent_const_sptr sample = this->getSample(); + IComponent_const_sptr sample = this->getSample(); try { l1 = this->getSource()->getDistance(*sample); @@ -1142,7 +1166,7 @@ namespace Mantid std::vector detectors; detectors = getDetectors( detIDs ); - Geometry::IObjComponent_const_sptr sample = getSample(); + Geometry::IComponent_const_sptr sample = getSample(); Kernel::V3D sample_pos; if(sample) sample_pos = sample->getPos(); diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp index 7b9423ef38ef..6054d6212578 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp @@ -1009,6 +1009,20 @@ namespace Geometry setLogfile(ass, pCompElem, m_instrument->getLogfileCache()); // params specified within setLogfile(ass, pLocElem, m_instrument->getLogfileCache()); // params specified within specific + std::string category = ""; + if (pType->hasAttribute("is")) + category = pType->getAttribute("is"); + + // check if special Component + if ( category.compare("SamplePos") == 0 || category.compare("samplePos") == 0 ) + { + m_instrument->markAsSamplePos(ass); + } + if ( category.compare("Source") == 0 || category.compare("source") == 0 ) + { + m_instrument->markAsSource(ass); + } + // If enabled, check for a 'neutronic position' tag and add to cache if found if ( m_indirectPositions ) { diff --git a/Code/Mantid/Framework/Geometry/test/InstrumentDefinitionParserTest.h b/Code/Mantid/Framework/Geometry/test/InstrumentDefinitionParserTest.h index 55f276026fbf..61d987d71bd9 100644 --- a/Code/Mantid/Framework/Geometry/test/InstrumentDefinitionParserTest.h +++ b/Code/Mantid/Framework/Geometry/test/InstrumentDefinitionParserTest.h @@ -159,11 +159,11 @@ class InstrumentDefinitionParserTest : public CxxTest::TestSuite TS_FAIL("Cannot find expected .vtp file next to " + filename); } - boost::shared_ptr source = i->getSource(); + boost::shared_ptr source = boost::dynamic_pointer_cast(i->getSource()); TS_ASSERT_EQUALS( source->getName(), "undulator"); TS_ASSERT_DELTA( source->getPos().Z(), -17.0,0.01); - boost::shared_ptr samplepos = i->getSample(); + boost::shared_ptr samplepos = boost::dynamic_pointer_cast(i->getSample()); TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); TS_ASSERT_DELTA( samplepos->getPos().Y(), 0.0,0.01); @@ -440,6 +440,16 @@ class InstrumentDefinitionParserTest : public CxxTest::TestSuite boost::shared_ptr ptrDetShape = i->getDetector(1100); TS_ASSERT_EQUALS( ptrDetShape->getID(), 1100); + // test sample + boost::shared_ptr sample = i->getSample(); + TS_ASSERT_EQUALS( sample->getName(), "nickel-holder"); + TS_ASSERT_DELTA( sample->getPos().X(), 2.0,0.01); + + // test source + boost::shared_ptr source = i->getSource(); + TS_ASSERT_EQUALS( source->getName(), "undulator"); + TS_ASSERT_DELTA( source->getPos().Z(), -95.0,0.01); + // Test of monitor shape boost::shared_ptr ptrMonShape = i->getDetector(1001); TS_ASSERT( ptrMonShape->isValid(V3D(0.002,0.0,0.0)+ptrMonShape->getPos()) ); diff --git a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp index 98f82e25f19e..9e7fd090d01a 100644 --- a/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp +++ b/Code/Mantid/Framework/ICat/src/ICat4/ICat4Catalog.cpp @@ -930,6 +930,8 @@ namespace Mantid { exception = error.substr(start + begmsg.length(), end - (start + begmsg.length()) ); } + // If no error is returned by ICAT then there is a connection problem. + if (exception.empty()) exception = "ICAT appears to be offline. Please check your connection or report this issue."; throw std::runtime_error(exception); } @@ -974,6 +976,8 @@ namespace Mantid // The soapEndPoint is only set when the user logs into the catalog. // If it's not set the correct error is returned (invalid sessionID) from the ICAT server. if (m_session->getSoapEndpoint().empty()) return; + // Stop receiving packets from ICAT server after period of time. + icat.recv_timeout = boost::lexical_cast(Kernel::ConfigService::Instance().getString("catalog.timeout.value")); // Set the soap-endpoint of the catalog we want to use. icat.soap_endpoint = m_session->getSoapEndpoint().c_str(); // Sets SSL authentication scheme diff --git a/Code/Mantid/Framework/Kernel/CMakeLists.txt b/Code/Mantid/Framework/Kernel/CMakeLists.txt index 36211f146f88..b2de365561b9 100644 --- a/Code/Mantid/Framework/Kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/Kernel/CMakeLists.txt @@ -12,6 +12,7 @@ set ( SRC_FILES src/DataItem.cpp src/DateAndTime.cpp src/DateValidator.cpp + src/DateTimeValidator.cpp src/DeltaEMode.cpp src/DirectoryValidator.cpp src/DiskBuffer.cpp @@ -127,6 +128,7 @@ set ( INC_FILES inc/MantidKernel/DataService.h inc/MantidKernel/DateAndTime.h inc/MantidKernel/DateValidator.h + inc/MantidKernel/DateTimeValidator.h inc/MantidKernel/DeltaEMode.h inc/MantidKernel/DirectoryValidator.h inc/MantidKernel/DiskBuffer.h @@ -252,6 +254,7 @@ set ( TEST_FILES ConfigServiceTest.h DataServiceTest.h DateAndTimeTest.h + DateTimeValidatorTest.h DateValidatorTest.h DeltaEModeTest.h DirectoryValidatorTest.h diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/DateTimeValidator.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/DateTimeValidator.h new file mode 100644 index 000000000000..10556b192530 --- /dev/null +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/DateTimeValidator.h @@ -0,0 +1,47 @@ +#ifndef MANTID_KERNEL_DATETIMEVALIDATOR_H_ +#define MANTID_KERNEL_DATETIMEVALIDATOR_H_ + +#include "MantidKernel/TypedValidator.h" + +namespace Mantid +{ + namespace Kernel + { + /** + Checks that a string contains a timestamp in ISO 8601 format (YYYY-MM-DDTHH:MM:SS.mmmmmm) + + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: . + Code Documentation is available at: + */ + class MANTID_KERNEL_DLL DateTimeValidator : public TypedValidator + { + public: + /// Clone the current state + IValidator_sptr clone() const; + + private: + /// Checks the value is valid + std::string checkValidity(const std::string& value) const; + }; + + } +} + +#endif /** DATETIMEVALIDATOR */ diff --git a/Code/Mantid/Framework/Kernel/src/DateAndTime.cpp b/Code/Mantid/Framework/Kernel/src/DateAndTime.cpp index ef660f4fe5df..ca7887efbee2 100644 --- a/Code/Mantid/Framework/Kernel/src/DateAndTime.cpp +++ b/Code/Mantid/Framework/Kernel/src/DateAndTime.cpp @@ -493,7 +493,13 @@ void DateAndTime::setFromISO8601(const std::string str) } } - //The boost conversion will convert the string, then we subtract the time zone offset + // The boost conversion will convert the string, then we subtract the time zone offset + // Different versions of boost accept slightly different things. Earlier versions + // seem to accept only a date as valid, whereas later versions do not. We want the + // string to always denote the full timestamp so we check for a colon and if it is + // not present then assume the time has not been given + if(time.find(":") == std::string::npos) + throw std::invalid_argument("Error interpreting string '" + str + "' as a date/time."); try { if (positive_offset) @@ -506,7 +512,7 @@ void DateAndTime::setFromISO8601(const std::string str) catch (std::exception &) { // Re-throw a more helpful error message - throw std::invalid_argument("Error interpreting string '" + time + "' as a date/time."); + throw std::invalid_argument("Error interpreting string '" + str + "' as a date/time."); } } diff --git a/Code/Mantid/Framework/Kernel/src/DateTimeValidator.cpp b/Code/Mantid/Framework/Kernel/src/DateTimeValidator.cpp new file mode 100644 index 000000000000..228339ce9e2f --- /dev/null +++ b/Code/Mantid/Framework/Kernel/src/DateTimeValidator.cpp @@ -0,0 +1,47 @@ +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidKernel/DateTimeValidator.h" +#include "MantidKernel/DateAndTime.h" + + +namespace Mantid +{ + namespace Kernel + { + + /** + * @return A clone of the current state of the validator + */ + IValidator_sptr DateTimeValidator::clone() const + { + return boost::make_shared(*this); + } + + + /** + * @param value A string to check for an ISO formatted timestamp + * @return An empty string if the value is valid or an string containing + * a description of the error otherwise + */ + std::string DateTimeValidator::checkValidity(const std::string& value) const + { + // simply pass off the work DateAndTime constructor + // the DateAndTime::stringIsISO8601 does not seem strict enough, it accepts + // empty strings & strings of letters! + std::string error(""); + try + { + DateAndTime timestamp(value); + UNUSED_ARG(timestamp); + } + catch(std::invalid_argument& exc) + { + error = exc.what(); + } + return error; + } + + } +} + diff --git a/Code/Mantid/Framework/Kernel/src/Interpolation.cpp b/Code/Mantid/Framework/Kernel/src/Interpolation.cpp index dcbc771ee25d..c17f4d6ca6b5 100644 --- a/Code/Mantid/Framework/Kernel/src/Interpolation.cpp +++ b/Code/Mantid/Framework/Kernel/src/Interpolation.cpp @@ -55,7 +55,7 @@ namespace Kernel if ( at >= m_x[N-1] ) { - return m_y[N-1]+(at-m_y[N-1])*(m_y[N-1]-m_y[N-2])/(m_x[N-1]-m_x[N-2]); + return m_y[N-1]+(at-m_x[N-1])*(m_y[N-1]-m_y[N-2])/(m_x[N-1]-m_x[N-2]); } // otherwise diff --git a/Code/Mantid/Framework/Kernel/src/Logger.cpp b/Code/Mantid/Framework/Kernel/src/Logger.cpp index 9fc52b92c941..7882bef82024 100644 --- a/Code/Mantid/Framework/Kernel/src/Logger.cpp +++ b/Code/Mantid/Framework/Kernel/src/Logger.cpp @@ -215,6 +215,7 @@ namespace Kernel } } + int Logger::getLevel() const { return m_log->getLevel(); diff --git a/Code/Mantid/Framework/Kernel/test/DateTimeValidatorTest.h b/Code/Mantid/Framework/Kernel/test/DateTimeValidatorTest.h new file mode 100644 index 000000000000..0accbdb2f0f9 --- /dev/null +++ b/Code/Mantid/Framework/Kernel/test/DateTimeValidatorTest.h @@ -0,0 +1,70 @@ +#ifndef MANTID_KERNEL_DATETIMEVALIDATORTEST_H_ +#define MANTID_KERNEL_DATETIMEVALIDATORTEST_H_ + +#include + +#include "MantidKernel/DateTimeValidator.h" + +using Mantid::Kernel::DateTimeValidator; + +class DateTimeValidatorTest : 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 DateTimeValidatorTest *createSuite() { return new DateTimeValidatorTest(); } + static void destroySuite( DateTimeValidatorTest *suite ) { delete suite; } + + //---------------------------- Success cases -------------------------------------- + + void test_full_extended_iso_format_is_accepted() + { + DateTimeValidator validator; + const std::string input = "2014-03-21T00:01:30.52"; + TS_ASSERT_EQUALS("", validator.isValid(input)); + } + + void test_time_without_fractional_seconds_in_iso_format_is_accepted() + { + DateTimeValidator validator; + const std::string input = "2014-03-21T00:01:30"; + TS_ASSERT_EQUALS("", validator.isValid(input)); + } + + + //---------------------------- Failure cases -------------------------------------- + + void test_empty_string_is_invalid() + { + DateTimeValidator validator; + TS_ASSERT_EQUALS("Error interpreting string '' as a date/time.", validator.isValid("")); + } + + void test_text_string_is_invalid() + { + DateTimeValidator validator; + const std::string input = "not a timestamp"; + const std::string error = "Error interpreting string '" + input + "' as a date/time."; + TS_ASSERT_EQUALS(error, validator.isValid(input)); + } + + void test_date_alone_is_invalid() + { + DateTimeValidator validator; + const std::string input = "2014-03-21"; + const std::string error = "Error interpreting string '" + input + "' as a date/time."; + TS_ASSERT_EQUALS(error, validator.isValid(input)); + } + + void test_time_alone_is_invalid() + { + DateTimeValidator validator; + const std::string input = "09:03:30"; + const std::string error = "Error interpreting string '" + input + "' as a date/time."; + TS_ASSERT_EQUALS(error, validator.isValid(input)); + } + +}; + + +#endif /* MANTID_KERNEL_DATETIMEVALIDATORTEST_H_ */ diff --git a/Code/Mantid/Framework/Kernel/test/InterpolationTest.h b/Code/Mantid/Framework/Kernel/test/InterpolationTest.h index 462350cb4c76..b8e22fff1012 100644 --- a/Code/Mantid/Framework/Kernel/test/InterpolationTest.h +++ b/Code/Mantid/Framework/Kernel/test/InterpolationTest.h @@ -28,11 +28,12 @@ class InterpolationTest : public CxxTest::TestSuite // Test that all the base class member variables are correctly assigned to TS_ASSERT_DELTA( interpolation.value(100), -950.0 ,0.000000001); - TS_ASSERT_DELTA( interpolation.value(3000), 260400.0 ,0.000000001); + TS_ASSERT_DELTA( interpolation.value(3000), 280000.0 ,0.000000001); TS_ASSERT_DELTA( interpolation.value(200.5), 55.0 ,0.000000001); TS_ASSERT_DELTA( interpolation.value(201.25), 70.0 ,0.000000001); TS_ASSERT_DELTA( interpolation.value(203.5), 350.0 ,0.000000001); + TS_ASSERT_EQUALS(interpolation.value(204.0), 400.0); interpolation.setXUnit("Wavelength"); interpolation.setYUnit("dSpacing"); @@ -49,11 +50,11 @@ class InterpolationTest : public CxxTest::TestSuite // Test that all the base class member variables are correctly assigned to TS_ASSERT_DELTA( readIn.value(100), -950.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(3000), 260400.0 ,0.000000001); + TS_ASSERT_DELTA( readIn.value(3000), 280000.0 ,0.000000001); TS_ASSERT_DELTA( readIn.value(200.5), 55.0 ,0.000000001); TS_ASSERT_DELTA( readIn.value(201.25), 70.0 ,0.000000001); - TS_ASSERT_DELTA( readIn.value(203.5), 350.0 ,0.000000001); - } + TS_ASSERT_DELTA( readIn.value(203.5), 350.0 ,0.000000001); + } void testEmpty() { diff --git a/Code/Mantid/Framework/Kernel/test/LoggerTest.h b/Code/Mantid/Framework/Kernel/test/LoggerTest.h index 7e6bc7a7c15b..e27034dbc06e 100644 --- a/Code/Mantid/Framework/Kernel/test/LoggerTest.h +++ b/Code/Mantid/Framework/Kernel/test/LoggerTest.h @@ -79,6 +79,7 @@ class LoggerTest : public CxxTest::TestSuite log.information() << "Information Message" << std::endl; } + //--------------------------------------------------------------------------- /** Log very quickly from a lot of OpenMP threads*/ void test_OpenMP_ParallelLogging() diff --git a/Code/Mantid/Framework/MDAlgorithms/src/PreprocessDetectorsToMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/PreprocessDetectorsToMD.cpp index 85ed1b68dff9..473eff403fe0 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/PreprocessDetectorsToMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/PreprocessDetectorsToMD.cpp @@ -253,8 +253,8 @@ namespace Mantid Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); //this->pBaseInstr = instrument->baseInstrument(); // - Geometry::IObjComponent_const_sptr source = instrument->getSource(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if ((!source) || (!sample)) { g_log.error()<<" Instrument is not fully defined. Can not identify source or sample\n"; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp index ebec09716e3c..d08bace22235 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/CachedExperimentInfo.cpp @@ -154,8 +154,8 @@ namespace Mantid m_up = refFrame->pointingUp(); m_horiz = refFrame->pointingHorizontal(); - IObjComponent_const_sptr source = instrument->getSource(); - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr sample = instrument->getSample(); IComponent_const_sptr aperture = instrument->getComponentByName("aperture", 1); if(!aperture) { diff --git a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/ModeratorChopperResolution.cpp b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/ModeratorChopperResolution.cpp index a4d20946ea19..0eb450474fb7 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/ModeratorChopperResolution.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/Quantification/Resolution/ModeratorChopperResolution.cpp @@ -12,6 +12,7 @@ namespace Mantid { using Geometry::Instrument_const_sptr; using Geometry::IObjComponent_const_sptr; + using Geometry::IComponent_const_sptr; using Geometry::IDetector_const_sptr; /** @@ -78,7 +79,7 @@ namespace Mantid void ModeratorChopperResolution::initCaches() { Instrument_const_sptr instr = m_observation.experimentInfo().getInstrument(); - IObjComponent_const_sptr source = instr->getSource(); + IComponent_const_sptr source = instr->getSource(); m_modChopDist = m_observation.moderatorToFirstChopperDistance(); m_chopSampleDist = m_observation.firstChopperToSampleDistance(); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ThresholdMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ThresholdMD.cpp index 91b3bea28327..a0f7c342c84a 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/ThresholdMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/ThresholdMD.cpp @@ -1,6 +1,8 @@ /*WIKI* - Threshold an MDHistoWorkspace to overwrite values below or above the defined threshold. - *WIKI*/ + +Threshold an MDHistoWorkspace to overwrite values below or above the defined threshold. + +*WIKI*/ #include "MantidMDAlgorithms/ThresholdMD.h" #include "MantidAPI/WorkspaceProperty.h" diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/FitMD.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/FitMD.h index 593db91c2d03..a999eb6a61f8 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/FitMD.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/FitMD.h @@ -65,10 +65,11 @@ namespace Mantid virtual void createDomain( boost::shared_ptr&, boost::shared_ptr&, size_t i0); - virtual void createOutputWorkspace(const std::string& baseName, + virtual boost::shared_ptr createOutputWorkspace(const std::string& baseName, API::IFunction_sptr function, boost::shared_ptr domain, - boost::shared_ptr values); + boost::shared_ptr values, + const std::string& outputWorkspacePropertyName = "OutputWorkspace"); /// Return the size of the domain to be created. virtual size_t getDomainSize() const; diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDBoxIterator.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDBoxIterator.h index 875bc83d25ce..c42b19193878 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDBoxIterator.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDBoxIterator.h @@ -87,6 +87,8 @@ namespace MDEvents virtual std::vector findNeighbourIndexes() const; + virtual size_t getLinearIndex() const; + private: /// Common code run my a few of the constructors. diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspaceIterator.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspaceIterator.h index 668402e1ec33..751c266b2c7b 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspaceIterator.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspaceIterator.h @@ -94,7 +94,7 @@ namespace MDEvents virtual bool getIsMasked() const; - size_t getLinearIndex() const; + virtual size_t getLinearIndex() const; std::vector findNeighbourIndexes() const; diff --git a/Code/Mantid/Framework/MDEvents/src/FitMD.cpp b/Code/Mantid/Framework/MDEvents/src/FitMD.cpp index d618066eb859..6134e89d3d5a 100644 --- a/Code/Mantid/Framework/MDEvents/src/FitMD.cpp +++ b/Code/Mantid/Framework/MDEvents/src/FitMD.cpp @@ -136,27 +136,29 @@ namespace Mantid * @param function :: The function used for the calculation * @param domain :: A pointer to the input domain * @param ivalues :: A pointer to the calculated values + * @param outputWorkspacePropertyName :: The property name */ - void FitMD::createOutputWorkspace(const std::string& baseName, + boost::shared_ptr FitMD::createOutputWorkspace(const std::string& baseName, API::IFunction_sptr, boost::shared_ptr domain, - boost::shared_ptr ivalues) + boost::shared_ptr ivalues, + const std::string& outputWorkspacePropertyName) { auto values = boost::dynamic_pointer_cast(ivalues); if (!values) { - return; + return boost::shared_ptr(); } auto functionMD = boost::dynamic_pointer_cast(domain); if(!functionMD) { - return; + return boost::shared_ptr(); } API::IMDWorkspace_const_sptr domainWS = functionMD->getWorkspace(); auto inputWS = boost::dynamic_pointer_cast(domainWS); if(!inputWS) { - return; + return boost::shared_ptr(); } auto outputWS = MDEventFactory::CreateMDWorkspace(inputWS->getNumDims(), "MDEvent"); // Add events @@ -164,7 +166,7 @@ namespace Mantid auto mdWS = boost::dynamic_pointer_cast,4> >(outputWS); if(!mdWS) { - return; + return boost::shared_ptr(); } // Bins extents and meta data @@ -223,10 +225,15 @@ namespace Mantid API::MemoryManager::Instance().releaseFreeMemory(); // Store it - declareProperty(new API::WorkspaceProperty("OutputWorkspace","",Direction::Output), - "Name of the output Workspace holding resulting simulated spectrum"); - m_manager->setPropertyValue("OutputWorkspace",baseName+"Workspace"); - m_manager->setProperty("OutputWorkspace",outputWS); + if ( !outputWorkspacePropertyName.empty() ) + { + declareProperty(new API::WorkspaceProperty(outputWorkspacePropertyName,"",Direction::Output), + "Name of the output Workspace holding resulting simulated spectrum"); + m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspace"); + m_manager->setProperty(outputWorkspacePropertyName,outputWS); + } + + return outputWS; } /** diff --git a/Code/Mantid/Framework/MDEvents/src/MDBoxIterator.cpp b/Code/Mantid/Framework/MDEvents/src/MDBoxIterator.cpp index 6aed2fbd2338..06a0fa2d1584 100644 --- a/Code/Mantid/Framework/MDEvents/src/MDBoxIterator.cpp +++ b/Code/Mantid/Framework/MDEvents/src/MDBoxIterator.cpp @@ -372,6 +372,11 @@ namespace MDEvents throw std::runtime_error("MDBoxIterator does not implement findNeighbourIndex"); } + TMDE( size_t MDBoxIterator)::getLinearIndex() const + { + throw std::runtime_error("MDBoxIterator does not implement getLinearIndex"); + } + } // namespace Mantid } // namespace MDEvents diff --git a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp index f4df24cf451d..824b9d9c4a44 100644 --- a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp +++ b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspaceIterator.cpp @@ -149,8 +149,29 @@ namespace MDEvents next(); } + // --- Calculate index permutations for neighbour finding --- auto temp = std::vector(integerPower(3, m_nd), 0); m_permutations.swap(temp); + + int64_t offset = 1; + m_permutations[0] = 0; + m_permutations[1] = 1; + m_permutations[2] = -1; + + // Figure out what possible indexes deltas to generate indexes that are next to the current one. + size_t nPermutations = 3; + for(size_t j = 1; j < m_nd; ++j) + { + offset = offset * static_cast( m_ws->getDimension(j-1)->getNBins() ); + size_t counter = nPermutations; + for(size_t k = 0; k ( m_ws->getDimension(j-1)->getNBins() ); - size_t counter = nPermutations; - for(size_t k = 0; k neighbourIndexes; // Accumulate neighbour indexes. - for(size_t i = 0; i < nPermutations; ++i) + for(size_t i = 0; i < m_permutations.size(); ++i) { if (m_permutations[i] == 0) { diff --git a/Code/Mantid/Framework/MDEvents/test/FitMDTest.h b/Code/Mantid/Framework/MDEvents/test/FitMDTest.h index 71b16b38a07a..3884d0ace900 100644 --- a/Code/Mantid/Framework/MDEvents/test/FitMDTest.h +++ b/Code/Mantid/Framework/MDEvents/test/FitMDTest.h @@ -46,6 +46,7 @@ class IMDWorkspaceTesterIterator: public IMDIterator virtual signal_t getInnerError(size_t ) const {return 0;} virtual bool getIsMasked() const {return false;} virtual std::vector findNeighbourIndexes() const {throw std::runtime_error("findNeighbourIndexes not implemented on IMDWorkspaceTesterIterator");} + virtual size_t getLinearIndex() const {throw std::runtime_error("getLinearIndex not implemented on IMDWorkspaceTesterIterator");} }; class IMDWorkspaceTester: public WorkspaceTester diff --git a/Code/Mantid/Framework/MDEvents/test/MDBoxSaveableTest.h b/Code/Mantid/Framework/MDEvents/test/MDBoxSaveableTest.h index 07b9a95be94c..1e52e7d5c5ed 100644 --- a/Code/Mantid/Framework/MDEvents/test/MDBoxSaveableTest.h +++ b/Code/Mantid/Framework/MDEvents/test/MDBoxSaveableTest.h @@ -199,7 +199,7 @@ static void destroySuite(MDBoxSaveableTest * suite) { delete suite; } MDBox,3> c(sc.get()); TS_ASSERT_EQUALS( c.getNPoints(), 0); - auto loader =boost::shared_ptr(new MantidTestHelpers::BoxControllerDummyIO(sc)); + auto loader =boost::shared_ptr(new MantidTestHelpers::BoxControllerDummyIO(sc.get())); loader->setDataType(c.getCoordType(),c.getEventType()); // Create and open the test dummy file with 1000 floats in it (have to recalulate to events differently) @@ -283,16 +283,17 @@ static void destroySuite(MDBoxSaveableTest * suite) { delete suite; } void test_fileBackEnd_addEvent() { // Create a box with a controller for the back-end - BoxController_sptr bc(new BoxController(3)); + // Create on stack to ensure it's cleaned up properly. Its lifetime is sure to exceed those of the things that use it. + BoxController bc(3); // Create and open the test NXS file - MDBox,3> c(bc.get(), 0); - auto loader =boost::shared_ptr(new MantidTestHelpers::BoxControllerDummyIO(bc)); + MDBox,3> c(&bc, 0); + auto loader = boost::shared_ptr(new MantidTestHelpers::BoxControllerDummyIO(&bc)); loader->setDataType(c.getCoordType(),c.getEventType()); loader->setWriteBufferSize(10000); // Create and open the test dummy file with 1000 floats in it - bc->setFileBacked(loader,"existingDummy"); + bc.setFileBacked(loader,"existingDummy"); c.setFileBacked(0,1000,true); @@ -882,4 +883,4 @@ static void destroySuite(MDBoxSaveableTest * suite) { delete suite; } }; -#endif \ No newline at end of file +#endif diff --git a/Code/Mantid/Framework/Properties/Mantid.properties.template b/Code/Mantid/Framework/Properties/Mantid.properties.template index 2121e46aa0ad..7fc4798e6fc8 100644 --- a/Code/Mantid/Framework/Properties/Mantid.properties.template +++ b/Code/Mantid/Framework/Properties/Mantid.properties.template @@ -206,3 +206,6 @@ ScriptRepositoryIgnore = *pyc; # The ability to send a job to a cluster form the reduction UIs is turned off. Set it to 'On' to enable it. cluster.submission=Off + +# Used to stop a catalog asynchronous algorithm after the timeout period +catalog.timeout.value=30 diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h similarity index 55% rename from Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h rename to Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h index cbbd5ec7cbb6..3615bc3bb684 100644 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h @@ -1,5 +1,5 @@ -#ifndef MANTID_PYTHONINTERFACE_ALGORITHMWRAPPER_H_ -#define MANTID_PYTHONINTERFACE_ALGORITHMWRAPPER_H_ +#ifndef MANTID_PYTHONINTERFACE_ALGORITHMADAPTER_H_ +#define MANTID_PYTHONINTERFACE_ALGORITHMADAPTER_H_ /** Copyright © 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory @@ -24,7 +24,8 @@ //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- -#include "MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h" +#include "MantidAPI/Algorithm.h" + #include "MantidKernel/ClassMacros.h" #include #include @@ -36,16 +37,19 @@ namespace Mantid /** * Provides a layer class for boost::python to allow C++ virtual functions - * to be overridden in a Python object that is derived from PythonAlgorithm. + * to be overridden in a Python object that is derived an Algorithm. * - * It works in tandem with the PythonAlgorithm class. This is essentially - * a transparent layer that handles the function calls up into Python. + * The templated-base class provides a mechanism to reuse the same adapter + * class for other classes that inherit from a different Algorithm sub class */ - class AlgorithmWrapper : public PythonAlgorithm + template + class AlgorithmAdapter : public BaseAlgorithm { + typedef BaseAlgorithm SuperClass; + public: /// A constructor that looks like a Python __init__ method - AlgorithmWrapper(PyObject* self); + AlgorithmAdapter(PyObject* self); /** @name Algorithm virtual methods */ ///@{ @@ -67,21 +71,46 @@ namespace Mantid std::map validateInputs(); ///@} + /** @name Property declarations + * The first function matches the base-classes signature so a different + * name is used consistently to avoid accidentally calling the wrong function internally + * From Python they will still be called declareProperty + */ + ///@{ + /// Declare a specialized property + static void declarePyAlgProperty(boost::python::object & self, Kernel::Property *prop, const std::string &doc = ""); + /// Declare a property using the type of the defaultValue with a validator and doc string + static void declarePyAlgProperty(boost::python::object & self, const std::string & name, const boost::python::object & defaultValue, + const boost::python::object & validator = boost::python::object(), + const std::string & doc = "", const int direction = Kernel::Direction::Input); + + /// Declare a property with a documentation string + static void declarePyAlgProperty(boost::python::object & self, const std::string & name, const boost::python::object & defaultValue, + const std::string & doc, const int direction = Kernel::Direction::Input); + + /// Declare a property using the type of the defaultValue + static void declarePyAlgProperty(boost::python::object & self, const std::string & name, const boost::python::object & defaultValue, + const int direction); + + protected: + /** + * Returns the PyObject that owns this wrapper, i.e. self + * @returns A pointer to self + */ + inline PyObject * getSelf() const { return m_self; } + private: /// The PyObject must be supplied to construct the object - DISABLE_DEFAULT_CONSTRUCT(AlgorithmWrapper); - DISABLE_COPY_AND_ASSIGN(AlgorithmWrapper); + DISABLE_DEFAULT_CONSTRUCT(AlgorithmAdapter); + DISABLE_COPY_AND_ASSIGN(AlgorithmAdapter); /// Private init for this algorithm virtual void init(); /// Private exec for this algorithm virtual void exec(); - /** - * Returns the PyObject that owns this wrapper, i.e. self - * @returns A pointer to self - */ - inline PyObject * getSelf() const { return m_self; } + /// We don't want the base class versions + using SuperClass::declareProperty; /// The Python portion of the object PyObject *m_self; @@ -92,4 +121,4 @@ namespace Mantid } -#endif /* MANTID_PYTHONINTERFACE_ALGORITHMWRAPPER_H_ */ +#endif /* MANTID_PYTHONINTERFACE_ALGORITHMADAPTER_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/DataProcessorAdapter.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/DataProcessorAdapter.h new file mode 100644 index 000000000000..8b9f93529cd3 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/DataProcessorAdapter.h @@ -0,0 +1,101 @@ +#ifndef MANTID_PYTHON_INTERFACE_DATAPROCESSORADAPTER_H +#define MANTID_PYTHON_INTERFACE_DATAPROCESSORADAPTER_H +/** + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: . + Code Documentation is available at: + */ +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h" +#include "MantidAPI/DataProcessorAlgorithm.h" + +namespace Mantid +{ + namespace PythonInterface + { + /** + * Provides a layer class for boost::python to allow C++ virtual functions + * to be overridden in a Python object that is derived an DataProcessorAlgorithm. + * + * It also provides access to the protected methods on DataProcessorAlgorithm + * from the type exported to Python + */ + class DataProcessorAdapter : public AlgorithmAdapter + { + typedef AlgorithmAdapter SuperClass; + + public: + /// A constructor that looks like a Python __init__ method + DataProcessorAdapter(PyObject* self); + + // -------------------- Pass through methods ---------------------------- + // Boost.python needs public access to the base class methods in order to + // be able to call them. We should just be able to put a using declaration + // to raise the methods to public but this does not work on MSVC as in + // the class_ definition it can't seem to figure out that its calling + // this class not DataProcessorAlgorithm. This means we have to resort to + // proxy methods :( + + void setLoadAlgProxy(const std::string & alg) { this->setLoadAlg(alg); } + + void setLoadAlgFilePropProxy(const std::string & filePropName) { this->setLoadAlgFileProp(filePropName); } + + void setAccumAlgProxy(const std::string & alg) { this->setAccumAlg(alg); } + + API::ITableWorkspace_sptr determineChunkProxy() { return this->determineChunk(); } + + void loadChunkProxy() { this->loadChunk(); } + + API::Workspace_sptr loadProxy(const std::string &inputData, const bool loadQuiet = false) { return this->load(inputData, loadQuiet); } + + std::vector splitInputProxy(const std::string & input) { return this->splitInput(input); } + + void forwardPropertiesProxy() { this->forwardProperties(); } + + boost::shared_ptr getProcessPropertiesProxy(const std::string &propertyManager) + { + return this->getProcessProperties(propertyManager); + } + + API::Workspace_sptr assembleProxy(const std::string &partialWSName, const std::string &outputWSName) + { + return this->assemble(partialWSName, outputWSName); + } + void saveNexusProxy(const std::string &outputWSName, const std::string &outputFile) + { + this->saveNexus(outputWSName, outputFile); + } + + bool isMainThreadProxy() { return this->isMainThread(); } + + int getNThreadsProxy() { return this->getNThreads(); } + // ------------------------------------------------------------------------ + + private: + /// The PyObject must be supplied to construct the object + DISABLE_DEFAULT_CONSTRUCT(DataProcessorAdapter); + DISABLE_COPY_AND_ASSIGN(DataProcessorAdapter); + }; + + } +} + +#endif // MANTID_PYTHON_INTERFACE_DATAPROCESSORADAPTER_H diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h deleted file mode 100644 index 8b96430178d0..000000000000 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MANTID_PYTHONINTERFACE_PYTHONALGORITHM_H_ -#define MANTID_PYTHONINTERFACE_PYTHONALGORITHM_H_ -/** - 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 . - - File change history is stored at: . - Code Documentation is available at: - */ -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- -#include "MantidKernel/System.h" -#include "MantidAPI/Algorithm.h" - -#include - -namespace Mantid -{ - namespace PythonInterface - { - /** - * Provides a class that forms an interface between a Python algorithm - * and a C++ algorithm. - * - * It defines several functions for declaring properties that handle the - * fact that the type is only known at runtime - * - * It works in tandem with the AlgorithmWrapper such that - * when the AlgorithmWrapper is exported to Python - * a user sees the PythonAlgorithm class. - */ - class PythonAlgorithm : public API::Algorithm - { - public: - /** @name Property declarations - * The first function matches the base-classes signature so a different - * name is used consistently to avoid accidentally calling the wrong function internally - * From Python they will still be called declareProperty - */ - ///@{ - /// Declare a specialized property - void declarePyAlgProperty(Kernel::Property *prop, const std::string &doc=""); - /// Declare a property using the type of the defaultValue with a validator and doc string - void declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const boost::python::object & validator = boost::python::object(), - const std::string & doc = "", const int direction = Kernel::Direction::Input); - - /// Declare a property with a documentation string - void declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const std::string & doc, const int direction = Kernel::Direction::Input); - - /// Declare a property using the type of the defaultValue - void declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const int direction); - ///@} - private: - // Hide the base class variants as they are not required on this interface - using Mantid::API::Algorithm::declareProperty; - }; - - } -} - - - -#endif /* MANTID_PYTHONINTERFACE_PYTHONALGORITHM_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Environment/CallStack.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Environment/CallStack.h deleted file mode 100644 index ee2fcf538ea7..000000000000 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Environment/CallStack.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef MANTID_PYTHONINTERFACE_PYENVIRONMENT_H_ -#define MANTID_PYTHONINTERFACE_PYENVIRONMENT_H_ -/* - 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 . - - File change history is stored at: . - Code Documentation is available at: - */ -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- -#include "MantidKernel/System.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct _frame; - -namespace Mantid -{ - namespace PythonInterface - { - namespace Environment - { - /// Is the given function name in the call stack - DLLExport bool isInCallStack(const char * name, _frame* startFrame = NULL); - } - } -} - - - -#endif /* MANTID_PYTHONINTERFACE_PYENVIRONMENT_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt index 2a8045208668..08fe03210589 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt @@ -9,9 +9,10 @@ set ( MODULE_TEMPLATE src/api.cpp.in ) # definitions occur and some depend on their base classes being exported first -- set ( EXPORT_FILES src/Exports/IAlgorithm.cpp - src/Exports/Algorithm.cpp + src/Exports/AlgorithmProxy.cpp src/Exports/DeprecatedAlgorithmChecker.cpp - src/Exports/PythonAlgorithmExport.cpp + src/Exports/Algorithm.cpp + src/Exports/DataProcessorAlgorithm.cpp src/Exports/AlgorithmFactory.cpp src/Exports/AlgorithmManager.cpp src/Exports/AnalysisDataService.cpp @@ -69,8 +70,8 @@ set ( SRC_FILES src/FitFunctions/IFunctionAdapter.cpp src/FitFunctions/IFunction1DAdapter.cpp src/FitFunctions/IPeakFunctionAdapter.cpp - src/PythonAlgorithm/AlgorithmWrapper.cpp - src/PythonAlgorithm/PythonAlgorithm.cpp + src/PythonAlgorithm/AlgorithmAdapter.cpp + src/PythonAlgorithm/DataProcessorAdapter.cpp src/CloneMatrixWorkspace.cpp ) @@ -79,8 +80,8 @@ set ( INC_FILES ${HEADER_DIR}/api/FitFunctions/IFunctionAdapter.h ${HEADER_DIR}/api/FitFunctions/IFunction1DAdapter.h ${HEADER_DIR}/api/FitFunctions/IPeakFunctionAdapter.h - ${HEADER_DIR}/api/PythonAlgorithm/AlgorithmWrapper.h - ${HEADER_DIR}/api/PythonAlgorithm/PythonAlgorithm.h + ${HEADER_DIR}/api/PythonAlgorithm/AlgorithmAdapter.h + ${HEADER_DIR}/api/PythonAlgorithm/DataProcessorAdapter.h ${HEADER_DIR}/api/BinaryOperations.h ${HEADER_DIR}/api/CloneMatrixWorkspace.h ${HEADER_DIR}/api/WorkspacePropertyExporter.h diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/_workspaceops.py b/Code/Mantid/Framework/PythonInterface/mantid/api/_workspaceops.py index 55ee50f0cd5e..7c9876a659e9 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/_workspaceops.py +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/_workspaceops.py @@ -136,6 +136,7 @@ def _do_unary_operation(op, self, lhs_vars): their names as the first and second element respectively """ global _workspace_op_tmps + import mantid.simpleapi as simpleapi if lhs_vars[0] > 0: # Assume the first and clear the temporaries as this @@ -150,9 +151,8 @@ def _do_unary_operation(op, self, lhs_vars): # Do the operation ads = _api.AnalysisDataServiceImpl.Instance() - fmgr = _api.FrameworkManagerImpl.Instance() - alg = fmgr.createAlgorithm(op) + alg = simpleapi._create_algorithm_object(op) # gets the child status correct for PythonAlgorithms alg.setPropertyValue("InputWorkspace", self.name()) alg.setPropertyValue("OutputWorkspace", output_name) alg.execute() @@ -225,4 +225,4 @@ def _method_impl(self, *args, **kwargs): cls = getattr(_api, typename) setattr(cls, name, _method_impl) else: - setattr(_api.Workspace, name, _method_impl) \ No newline at end of file + setattr(_api.Workspace, name, _method_impl) diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithms/RunPythonScript.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithms/RunPythonScript.cpp index 5e8efe6f5f1f..876cae241d58 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithms/RunPythonScript.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithms/RunPythonScript.cpp @@ -81,9 +81,9 @@ namespace Mantid /** * Builds the code string from the user input. The user script is wrapped - * in a PyExec function to 'fool' the Python FrameworkManager into + * in a tiny PythonAlgorithm to 'fool' the Python framework into * creating a child algorithm for each algorithm that is run. See - * PythonInterface/mantid/api/src/Exports/FrameworkManager.cpp + * PythonInterface/mantid/simpleapi.py:_create_algorithm_object * This has to be the case to get the workspace locking correct. * * The code assumes that the scope in which it is executed has defined @@ -101,15 +101,20 @@ namespace Mantid // Wrap and indent the user code (see method documentation) std::istringstream is(userCode); std::ostringstream os; - os << "from mantid.simpleapi import *\n" - << "def PyExec(input=None,output=None):\n"; + const char * indent = " "; + os << "import mantid\n" + << "from mantid.simpleapi import *\n" + << "class _DUMMY_ALG(mantid.api.PythonAlgorithm):\n" + << indent << "def PyExec(self, input=None,output=None):\n"; std::string line; while(getline(is, line)) { - os << " " << line << "\n"; + os << indent << indent << line << "\n"; } - os << " return input,output\n"; // When executed the global scope needs to know about input,output so we return them - os << "input,output = PyExec(input,output)"; + os << indent << indent << "return input,output\n"; // When executed the global scope needs to know about input,output so we return them + os << "input,output = _DUMMY_ALG().PyExec(input,output)"; + + if(g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) g_log.debug() << "Full code to be executed:\n" << os.str() << "\n"; return os.str(); } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/Algorithm.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/Algorithm.cpp index 27e1ce60cdd0..5bc3659a584b 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/Algorithm.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/Algorithm.cpp @@ -1,36 +1,89 @@ #ifdef _MSC_VER #pragma warning( disable: 4250 ) // Disable warning regarding inheritance via dominance, we have no way around it with the design #endif -#include "MantidAPI/AlgorithmProxy.h" -#include "MantidAPI/Algorithm.h" +#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h" +#ifdef _MSC_VER + #pragma warning( default: 4250 ) +#endif +#include #include +#include #include +#include -using namespace Mantid::API; +using Mantid::API::Algorithm; +using Mantid::PythonInterface::AlgorithmAdapter; +using Mantid::Kernel::Direction; using namespace boost::python; -void export_algorithm() +namespace +{ + typedef AlgorithmAdapter PythonAlgorithm; + + // declarePyAlgProperty(property*,doc) + typedef void(*declarePropertyType1)(boost::python::object & self, Mantid::Kernel::Property*, const std::string &); + // declarePyAlgProperty(name, defaultValue, validator, doc, direction) + typedef void(*declarePropertyType2)(boost::python::object & self, const std::string &, const boost::python::object &, + const boost::python::object &, const std::string &, const int); + // declarePyAlgProperty(name, defaultValue, doc, direction) + typedef void(*declarePropertyType3)(boost::python::object & self, const std::string &, const boost::python::object &, + const std::string &, const int); + // declarePyAlgProperty(name, defaultValue, direction) + typedef void(*declarePropertyType4)(boost::python::object & self, const std::string &, const boost::python::object &, const int); + + // Overload types + BOOST_PYTHON_FUNCTION_OVERLOADS(declarePropertyType1_Overload, PythonAlgorithm::declarePyAlgProperty, 2, 3); + BOOST_PYTHON_FUNCTION_OVERLOADS(declarePropertyType2_Overload, PythonAlgorithm::declarePyAlgProperty, 3, 6); + BOOST_PYTHON_FUNCTION_OVERLOADS(declarePropertyType3_Overload, PythonAlgorithm::declarePyAlgProperty, 4, 5); +} + +void export_leaf_classes() { + register_ptr_to_python>(); - class_, boost::noncopyable>("Algorithm", "Base-class for C algorithms", no_init) + // Export Algorithm but the actual held type in Python is boost::shared_ptr + // See http://wiki.python.org/moin/boost.python/HowTo#ownership_of_C.2B-.2B-_object_extended_in_Python + + class_, boost::shared_ptr, + boost::noncopyable>("Algorithm", "Base class for all algorithms") .def("fromString", &Algorithm::fromString, "Initialize the algorithm from a string representation") .staticmethod("fromString") - + .def("setOptionalMessage", &Algorithm::setOptionalMessage) - .def("createChildAlgorithm", &Algorithm::createChildAlgorithm, + .def("createChildAlgorithm", &Algorithm::createChildAlgorithm, (arg("name"),arg("startProgress")=-1.0,arg("endProgress")=-1.0, arg("enableLogging")=true,arg("version")=-1), "Creates and intializes a named child algorithm. Output workspaces are given a dummy name.") - ; + .def("declareProperty", (declarePropertyType1)&PythonAlgorithm::declarePyAlgProperty, + declarePropertyType1_Overload((arg("self"), arg("prop"), arg("doc") = ""))) - //---------------------------- AlgorithmProxy ---------------------------------- - register_ptr_to_python>(); + .def("declareProperty", (declarePropertyType2)&PythonAlgorithm::declarePyAlgProperty, + declarePropertyType2_Overload((arg("self"), arg("name"), arg("defaultValue"), arg("validator")=object(), arg("doc")="",arg("direction")=Direction::Input), + "Declares a named property where the type is taken from " + "the type of the defaultValue and mapped to an appropriate C++ type")) - class_, boost::noncopyable>("AlgorithmProxy", "Proxy class returned by managed algorithms", no_init); -} + .def("declareProperty", (declarePropertyType3)&PythonAlgorithm::declarePyAlgProperty, + declarePropertyType3_Overload((arg("self"), arg("name"), arg("defaultValue"), arg("doc")="",arg("direction")=Direction::Input), + "Declares a named property where the type is taken from the type " + "of the defaultValue and mapped to an appropriate C++ type")) -#ifdef _MSC_VER - #pragma warning( default: 4250 ) -#endif + .def("declareProperty", (declarePropertyType4)&PythonAlgorithm::declarePyAlgProperty, + (arg("self"), arg("name"), arg("defaultValue"), arg("direction")=Direction::Input), + "Declares a named property where the type is taken from the type " + "of the defaultValue and mapped to an appropriate C++ type") + + .def("getLogger", &PythonAlgorithm::getLogger, return_value_policy(), + "Returns a reference to this algorithm's logger") + .def("log", &PythonAlgorithm::getLogger, return_value_policy(), + "Returns a reference to this algorithm's logger") // Traditional name + ; + + // Prior to version 3.2 there was a separate C++ PythonAlgorithm class that inherited from Algorithm and the "PythonAlgorithm" + // name was a distinct class in Python from the Algorithm export. In 3.2 the need for the C++ PythonAlgorithm class + // was removed in favour of simply adapting the Algorithm base class. A lot of client code relies on the "PythonAlgorithm" name in + // Python so we simply add an alias of the Algorithm name to PythonAlgorithm + scope().attr("PythonAlgorithm") = scope().attr("Algorithm"); + +} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmFactory.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmFactory.cpp index d241f44b8a6a..4b9b34ab283c 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmFactory.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmFactory.cpp @@ -3,10 +3,10 @@ #include "MantidAPI/FileLoaderRegistry.h" #include "MantidKernel/WarningSuppressions.h" #include "MantidPythonInterface/kernel/PythonObjectInstantiator.h" -#include "MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h" #include #include +#include #include // Python frameobject. This is under the boost includes so that boost will have done the @@ -16,7 +16,6 @@ using namespace Mantid::API; using namespace boost::python; using Mantid::Kernel::AbstractInstantiator; -using Mantid::PythonInterface::PythonAlgorithm; using Mantid::PythonInterface::PythonObjectInstantiator; namespace @@ -74,7 +73,8 @@ GCC_DIAG_OFF(cast-qual) { Poco::ScopedLock lock(PYALG_REGISTER_MUTEX); - static PyObject * const pyAlgClass = (PyObject*)converter::registered::converters.to_python_target_type(); + static PyObject * const pyAlgClass = + (PyObject*)converter::registered::converters.to_python_target_type(); // obj could be or instance/class, check instance first PyObject *classObject(NULL); if( PyObject_IsInstance(obj.ptr(), pyAlgClass) ) @@ -87,7 +87,7 @@ GCC_DIAG_OFF(cast-qual) } else { - throw std::invalid_argument("Cannot register an algorithm that does not derive from PythonAlgorithm."); + throw std::invalid_argument("Cannot register an algorithm that does not derive from Algorithm."); } boost::python::object classType(handle<>(borrowed(classObject))); // Takes ownership of instantiator and replaces any existing algorithm @@ -97,6 +97,8 @@ GCC_DIAG_OFF(cast-qual) FileLoaderRegistry::Instance().unsubscribe(descr.first, descr.second); } + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(existsOverloader, exists, 1, 2); + ///@endcond } GCC_DIAG_ON(cast-qual) @@ -105,8 +107,14 @@ void export_AlgorithmFactory() { class_("AlgorithmFactoryImpl", no_init) + .def("exists", &AlgorithmFactoryImpl::exists, + existsOverloader((arg("name"), arg("version")=-1), + "Returns true if the given algorithm exists with an option to specify the version")) + .def("getRegisteredAlgorithms", &getRegisteredAlgorithms, "Returns a Python dictionary of currently registered algorithms") + .def("subscribe", &subscribe, "Register a Python class derived from PythonAlgorithm into the factory") + .def("Instance", &AlgorithmFactory::Instance, return_value_policy(), "Returns a reference to the AlgorithmFactory singleton") .staticmethod("Instance") diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmProxy.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmProxy.cpp new file mode 100644 index 000000000000..34b4053367b6 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmProxy.cpp @@ -0,0 +1,24 @@ +#ifdef _MSC_VER + #pragma warning( disable: 4250 ) // Disable warning regarding inheritance via dominance, we have no way around it with the design +#endif +#include "MantidAPI/AlgorithmProxy.h" + +#include +#include + +using namespace Mantid::API; +using namespace boost::python; + +void export_algorithm_proxy() +{ + + register_ptr_to_python>(); + + // We do not require any additional methods here but some parts of the code specifically check that a proxy has + // been returned + class_, boost::noncopyable>("AlgorithmProxy", "Proxy class returned by managed algorithms", no_init); +} + +#ifdef _MSC_VER + #pragma warning( default: 4250 ) +#endif diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/DataProcessorAlgorithm.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/DataProcessorAlgorithm.cpp new file mode 100644 index 000000000000..a58493170a2e --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/DataProcessorAlgorithm.cpp @@ -0,0 +1,76 @@ +#include "MantidPythonInterface/api/PythonAlgorithm/DataProcessorAdapter.h" +#include "MantidPythonInterface/kernel/Policies/VectorToNumpy.h" +#include +#include + +using namespace Mantid::API; +using Mantid::Kernel::Direction; +using Mantid::PythonInterface::DataProcessorAdapter; +using namespace boost::python; + +namespace +{ + typedef Workspace_sptr(DataProcessorAdapter::*loadOverload1)(const std::string&); + typedef Workspace_sptr(DataProcessorAdapter::*loadOverload2)(const std::string&, const bool); +} + +void export_DataProcessorAlgorithm() +{ + // for strings will actually create a list + using Mantid::PythonInterface::Policies::VectorToNumpy; + + class_, boost::shared_ptr, + boost::noncopyable>("DataProcessorAlgorithm", "Base class workflow-type algorithms") + + .def("setLoadAlg", &DataProcessorAdapter::setLoadAlgProxy, + "Set the name of the algorithm called using the load() method [Default=Load]") + + .def("setLoadAlgFileProp", &DataProcessorAdapter::setLoadAlgFilePropProxy, + "Set the name of the file property for the load algorithm when using " + "the load() method [Default=Filename]") + + .def("setAccumAlg", &DataProcessorAdapter::setAccumAlgProxy, + "Set the name of the algorithm called to accumulate a chunk of processed data [Default=Plus]") + + .def("determineChunk", &DataProcessorAdapter::determineChunkProxy, + "Return a TableWorkspace containing the information on how to split the " + "input file when processing in chunks") + + .def("loadChunk", &DataProcessorAdapter::loadChunkProxy, + "Load a chunk of data") + + .def("load", (loadOverload1)&DataProcessorAdapter::loadProxy, + "Loads the given file or workspace data and returns the workspace. " + "The output is not stored in the AnalysisDataService.") + + .def("load", (loadOverload2)&DataProcessorAdapter::loadProxy, + "Loads the given file or workspace data and returns the workspace. " + "If loadQuiet=True then output is not stored in the AnalysisDataService.") + + .def("splitInput", &DataProcessorAdapter::splitInputProxy, + return_value_policy()) + + .def("forwardProperties", &DataProcessorAdapter::forwardPropertiesProxy) + + .def("getProcessProperties", &DataProcessorAdapter::getProcessPropertiesProxy, + "Returns the named property manager from the service or creates " + "a new one if it does not exist") + + .def("assemble", &DataProcessorAdapter::assembleProxy, + "If an MPI build, assemble the partial workspaces from all MPI processes. " + "Otherwise, simply returns the input workspace") + + .def("saveNexus", &DataProcessorAdapter::saveNexusProxy, + "Save a workspace as a nexus file. If this is an MPI build then saving only " + "happens for the main thread.") + + .def("isMainThread", &DataProcessorAdapter::isMainThreadProxy, + "Returns true if this algorithm is the main thread for an MPI build. For " + "non-MPI build it always returns true") + + .def("getNThreads", &DataProcessorAdapter::getNThreadsProxy, + "Returns the number of running MPI processes in an MPI build or 1 for " + "a non-MPI build") + ; +} + diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FrameworkManager.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FrameworkManager.cpp index 3b9dae818d9e..206ab4a29263 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FrameworkManager.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FrameworkManager.cpp @@ -1,65 +1,13 @@ #include "MantidAPI/FrameworkManager.h" -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/IAlgorithm.h" -#include "MantidPythonInterface/kernel/Environment/CallStack.h" #include -#include #include #include -#include -#include -#include -#include using Mantid::API::FrameworkManagerImpl; using Mantid::API::FrameworkManager; -using Mantid::API::AlgorithmManager; -using Mantid::API::IAlgorithm_sptr; using namespace boost::python; -namespace -{ - ///@cond - /** - * Creates an initialised algorithm. - * If this called from within a Python, i.e if PyExec is in the call stack, - * an unmanaged algorithm is created otherwise it will be a managed algorithm. - * @param self :: A reference to the FrameworkManager object - * @param name :: The name of the algorithm to create - * @param version :: The version of the algorithm to create (default = -1 = highest version) - */ - PyObject * createAlgorithm(FrameworkManagerImpl & self, const std::string & name, const int version = -1) - { - UNUSED_ARG(self); - IAlgorithm_sptr alg; - if( Mantid::PythonInterface::Environment::isInCallStack("PyExec") ) - { - alg = AlgorithmManager::Instance().createUnmanaged(name, version); - alg->setChild(true); // Ensures locking behaves correctly - alg->setLogging(true); - alg->setAlwaysStoreInADS(true); - alg->enableHistoryRecordingForChild(true); - alg->initialize(); - } - else - { - // creating through the manager ensures that observers can listen for things like - // progress & cancellation notifications - alg = AlgorithmManager::Instance().create(name, version); - } - alg->setRethrows(true); - - return converter::shared_ptr_to_python(alg); - } - - //------------------------------------------------------------------------------------------------------ - /// Define overload generators - BOOST_PYTHON_FUNCTION_OVERLOADS(create_overloads, createAlgorithm, 2,3); - ///@endcond -} - - void export_FrameworkManager() { class_("FrameworkManagerImpl", no_init) @@ -80,12 +28,6 @@ void export_FrameworkManager() .def("clearInstruments", &FrameworkManagerImpl::clearInstruments, "Clear memory held by the cached instruments") - // NOTE: This differs from the C++ FrameworkManager::createAlgorithm to ensure consistency when called within Python - .def("createAlgorithm", &createAlgorithm, - create_overloads((arg("name"), arg("version")), "Creates and initializes an algorithm of the " - "given name and version. If this called from within a Python algorithm " - "an unmanaged algorithm is created otherwise it will be a managed algorithm")) - .def("Instance", &FrameworkManager::Instance, return_value_policy(), "Returns a reference to the FrameworkManager singleton") .staticmethod("Instance") diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp index af90f1f1c29d..d00e88e34f35 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/FunctionFactory.cpp @@ -2,7 +2,7 @@ #include "MantidAPI/IFunction.h" #include "MantidKernel/WarningSuppressions.h" #include "MantidPythonInterface/kernel/PythonObjectInstantiator.h" -#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h" +#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h" #include #include diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp index 20c82257b24f..8fe99fe1e88a 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp @@ -262,9 +262,12 @@ void export_ialgorithm() .def("outputProperties",&getOutputProperties, "Returns a list of the output properties on the algorithm") .def("isInitialized", &IAlgorithm::isInitialized, "Returns True if the algorithm is initialized, False otherwise") .def("isExecuted", &IAlgorithm::isExecuted, "Returns True if the algorithm has been executed successfully, False otherwise") + .def("isLogging", &IAlgorithm::isLogging, "Returns True if the algorithm's logger is turned on, False otherwise") .def("isRunning", &IAlgorithm::isRunning, "Returns True if the algorithm is considered to be running, False otherwise") .def("setChild", &IAlgorithm::setChild, "If true this algorithm is run as a child algorithm. There will be no logging and nothing is stored in the Analysis Data Service") + .def("enableHistoryRecordingForChild", &IAlgorithm::enableHistoryRecordingForChild, + "If true then history will be recorded regardless of the child status") .def("setAlwaysStoreInADS", &IAlgorithm::setAlwaysStoreInADS, "If true then even child algorithms will have their workspaces stored in the ADS.") .def("isChild", &IAlgorithm::isChild, "Returns True if the algorithm has been marked to run as a child. If True then Output workspaces " diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PythonAlgorithmExport.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PythonAlgorithmExport.cpp deleted file mode 100644 index 9dc7da0cf607..000000000000 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PythonAlgorithmExport.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifdef _MSC_VER - #pragma warning( disable: 4250 ) // Disable warning regarding inheritance via dominance, we have no way around it with the design -#endif -#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h" -#ifdef _MSC_VER - #pragma warning( default: 4250 ) -#endif - -#include -#include -#include -#include - -using Mantid::API::Algorithm; -using Mantid::PythonInterface::AlgorithmWrapper; -using Mantid::PythonInterface::PythonAlgorithm; -using Mantid::Kernel::Direction; -using namespace boost::python; - -namespace -{ - // declarePyAlgProperty(property*,doc) - typedef void(PythonAlgorithm::*declarePropertyType1)(Mantid::Kernel::Property*, const std::string &); - // declarePyAlgProperty(name, defaultValue, validator, doc, direction) - typedef void(PythonAlgorithm::*declarePropertyType2)(const std::string &, const boost::python::object &, - const boost::python::object &, const std::string &, const int); - // declarePyAlgProperty(name, defaultValue, doc, direction) - typedef void(PythonAlgorithm::*declarePropertyType3)(const std::string &, const boost::python::object &, - const std::string &, const int); - // declarePyAlgProperty(name, defaultValue, direction) - typedef void(PythonAlgorithm::*declarePropertyType4)(const std::string &, const boost::python::object &, const int); - - // Overload types - BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(declarePropertyType1_Overload, declarePyAlgProperty, 1, 2); - BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(declarePropertyType2_Overload, declarePyAlgProperty, 2, 5); - BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(declarePropertyType3_Overload, declarePyAlgProperty, 3, 4); -} - -void export_leaf_classes() -{ - - // Export PythonAlgorithm but the actual held type in Python is boost::shared_ptr - // See http://wiki.python.org/moin/boost.python/HowTo#ownership_of_C.2B-.2B-_object_extended_in_Python - - class_, boost::shared_ptr, - boost::noncopyable>("PythonAlgorithm", "Base class for all Python algorithms") - .def("declareProperty", (declarePropertyType1)&PythonAlgorithm::declarePyAlgProperty, - declarePropertyType1_Overload((arg("prop"), arg("doc") = ""))) - - .def("declareProperty", (declarePropertyType2)&PythonAlgorithm::declarePyAlgProperty, - declarePropertyType2_Overload((arg("name"), arg("defaultValue"), arg("validator")=object(), arg("doc")="",arg("direction")=Direction::Input), - "Declares a named property where the type is taken from " - "the type of the defaultValue and mapped to an appropriate C++ type")) - - .def("declareProperty", (declarePropertyType3)&PythonAlgorithm::declarePyAlgProperty, - declarePropertyType3_Overload((arg("name"), arg("defaultValue"), arg("doc")="",arg("direction")=Direction::Input), - "Declares a named property where the type is taken from the type " - "of the defaultValue and mapped to an appropriate C++ type")) - - .def("declareProperty", (declarePropertyType4)&PythonAlgorithm::declarePyAlgProperty, - (arg("name"), arg("defaultValue"), arg("direction")=Direction::Input), - "Declares a named property where the type is taken from the type " - "of the defaultValue and mapped to an appropriate C++ type") - - .def("getLogger", &PythonAlgorithm::getLogger, return_value_policy(), - "Returns a reference to this algorithm's logger") - .def("log", &PythonAlgorithm::getLogger, return_value_policy(), - "Returns a reference to this algorithm's logger") // Traditional name - ; -} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ScriptRepositoryFactory.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ScriptRepositoryFactory.cpp index 0fdae495f469..6b7d223e588e 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ScriptRepositoryFactory.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/ScriptRepositoryFactory.cpp @@ -1,14 +1,7 @@ #include "MantidAPI/ScriptRepositoryFactory.h" #include "MantidAPI/ScriptRepository.h" -//#include "MantidPythonInterface/kernel/PythonObjectInstantiator.h" -//#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h" #include -#include - -// Python frameobject. This is under the boost includes so that boost will have done the -// include of Python.h which it ensures is done correctly -#include using Mantid::API::ScriptRepositoryFactoryImpl; using Mantid::API::ScriptRepositoryFactory; diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmAdapter.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmAdapter.cpp new file mode 100644 index 000000000000..217cea94f8e2 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmAdapter.cpp @@ -0,0 +1,268 @@ +#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmAdapter.h" +#include "MantidPythonInterface/kernel/Registry/PropertyWithValueFactory.h" +#include "MantidPythonInterface/kernel/Environment/WrapperHelpers.h" +#include "MantidPythonInterface/kernel/Environment/CallMethod.h" +#include "MantidPythonInterface/kernel/Environment/Threading.h" +#include "MantidAPI/DataProcessorAlgorithm.h" + +#include +#include + +//----------------------------------------------------------------------------- +// AlgorithmAdapter definition +//----------------------------------------------------------------------------- +namespace Mantid +{ + namespace PythonInterface + { + using namespace boost::python; + using Environment::CallMethod0; + + /** + * Construct the "wrapper" and stores the reference to the PyObject + * @param self A reference to the calling Python object + */ + template + AlgorithmAdapter::AlgorithmAdapter(PyObject* self) + : BaseAlgorithm(), m_self(self), m_isRunningObj(NULL) + { + // Cache the isRunning call to save the lookup each time it is called + // as it is most likely called in a loop + + // If the derived class type has isRunning then use that. + // A standard PyObject_HasAttr will check the whole inheritance + // hierarchy and always return true because IAlgorithm::isRunning is present. + // We just want to look at the Python class + if(Environment::typeHasAttribute(self, "isRunning")) + m_isRunningObj = PyObject_GetAttrString(self, "isRunning"); + } + + /** + * Returns the name of the algorithm. This cannot be overridden in Python. + */ + template + const std::string AlgorithmAdapter::name() const + { + return std::string(getSelf()->ob_type->tp_name); + } + + /** + * Returns the version of the algorithm. If not overridden + * it returns 1 + */ + template + int AlgorithmAdapter::version() const + { + return CallMethod0::dispatchWithDefaultReturn(getSelf(), "version", defaultVersion()); + } + + /** + * Returns the default version of the algorithm. If not overridden + * it returns 1 + */ + template + int AlgorithmAdapter::defaultVersion() const + { + return 1; + } + + /** + * Returns the category of the algorithm. If not overridden + * it returns "AlgorithmAdapter" + */ + template + const std::string AlgorithmAdapter::category() const + { + return CallMethod0::dispatchWithDefaultReturn(getSelf(), "category", defaultCategory()); + } + + /** + * A default category, chosen if there is no override + * @returns A default category + */ + template + std::string AlgorithmAdapter::defaultCategory() const + { + return "PythonAlgorithms"; + } + + /** + * @return True if the algorithm is considered to be running + */ + template + bool AlgorithmAdapter::isRunning() const + { + if(!m_isRunningObj) + { + return SuperClass::isRunning(); + } + else + { + Environment::GlobalInterpreterLock gil; + PyObject *result = PyObject_CallObject(m_isRunningObj, NULL); + if(PyErr_Occurred()) Environment::throwRuntimeError(true); + if(PyBool_Check(result)) return PyInt_AsLong(result); + else throw std::runtime_error("AlgorithmAdapter.isRunning - Expected bool return type."); + } + } + + /** + */ + template + void AlgorithmAdapter::cancel() + { + // No real need for eye on performance here. Use standard methods + if(Environment::typeHasAttribute(getSelf(), "cancel")) + { + Environment::GlobalInterpreterLock gil; + CallMethod0::dispatchWithException(getSelf(), "cancel"); + } + else SuperClass::cancel(); + } + + /** + * @copydoc Mantid::API::Algorithm::validateInputs + */ + template + std::map AlgorithmAdapter::validateInputs() + { + // variables that are needed further down + boost::python::dict resultDict; + std::map resultMap; + + // this is a modified version of CallMethod0::dispatchWithDefaultReturn + Environment::GlobalInterpreterLock gil; + if(Environment::typeHasAttribute(getSelf(), "validateInputs")) + { + try + { + resultDict = boost::python::call_method(getSelf(),"validateInputs"); + + if (!bool(resultDict)) + return resultMap; + } + catch(boost::python::error_already_set&) + { + Environment::throwRuntimeError(); + } + } + + // convert to a map + boost::python::list keys = resultDict.keys(); + size_t numItems = boost::python::len(keys); + for (size_t i = 0; i < numItems; ++i) + { + boost::python::object value = resultDict[keys[i]]; + if (value) + { + try + { + std::string key = boost::python::extract(keys[i]); + std::string value = boost::python::extract(resultDict[keys[i]]); + resultMap[key] = value; + } + catch(boost::python::error_already_set &) + { + this->getLogger().error() << "In validateInputs(self): Invalid type for key/value pair " + << "detected in dict.\n" + << "All keys and values must be strings\n"; + } + } + } + return resultMap; + } + + /** + * Declare a preconstructed property. + * @param prop :: A pointer to a property + * @param doc :: An optional doc string + */ + template + void AlgorithmAdapter::declarePyAlgProperty(boost::python::object &self, Kernel::Property *prop, const std::string & doc) + { + BaseAlgorithm & caller = extract(self); + // We need to clone the property so that python doesn't own the object that gets inserted + // into the manager + caller.declareProperty(prop->clone(), doc); + } + + /** + * Declare a property using the type of the defaultValue, a documentation string and validator + * @param name :: The name of the new property + * @param defaultValue :: A default value for the property. The type is mapped to a C++ type + * @param validator :: A validator object + * @param doc :: The documentation string + * @param direction :: The direction of the property + */ + template + void AlgorithmAdapter::declarePyAlgProperty(boost::python::object &self, const std::string & name, const boost::python::object & defaultValue, + const boost::python::object & validator, + const std::string & doc, const int direction) + { + BaseAlgorithm & caller = extract(self); + caller.declareProperty(Registry::PropertyWithValueFactory::create(name, defaultValue, validator, direction), doc); + } + + /** + * Declare a property using the type of the defaultValue and a documentation string + * @param name :: The name of the new property + * @param defaultValue :: A default value for the property. The type is mapped to a C++ type + * @param doc :: The documentation string + * @param direction :: The direction of the property + */ + template + void AlgorithmAdapter::declarePyAlgProperty(boost::python::object &self, const std::string & name, const boost::python::object & defaultValue, + const std::string & doc, const int direction) + { + BaseAlgorithm & caller = extract(self); + caller.declareProperty(Registry::PropertyWithValueFactory::create(name, defaultValue, direction), doc); + } + + /** + * Declare a property using the type of the defaultValue + * @param name :: The name of the new property + * @param defaultValue :: A default value for the property. The type is mapped to a C++ type + * @param direction :: The direction of the property + */ + template + void AlgorithmAdapter::declarePyAlgProperty(boost::python::object &self, const std::string & name, const boost::python::object & defaultValue, + const int direction) + { + declarePyAlgProperty(self, name, defaultValue, "", direction); + } + + + //--------------------------------------------------------------------------------------------- + // Private members + //--------------------------------------------------------------------------------------------- + + /** + * Private init for this algorithm. Expected to be + * overridden in the subclass by a function named PyInit + */ + template + void AlgorithmAdapter::init() + { + CallMethod0::dispatchWithException(getSelf(), "PyInit"); + } + + /** + * Private exec for this algorithm. Expected to be + * overridden in the subclass by a function named PyExec + */ + template + void AlgorithmAdapter::exec() + { + CallMethod0::dispatchWithException(getSelf(), "PyExec"); + } + + //----------------------------------------------------------------------------------------------------------------------------- + // Concete instantiations (avoids definitions being all in the headers) + //----------------------------------------------------------------------------------------------------------------------------- + /// API::Algorithm as base + template class AlgorithmAdapter; + /// API::DataProcesstor as base + template class AlgorithmAdapter; + + } +} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp deleted file mode 100644 index a055041e2110..000000000000 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include "MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h" -#include "MantidPythonInterface/kernel/Environment/WrapperHelpers.h" -#include "MantidPythonInterface/kernel/Environment/CallMethod.h" -#include "MantidPythonInterface/kernel/Environment/Threading.h" - -#include -#include - -//----------------------------------------------------------------------------- -// AlgorithmWrapper definition -//----------------------------------------------------------------------------- -namespace Mantid -{ - namespace PythonInterface - { - using namespace boost::python; - using Environment::CallMethod0; - - /** - * Construct the "wrapper" and stores the reference to the PyObject - * @param self A reference to the calling Python object - */ - AlgorithmWrapper::AlgorithmWrapper(PyObject* self) - : PythonAlgorithm(), m_self(self), m_isRunningObj(NULL) - { - // Cache the isRunning call to save the lookup each time it is called - // as it is most likely called in a loop - - // If the derived class type has isRunning then use that. - // A standard PyObject_HasAttr will check the whole inheritance - // hierarchy and always return true because IAlgorithm::isRunning is present. - // We just want to look at the Python class - if(Environment::typeHasAttribute(self, "isRunning")) - m_isRunningObj = PyObject_GetAttrString(self, "isRunning"); - } - - /** - * Returns the name of the algorithm. This cannot be overridden in Python. - */ - const std::string AlgorithmWrapper::name() const - { - return std::string(getSelf()->ob_type->tp_name); - } - - /** - * Returns the version of the algorithm. If not overridden - * it returns 1 - */ - int AlgorithmWrapper::version() const - { - return CallMethod0::dispatchWithDefaultReturn(getSelf(), "version", defaultVersion()); - } - - int AlgorithmWrapper::defaultVersion() const - { - return 1; - } - - /** - * Returns the category of the algorithm. If not overridden - * it returns "PythonAlgorithm" - */ - const std::string AlgorithmWrapper::category() const - { - return CallMethod0::dispatchWithDefaultReturn(getSelf(), "category", defaultCategory()); - } - - /** - * A default category, chosen if there is no override - * @returns A default category - */ - std::string AlgorithmWrapper::defaultCategory() const - { - return "PythonAlgorithms"; - } - - /** - * @return True if the algorithm is considered to be running - */ - bool AlgorithmWrapper::isRunning() const - { - if(!m_isRunningObj) - { - return Algorithm::isRunning(); - } - else - { - Environment::GlobalInterpreterLock gil; - PyObject *result = PyObject_CallObject(m_isRunningObj, NULL); - if(PyErr_Occurred()) Environment::throwRuntimeError(true); - if(PyBool_Check(result)) return PyInt_AsLong(result); - else throw std::runtime_error("PythonAlgorithm.isRunning - Expected bool return type."); - } - } - - /** - */ - void AlgorithmWrapper::cancel() - { - // No real need for eye on performance here. Use standard methods - if(Environment::typeHasAttribute(getSelf(), "cancel")) - { - Environment::GlobalInterpreterLock gil; - CallMethod0::dispatchWithException(getSelf(), "cancel"); - } - else Algorithm::cancel(); - } - - /** - * @copydoc Mantid::API::Algorithm::validateInputs - */ - std::map AlgorithmWrapper::validateInputs() - { - // variables that are needed further down - boost::python::dict resultDict; - std::map resultMap; - - // this is a modified version of CallMethod0::dispatchWithDefaultReturn - Environment::GlobalInterpreterLock gil; - if(Environment::typeHasAttribute(getSelf(), "validateInputs")) - { - try - { - resultDict = boost::python::call_method(getSelf(),"validateInputs"); - - if (!bool(resultDict)) - return resultMap; - } - catch(boost::python::error_already_set&) - { - Environment::throwRuntimeError(); - } - } - - // convert to a map - boost::python::list keys = resultDict.keys(); - size_t numItems = boost::python::len(keys); - for (size_t i = 0; i < numItems; ++i) - { - boost::python::object value = resultDict[keys[i]]; - if (value) - { - try - { - std::string key = boost::python::extract(keys[i]); - std::string value = boost::python::extract(resultDict[keys[i]]); - resultMap[key] = value; - } - catch(boost::python::error_already_set &) - { - this->getLogger().error() << "In validateInputs(self): Invalid type for key/value pair " - << "detected in dict.\n" - << "All keys and values must be strings\n"; - } - } - } - return resultMap; - } - - /** - * Private init for this algorithm. Expected to be - * overridden in the subclass by a function named PyInit - */ - void AlgorithmWrapper::init() - { - CallMethod0::dispatchWithException(getSelf(), "PyInit"); - } - - /** - * Private exec for this algorithm. Expected to be - * overridden in the subclass by a function named PyExec - */ - void AlgorithmWrapper::exec() - { - - CallMethod0::dispatchWithException(getSelf(), "PyExec"); - } - - } -} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/DataProcessorAdapter.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/DataProcessorAdapter.cpp new file mode 100644 index 000000000000..9b803f02b482 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/DataProcessorAdapter.cpp @@ -0,0 +1,21 @@ +#include "MantidPythonInterface/api/PythonAlgorithm/DataProcessorAdapter.h" + +//----------------------------------------------------------------------------- +// AlgorithmAdapter definition +//----------------------------------------------------------------------------- +namespace Mantid +{ + namespace PythonInterface + { + + /** + * Construct the "wrapper" and stores the reference to the PyObject + * @param self A reference to the calling Python object + */ + DataProcessorAdapter::DataProcessorAdapter(PyObject* self) + : SuperClass(self) + { + } + + } +} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/PythonAlgorithm.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/PythonAlgorithm.cpp deleted file mode 100644 index f356dea44193..000000000000 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/PythonAlgorithm.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- -#include "MantidPythonInterface/api/PythonAlgorithm/PythonAlgorithm.h" -#include "MantidPythonInterface/kernel/Registry/PropertyWithValueFactory.h" - -namespace Mantid -{ - namespace PythonInterface - { - - /** - * Declare a preconstructed property. - * @param prop :: A pointer to a property - * @param doc :: An optional doc string - */ - void PythonAlgorithm::declarePyAlgProperty(Kernel::Property *prop, const std::string & doc) - { - // We need to clone the property so that python doesn't own the object that gets inserted - // into the manager - this->declareProperty(prop->clone(), doc); - } - - /** - * Declare a property using the type of the defaultValue, a documentation string and validator - * @param name :: The name of the new property - * @param defaultValue :: A default value for the property. The type is mapped to a C++ type - * @param validator :: A validator object - * @param doc :: The documentation string - * @param direction :: The direction of the property - */ - void PythonAlgorithm::declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const boost::python::object & validator, - const std::string & doc, const int direction) - { - this->declareProperty(Registry::PropertyWithValueFactory::create(name, defaultValue, validator, direction), doc); - } - - /** - * Declare a property using the type of the defaultValue and a documentation string - * @param name :: The name of the new property - * @param defaultValue :: A default value for the property. The type is mapped to a C++ type - * @param doc :: The documentation string - * @param direction :: The direction of the property - */ - void PythonAlgorithm::declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const std::string & doc, const int direction) - { - this->declareProperty(Registry::PropertyWithValueFactory::create(name, defaultValue, direction), doc); - } - - /** - * Declare a property using the type of the defaultValue - * @param name :: The name of the new property - * @param defaultValue :: A default value for the property. The type is mapped to a C++ type - * @param direction :: The direction of the property - */ - void PythonAlgorithm::declarePyAlgProperty(const std::string & name, const boost::python::object & defaultValue, - const int direction) - { - declarePyAlgProperty(name, defaultValue, "", direction); - } - - } -} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/geometry/src/Exports/Instrument.cpp b/Code/Mantid/Framework/PythonInterface/mantid/geometry/src/Exports/Instrument.cpp index 69d8f79d45d4..b1d3ba2f116d 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/geometry/src/Exports/Instrument.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/geometry/src/Exports/Instrument.cpp @@ -15,10 +15,10 @@ void export_Instrument() register_ptr_to_python>(); class_, boost::noncopyable>("Instrument", no_init) - .def("getSample", (boost::shared_ptr (Instrument::*)())&Instrument::getSample, - "Return the object that represents the sample") + .def("getSample", &Instrument::getSample, return_value_policy(), + "Return the object that represents the sample") - .def("getSource", (boost::shared_ptr (Instrument::*)())&Instrument::getSource, + .def("getSource", &Instrument::getSource, return_value_policy(), "Return the object that represents the source") .def("getComponentByName", (boost::shared_ptr (Instrument::*)(const std::string&))&Instrument::getComponentByName, diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt index fa48f236c134..4eec7741b9c2 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt @@ -60,7 +60,6 @@ set ( SRC_FILES src/Registry/SequenceTypeHandler.cpp src/Registry/TypeRegistry.cpp src/Registry/DowncastRegistry.cpp - src/Environment/CallStack.cpp src/Environment/ErrorHandling.cpp src/Environment/Threading.cpp src/Environment/WrapperHelpers.cpp @@ -77,7 +76,6 @@ set ( INC_FILES ${HEADER_DIR}/kernel/Converters/PyObjectToMatrix.h ${HEADER_DIR}/kernel/Converters/PyObjectToV3D.h ${HEADER_DIR}/kernel/Converters/PySequenceToVector.h - ${HEADER_DIR}/kernel/Environment/CallStack.h ${HEADER_DIR}/kernel/Environment/CallMethod.h ${HEADER_DIR}/kernel/Environment/ErrorHandling.h ${HEADER_DIR}/kernel/Environment/Threading.h diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Environment/CallStack.cpp b/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Environment/CallStack.cpp deleted file mode 100644 index 75870cd15f2e..000000000000 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Environment/CallStack.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- -#include "MantidPythonInterface/kernel/Environment/CallStack.h" - -#include -#include -#include - -namespace Mantid -{ - namespace PythonInterface - { - namespace Environment - { - /** - * Is the given function name in the call stack - * @param name :: The name of the function call to search for - * @param startFrame :: An optional frame to start from, if NULL then the current frame is - * retrieved from the interpreter - * @return True if the function name is found in the stack, false otherwise - */ - bool isInCallStack(const char * name, PyFrameObject* startFrame) - { - PyFrameObject *frame = startFrame; - if( !frame ) frame = PyEval_GetFrame(); // current frame - if( !frame ) return false; - bool inStack(false); - if( strcmp(PyString_AsString(frame->f_code->co_name), name) == 0) - { - inStack = true; - } - else - { - while(frame->f_back) - { - frame = frame->f_back; - if( strcmp(PyString_AsString(frame->f_code->co_name), name) == 0 ) - { - inStack = true; - break; - } - } - } - return inStack; - } - - } - } -} diff --git a/Code/Mantid/Framework/PythonInterface/mantid/simpleapi.py b/Code/Mantid/Framework/PythonInterface/mantid/simpleapi.py index d354b06aa86c..2237489e6a09 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/simpleapi.py +++ b/Code/Mantid/Framework/PythonInterface/mantid/simpleapi.py @@ -86,7 +86,7 @@ def Load(*args, **kwargs): filename, = _get_mandatory_args('Load', ["Filename"], *args, **kwargs) # Create and execute - algm = _framework.createAlgorithm('Load') + algm = _create_algorithm_object('Load') _set_logging_option(algm, kwargs) algm.setProperty('Filename', filename) # Must be set first # Remove from keywords so it is not set twice @@ -157,7 +157,7 @@ def LoadDialog(*args, **kwargs): if 'Disable' not in arguments: arguments['Disable']='' if 'Message' not in arguments: arguments['Message']='' - algm = _framework.createAlgorithm('Load') + algm = _create_algorithm_object('Load') _set_properties_dialog(algm,**arguments) algm.execute() return algm @@ -189,7 +189,7 @@ def Fit(*args, **kwargs): if type(Function) == str and Function in _ads: raise ValueError("Fit API has changed. The function must now come first in the argument list and the workspace second.") # Create and execute - algm = _framework.createAlgorithm('Fit') + algm = _create_algorithm_object('Fit') _set_logging_option(algm, kwargs) algm.setProperty('Function', Function) # Must be set first algm.setProperty('InputWorkspace', InputWorkspace) @@ -244,7 +244,7 @@ def FitDialog(*args, **kwargs): if 'Disable' not in arguments: arguments['Disable']='' if 'Message' not in arguments: arguments['Message']='' - algm = _framework.createAlgorithm('Fit') + algm = _create_algorithm_object('Fit') _set_properties_dialog(algm,**arguments) algm.execute() return algm @@ -529,7 +529,7 @@ def _set_properties(alg_object, *args, **kwargs): else: alg_object.setProperty(key, value) -def _create_algorithm(algorithm, version, _algm_object): +def _create_algorithm_function(algorithm, version, _algm_object): """ Create a function that will set up and execute an algorithm. The help that will be displayed is that of the most recent version. @@ -546,7 +546,7 @@ def algorithm_wrapper(*args, **kwargs): if "Version" in kwargs: _version = kwargs["Version"] del kwargs["Version"] - algm = _framework.createAlgorithm(algorithm, _version) + algm = _create_algorithm_object(algorithm, _version) _set_logging_option(algm, kwargs) # Temporary removal of unneeded parameter from user's python scripts @@ -621,7 +621,72 @@ def algorithm_wrapper(*args, **kwargs): return algorithm_wrapper #------------------------------------------------------------------------------------------------------------- - + +def _create_algorithm_object(name, version=-1): + """ + Create and initialize the named algorithm of the given version. This + method checks whether the function call has come from within a PyExec + call. If that is the case then an unmanaged child algorithm is created. + + :param name A string name giving the algorithm + :param version A int version number + """ + import inspect + parent = _find_parent_pythonalgorithm(inspect.currentframe()) + if parent is not None: + alg = parent.createChildAlgorithm(name, version) + alg.setLogging(parent.isLogging()) # default is to log if parent is logging + + # Historic: simpleapi functions always put stuff in the ADS + # If we change this we culd potentially break many users' algorithms + alg.setAlwaysStoreInADS(True) + + # This can be removed when the C++ does the correct thing. see #8913 + if isinstance(parent, _api.DataProcessorAlgorithm): + alg.enableHistoryRecordingForChild(True) + else: + # managed algorithm so that progress reporting + # can be more easily wired up automatically + alg = AlgorithmManager.create(name, version) + # common traits + alg.setRethrows(True) + return alg + +#------------------------------------------------------------------------------------------------------------- + +def _find_parent_pythonalgorithm(frame): + """ + Look for a PyExec method in the call stack and return + the self object that the method is attached to + + :param frame The starting frame for the stack walk + :returns The self object that is running the PyExec method + or None if one was not found + """ + # We are looking for this method name + fn_name = "PyExec" + + # Return the 'self' object of a given frame + def get_self(frame): + return frame.f_locals['self'] + + # Look recursively for the PyExec method in the stack + if frame.f_code.co_name == fn_name: + return get_self(frame) + while True: + if frame.f_back: + if frame.f_back.f_code.co_name == fn_name: + return get_self(frame.f_back) + frame = frame.f_back + else: + break + if frame.f_code.co_name == fn_name: + return get_self(frame) + else: + return None + +#------------------------------------------------------------------------------------------------------------- + def _set_properties_dialog(algm_object, *args, **kwargs): """ Set the properties all in one go assuming that you are preparing for a @@ -701,7 +766,7 @@ def algorithm_wrapper(*args, **kwargs): if item not in kwargs: kwargs[item] = "" - algm = _framework.createAlgorithm(algorithm, _version) + algm = _create_algorithm_object(algorithm, _version) _set_properties_dialog(algm, *args, **kwargs) algm.execute() return algm @@ -816,7 +881,7 @@ def _translate(): except Exception: continue - algorithm_wrapper = _create_algorithm(name, max(versions), algm_object) + algorithm_wrapper = _create_algorithm_function(name, max(versions), algm_object) method_name = algm_object.workspaceMethodName() if len(method_name) > 0: if method_name in new_methods: diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py index 7c9d509b2271..ae1274492adb 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CreateTransmissionWorkspaceAuto.py @@ -13,7 +13,7 @@ from mantid.api import * from mantid.kernel import * -class CreateTransmissionWorkspaceAuto(PythonAlgorithm): +class CreateTransmissionWorkspaceAuto(DataProcessorAlgorithm): def category(self): return "Reflectometry\\ISIS" diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadSINQFile.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadSINQFile.py index 13666baccd49..88c60d07f1c4 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadSINQFile.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/LoadSINQFile.py @@ -1,7 +1,8 @@ """*WIKI* -== DESCRIPTION == -LoadSINQFile is a wrapper algorithm around LoadFlexiNexus. It locates a suitable dictionary file for the instrument in question and then goes away to call LoadFlexiNexus with the right arguments. It also performs any other magic which might be required to get the data in the right shape for further processing in Mantid. +LoadSINQFile is a wrapper algorithm around LoadFlexiNexus. +It locates a suitable dictionary file for the instrument in question and then goes away to call LoadFlexiNexus with the right arguments. +It also performs any other magic which might be required to get the data in the right shape for further processing in Mantid. *WIKI*""" diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py index 7e8466e9f3a3..975c443b7606 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ReflectometryReductionOneAuto.py @@ -13,7 +13,7 @@ from mantid.api import * from mantid.kernel import * -class ReflectometryReductionOneAuto(PythonAlgorithm): +class ReflectometryReductionOneAuto(DataProcessorAlgorithm): def category(self): return "Reflectometry\\ISIS" @@ -184,4 +184,4 @@ def PyExec(self): -AlgorithmFactory.subscribe(ReflectometryReductionOneAuto) \ No newline at end of file +AlgorithmFactory.subscribe(ReflectometryReductionOneAuto) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py index 37a9495f2563..207f4f050a8b 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py @@ -15,8 +15,7 @@ from mantid.kernel import * import os -all_algs = AlgorithmFactory.getRegisteredAlgorithms(True) -if 'GatherWorkspaces' in all_algs: +if AlgorithmFactory.exists('GatherWorkspaces'): HAVE_MPI = True from mpi4py import MPI mpiRank = MPI.COMM_WORLD.Get_rank() @@ -27,7 +26,7 @@ COMPRESS_TOL_TOF = .01 EVENT_WORKSPACE_ID = "EventWorkspace" -class SNSPowderReduction(PythonAlgorithm): +class SNSPowderReduction(DataProcessorAlgorithm): def category(self): return "Diffraction;PythonAlgorithms" @@ -492,6 +491,13 @@ def _getStrategy(self, runnumber, extension): return strategy + def __logChunkInfo(self, chunk): + keys = chunk.keys() + keys.sort() + + keys = [ str(key) + "=" + str(chunk[key]) for key in keys ] + self.log().information("Working on chunk [" + ", ".join(keys) + "]") + def _focusChunks(self, runnumber, extension, filterWall, calib, splitwksp=None, preserveEvents=True): """ Load, (optional) split and focus data in chunks @@ -545,10 +551,7 @@ def _focusChunks(self, runnumber, extension, filterWall, calib, splitwksp=None, ichunk += 1 # Log information - if "ChunkNumber" in chunk: - self.log().information("Working on chunk %d of %d" % (chunk["ChunkNumber"], chunk["TotalChunks"])) - elif "SpectrumMin" in chunk: - self.log().information("Working on spectrums %d through %d" % (chunk["SpectrumMin"], chunk["SpectrumMax"])) + self.__logChunkInfo(chunk) # Load chunk temp = self._loadData(runnumber, extension, filterWall, **chunk) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ViewBOA.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ViewBOA.py index daeeb232d0ec..8c703d48ee05 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ViewBOA.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/ViewBOA.py @@ -1,9 +1,10 @@ -#-------------------------------------------------------------------- -# Algorithm which loads a BOA file and creates the 3 BOA plots -# of Uwe Filges desire. -# -# Mark Koennecke, July 2013 -#--------------------------------------------------------------------- +"""*WIKI* + +Algorithm which loads a BOA file and creates the 3 BOA plots of Uwe Filges desire + +Mark Koennecke, July 2013 + +*WIKI*""" from mantid.api import AlgorithmFactory from mantid.api import PythonAlgorithm, WorkspaceFactory, FileProperty, FileAction, WorkspaceProperty @@ -19,10 +20,12 @@ def category(self): return 'PythonAlgorithms;SINQ' def PyInit(self): + self.setOptionalMessage("Load a BOA file and create the 3 BOA plots.") + self.setWikiSummary("Load a BOA file and create the 3 BOA plots.") now = datetime.datetime.now() self.declareProperty("Year",now.year,"Choose year",direction=Direction.Input) self.declareProperty('Numor',0,'Choose file number',direction=Direction.Input) - self.declareProperty('CD-Distance',6.000,'Chopper Detector distance in meter',direction=Direction.Input) + self.declareProperty('CD-Distance',6.000,'Chopper Detector distance in metres',direction=Direction.Input) def PyExec(self): year=self.getProperty('Year').value diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/HFIRSANSReduction.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/HFIRSANSReduction.py index af7d6755dd30..1af7f7ac79cd 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/HFIRSANSReduction.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/HFIRSANSReduction.py @@ -1,6 +1,6 @@ """*WIKI* - HFIR SANS reduction workflow +HFIR SANS reduction workflow *WIKI*""" import mantid.simpleapi as api diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSAzimuthalAverage1D.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSAzimuthalAverage1D.py index e1602c3bd76f..1e0af1de067a 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSAzimuthalAverage1D.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSAzimuthalAverage1D.py @@ -1,5 +1,5 @@ """*WIKI* - Compute I(q) for reduced SANS data +Compute I(q) for reduced SANS data *WIKI*""" from mantid.api import * from mantid.kernel import * diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSBeamSpreaderTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSBeamSpreaderTransmission.py index a7ce7699a3a5..040b0ac4cf4e 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSBeamSpreaderTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSBeamSpreaderTransmission.py @@ -1,5 +1,5 @@ """*WIKI* - Compute transmission using the beam spreader method +Compute transmission using the beam spreader method *WIKI*""" import mantid.simpleapi as api from mantid.api import * diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSDirectBeamTransmission.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSDirectBeamTransmission.py index 0efde175c0b0..bdff030c266e 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSDirectBeamTransmission.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SANSDirectBeamTransmission.py @@ -1,5 +1,5 @@ """*WIKI* - Compute transmission using the direct beam method +Compute transmission using the direct beam method *WIKI*""" import mantid.simpleapi as api from mantid.api import * diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py index c78e998b4fb5..6d916341b453 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py @@ -1,6 +1,6 @@ import unittest -from mantid.api import (AlgorithmFactory, mtd, IEventWorkspace, ITableWorkspace, - MatrixWorkspace, WorkspaceGroup) +from mantid.api import (AlgorithmFactory, AlgorithmProxy, IAlgorithm, IEventWorkspace, ITableWorkspace, + PythonAlgorithm, MatrixWorkspace, mtd, WorkspaceGroup) import mantid.simpleapi as simpleapi import numpy @@ -274,7 +274,7 @@ def PyExec(self): name="OptionalWorkspace" algm_object = AlgorithmManager.createUnmanaged(name, 1) algm_object.initialize() - simpleapi._create_algorithm(name, 1, algm_object) # Create the wrapper + simpleapi._create_algorithm_function(name, 1, algm_object) # Create the wrapper # Call with no optional output specified result = simpleapi.OptionalWorkspace(RequiredWorkspace="required") @@ -290,7 +290,36 @@ def PyExec(self): # Tidy up simple api function del simpleapi.OptionalWorkspace - + + def test_create_algorithm_object_produces_initialized_non_child_alorithm_outside_PyExec(self): + alg = simpleapi._create_algorithm_object("Rebin") + self._is_initialized_test(alg, 1, expected_class=AlgorithmProxy, + expected_child=False) + + def test_create_algorithm_with_version_produces_initialized_alorithm(self): + alg = simpleapi._create_algorithm_object("LoadRaw", 2) + self._is_initialized_test(alg, 2, expected_class=AlgorithmProxy, + expected_child=False) + + def test_create_algorithm_produces_child_inside_PyExec(self): + # A small test class to have a PyExec method call the + # algorithm creation + class TestAlg(PythonAlgorithm): + def PyInit(self): + pass + def PyExec(self): + self.alg = simpleapi._create_algorithm_object("Rebin") + # end + top_level = TestAlg() + top_level.PyExec() + self._is_initialized_test(top_level.alg, 1, expected_class=IAlgorithm, + expected_child=True) + + def _is_initialized_test(self, alg, version, expected_class, expected_child): + self.assertTrue(alg.isInitialized()) + self.assertEquals(expected_child,alg.isChild()) + self.assertEquals(alg.version(), version) + self.assertTrue(isinstance(alg, expected_class)) if __name__ == '__main__': unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py index 2f8b919c9c1a..73bc67567e29 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py @@ -14,7 +14,12 @@ class AlgorithmFactoryTest(unittest.TestCase): def test_get_algorithm_factory_does_not_return_None(self): self.assertTrue(AlgorithmFactory is not None ) - + + def test_exists_returns_correct_value_for_given_args(self): + self.assertTrue(AlgorithmFactory.exists('ConvertUnits')) #any version + self.assertTrue(AlgorithmFactory.exists('ConvertUnits', 1)) #any version + self.assertTrue(not AlgorithmFactory.exists('ConvertUnits', 100)) #any version + def test_get_registered_algs_returns_dictionary_of_known_algorithms(self): all_algs = AlgorithmFactory.getRegisteredAlgorithms(True) self.assertTrue( len(all_algs) > 0 ) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt index d3fe3833c6af..50b3f15589f5 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt @@ -8,6 +8,7 @@ set ( TEST_PY_FILES AlgorithmPropertyTest.py AnalysisDataServiceTest.py AxisTest.py + DataProcessorAlgorithmTest.py DeprecatedAlgorithmCheckerTest.py ExperimentInfoTest.py FilePropertyTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/DataProcessorAlgorithmTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/DataProcessorAlgorithmTest.py new file mode 100644 index 000000000000..1cf35e43d2f2 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/DataProcessorAlgorithmTest.py @@ -0,0 +1,75 @@ +import unittest +from testhelpers import assertRaisesNothing +from mantid.api import (Algorithm, DataProcessorAlgorithm, AlgorithmFactory, + AlgorithmManager, WorkspaceProperty) +from mantid.kernel import Direction + +class TestDataProcessor(DataProcessorAlgorithm): + def PyInit(self): + pass + def PyExec(self): + pass +# end v1 alg + +class DataProcessorAlgorithmTest(unittest.TestCase): + + def test_DataProcessorAlgorithm_instance_inherits_Algorithm(self): + alg = TestDataProcessor() + self.assertTrue(isinstance(alg, Algorithm)) + + def test_class_has_expected_attrbutes(self): + expected_attrs = \ + [ + "setLoadAlg", + "setLoadAlgFileProp", + "setAccumAlg", + "determineChunk", + "loadChunk", + "load", + "splitInput", + "forwardProperties", + "getProcessProperties", + "assemble", + "saveNexus", + "isMainThread", + "getNThreads" + ] + for name in expected_attrs: + if not hasattr(DataProcessorAlgorithm, name): + self.fail("DataProcessorAlgorithm does not have expected attribute '%s'" % name) + + def test_inheriting_class_can_be_subscribed_and_created_through_factory(self): + assertRaisesNothing(self, AlgorithmFactory.subscribe, TestDataProcessor) + assertRaisesNothing(self, AlgorithmManager.createUnmanaged, "TestDataProcessor") + + def test_class_can_override_standard_algorithm_methods(self): + class TestDataProcessor(DataProcessorAlgorithm): + def version(self): + return 2 + def PyInit(self): + pass + def PyExec(self): + pass + # end v2 alg + + AlgorithmFactory.subscribe(TestDataProcessor) + assertRaisesNothing(self, AlgorithmManager.createUnmanaged, "TestDataProcessor", 2) + + def test_declareProperty_methods_can_be_called_on_inheriting_algorithm(self): + class DataProcessorProperties(DataProcessorAlgorithm): + def PyInit(self): + self.declareProperty("NumberProperty", 1) + self.declareProperty(WorkspaceProperty("Workspace","", Direction.Output)) + + def PyExec(self): + number = self.getProperty("NumberProperty").value + wksp = self.getProperty("Workspace").value + # end + alg = DataProcessorProperties() + assertRaisesNothing(self, alg.initialize) + alg.setPropertyValue("Workspace", "__anon") + assertRaisesNothing(self, alg.execute) + + +if __name__ == '__main__': + unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/FrameworkManagerTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/FrameworkManagerTest.py index e7d1a0498222..2d512010f1ca 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/FrameworkManagerTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/FrameworkManagerTest.py @@ -2,13 +2,6 @@ import testhelpers from mantid.api import FrameworkManager, FrameworkManagerImpl, IAlgorithm, AlgorithmProxy -def _is_initialized_test(testobj, alg, version, expected_class, expected_child): - testobj.assertTrue(alg.isInitialized()) - testobj.assertEquals(expected_child,alg.isChild()) - testobj.assertEquals(alg.version(), version) - testobj.assertTrue(isinstance(alg, expected_class)) - - class FrameworkManagerTest(unittest.TestCase): def test_clear_functions_do_not_throw(self): @@ -18,30 +11,5 @@ def test_clear_functions_do_not_throw(self): testhelpers.assertRaisesNothing(self, FrameworkManager.clearAlgorithms) testhelpers.assertRaisesNothing(self, FrameworkManager.clearInstruments) - def test_create_algorithm_produces_initialized_alorithm(self): - alg = FrameworkManager.createAlgorithm("Rebin") - _is_initialized_test(self, alg, 1, expected_class=AlgorithmProxy, - expected_child=False) - - def test_create_algorithm_with_version_produces_initialized_alorithm(self): - alg = FrameworkManager.createAlgorithm("LoadRaw", 2) - _is_initialized_test(self, alg, 2, expected_class=AlgorithmProxy, - expected_child=False) - - def test_create_algorithm_produces_child_inside_PyExec(self): - # A small test class to have a PyExec method call the - # algorithm creation - class TestAlg(object): - def __init__(self, test_object): - self._test_obj = test_object - - def PyExec(self): - alg = FrameworkManager.createAlgorithm("Rebin") - _is_initialized_test(self._test_obj, alg, 1, - expected_class=IAlgorithm, expected_child=True) - - top_level = TestAlg(self) - top_level.PyExec() - if __name__ == '__main__': unittest.main() diff --git a/Code/Mantid/Framework/SINQ/src/MDHistoToWorkspace2D.cpp b/Code/Mantid/Framework/SINQ/src/MDHistoToWorkspace2D.cpp index f4c6eafb413a..0c10557242e8 100644 --- a/Code/Mantid/Framework/SINQ/src/MDHistoToWorkspace2D.cpp +++ b/Code/Mantid/Framework/SINQ/src/MDHistoToWorkspace2D.cpp @@ -1,7 +1,7 @@ /*WIKI* -== Description == -MDHistoToWorkspace2D flattens a MDHistoWorkspace into a Workspace2D. It can process MDHistoWorkspaces of any dimensionality. The last dimension of the MDHistoWorkspace becomes +MDHistoToWorkspace2D flattens a MDHistoWorkspace into a Workspace2D. It can process MDHistoWorkspaces of any dimensionality. +The last dimension of the MDHistoWorkspace becomes the spectra length. Flattening happens such that the first dimension of the MDHistoWorkspace is the slowest varying, the second the second slowest varying and so on. diff --git a/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/BoxControllerDummyIO.h b/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/BoxControllerDummyIO.h index 807afb0c2814..813c074e6f0c 100644 --- a/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/BoxControllerDummyIO.h +++ b/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/BoxControllerDummyIO.h @@ -46,7 +46,7 @@ namespace MantidTestHelpers class DLLExport BoxControllerDummyIO : public Mantid::API::IBoxControllerIO { public: - BoxControllerDummyIO(Mantid::API::BoxController_sptr theBC); + BoxControllerDummyIO(const Mantid::API::BoxController* theBC); ///@return true if the file to write events is opened and false otherwise virtual bool isOpened()const @@ -90,7 +90,7 @@ namespace MantidTestHelpers // the file Handler responsible for Nexus IO operations; mutable std::vector fileContents; /// shared pointer to the box controller, which is repsoponsible for this IO - Mantid::API::BoxController_sptr m_bc; + const Mantid::API::BoxController* m_bc; mutable Mantid::Kernel::Mutex m_fileMutex; /// number of bytes in the event coorinates (coord_t length). Set by setDataType but can be defined statically with coord_t diff --git a/Code/Mantid/Framework/TestHelpers/src/BoxControllerDummyIO.cpp b/Code/Mantid/Framework/TestHelpers/src/BoxControllerDummyIO.cpp index cc1338351e7e..bfd490752ad4 100644 --- a/Code/Mantid/Framework/TestHelpers/src/BoxControllerDummyIO.cpp +++ b/Code/Mantid/Framework/TestHelpers/src/BoxControllerDummyIO.cpp @@ -16,7 +16,7 @@ namespace MantidTestHelpers /**Constructor @param bc shared pointer to the box controller which will use this IO operations */ - BoxControllerDummyIO::BoxControllerDummyIO(Mantid::API::BoxController_sptr bc) : + BoxControllerDummyIO::BoxControllerDummyIO(const Mantid::API::BoxController* bc) : m_bc(bc), m_CoordSize(4), m_TypeName("MDEvent"), diff --git a/Code/Mantid/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp b/Code/Mantid/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp index 33b40c803c38..d83e1c629a6c 100644 --- a/Code/Mantid/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp +++ b/Code/Mantid/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp @@ -1161,8 +1161,8 @@ namespace WorkspaceCreationHelper { Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); // - Geometry::IObjComponent_const_sptr source = instrument->getSource(); - Geometry::IObjComponent_const_sptr sample = instrument->getSample(); + Geometry::IComponent_const_sptr source = instrument->getSource(); + Geometry::IComponent_const_sptr sample = instrument->getSample(); if ((!source) || (!sample)) { diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/SANSSolidAngleCorrection.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/SANSSolidAngleCorrection.cpp index e0280e9ec70d..a02865b37b93 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/SANSSolidAngleCorrection.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/SANSSolidAngleCorrection.cpp @@ -37,8 +37,8 @@ DECLARE_ALGORITHM(SANSSolidAngleCorrection) static double getYTubeAngle(IDetector_const_sptr det, MatrixWorkspace_const_sptr workspace) { - Geometry::IObjComponent_const_sptr source = workspace->getInstrument()->getSource(); - Geometry::IObjComponent_const_sptr sample = workspace->getInstrument()->getSample(); + Geometry::IComponent_const_sptr source = workspace->getInstrument()->getSource(); + Geometry::IComponent_const_sptr sample = workspace->getInstrument()->getSample(); if ( source == NULL || sample == NULL ) { throw std::invalid_argument("Instrument not sufficiently defined: failed to get source and/or sample"); diff --git a/Code/Mantid/Installers/MacInstaller/MacOSX-README.rtf b/Code/Mantid/Installers/MacInstaller/MacOSX-README.rtf deleted file mode 100755 index 3535e8e24d7b..000000000000 --- a/Code/Mantid/Installers/MacInstaller/MacOSX-README.rtf +++ /dev/null @@ -1,37 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} -{\colortbl;\red255\green255\blue255;} -{\info -{\author Russell Taylor}}\paperw11900\paperh16840\margl1440\margr1440\vieww12200\viewh13420\viewkind1 -\deftab720 -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\f0\b\fs24 \cf0 Install instructions for MantidPlot on OS X\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\b0 \cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\b \cf0 Requirements -\b0 :-\ -\ -An Intel based Mac with OS X 10.6 (Snow Leopard) or above.\ -An admin password for the aforementioned computer.\ -\ -The Mac install of Mantid will install into the /Applications/MantidPlot.app directory. The sole requirement is the version of python 2.6 which ships with Snow Leopard, Lion (10.7) & Mountain Lion (10.8).\ -\ - -\b To start MantidPlot -\b0 :-\ -\ -1. Use spotlight to locate the application MantidPlot, or\ -2. Navigate to Applications and click on the MantidPlot icon \ -\ - -\b To import Mantid within Python -\b0 :-\ -\ -You need to add -\f1 /Applications/MantidPlot.app/Contents/MacOS -\f0 to both your PYTHONPATH & DYLD_LIBRARY_PATH environment variables.\ -Mantid will then be available if starting python2.6 from a terminal, either via an "import mantid" or by directly running scripts that do this.} \ No newline at end of file diff --git a/Code/Mantid/Installers/MacInstaller/MacOSX10-8-README.rtf b/Code/Mantid/Installers/MacInstaller/MacOSX10-8-README.rtf deleted file mode 100644 index c79e4787c8b6..000000000000 --- a/Code/Mantid/Installers/MacInstaller/MacOSX10-8-README.rtf +++ /dev/null @@ -1,41 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} -{\colortbl;\red255\green255\blue255;} -{\info -{\author Russell Taylor}}\paperw11900\paperh16840\margl1440\margr1440\vieww12500\viewh13720\viewkind1 -\deftab720 -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\f0\b\fs24 \cf0 Install instructions for MantidPlot on OS X\ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\b0 \cf0 \ -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ri0 - -\b \cf0 Requirements -\b0 :-\ -\ -An Intel based Mac with OS X 10.8 (Mountain Lion) or above. \ -An admin password for the aforementioned computer.\ -\ -If you are running Snow Leopard (10.6) or Lion (10.7), please download and install the 'mantid- -\i version -\i0 -SnowLeopard.dmg' package instead.\ -\ -The Mac install of Mantid will install into the /Applications/MantidPlot.app directory. The sole requirement is the version of python 2.7 which ships with Mountain Lion.\ -\ - -\b To start MantidPlot -\b0 :-\ -\ -1. Use spotlight to locate the application MantidPlot, or\ -2. Navigate to Applications and click on the MantidPlot icon \ -\ - -\b To import Mantid within Python -\b0 :-\ -\ -You need to add -\f1 /Applications/MantidPlot.app/Contents/MacOS -\f0 to both your PYTHONPATH & DYLD_LIBRARY_PATH environment variables.\ -Mantid will then be available if starting python (2.7) from a terminal, either via an "import mantid" or by directly running scripts that do this.} \ No newline at end of file diff --git a/Code/Mantid/Installers/MacInstaller/installer_hooks/preflight b/Code/Mantid/Installers/MacInstaller/installer_hooks/preflight deleted file mode 100644 index 5a63cda33091..000000000000 --- a/Code/Mantid/Installers/MacInstaller/installer_hooks/preflight +++ /dev/null @@ -1,58 +0,0 @@ -#! /bin/sh -# ------------------------------------------------------------------------- -# -# Some libraries (DataObjects & Nexus) have moved in the CPack Mac -# installer. We need to be sure to clean things up if there's a -# previous Mantid install on the machine. -# -# ------------------------------------------------------------------------- - -echo "=== Starting preflight installer hook ===" -echo - -echo "=== Removing old version ===" -if [ -d "/Applications/MantidPlot.app" ]; then - rm -Rf /Applications/MantidPlot.app -fi - -# ------------------------------------------------------------------------- -# -# We don't want the Mantid Python modules inside the Python -# distribution anymore -# -# ------------------------------------------------------------------------- - -PY_SITE_DIR=/Library/Python/2.6/site-packages -echo "=== Removing Mantid Python package from ${PY_SITE_DIR} ===" -if [ -d "${PY_SITE_DIR}/MantidFramework" ]; then - rm -Rf ${PY_SITE_DIR}/MantidFramework -fi - -if [ -f "${PY_SITE_DIR}/Mantid-1.0-py2.6.egg-info" ]; then - rm -f ${PY_SITE_DIR}/Mantid-1.0-py2.6.egg-info -fi - -# ------------------------------------------------------------------------- -# -# Remove MANTIDPATH from environment.plist (but back it up) -# -# ------------------------------------------------------------------------- -PLIST=${HOME}/.MacOS/environment.plist -if [ -f ${PLIST} ]; then - # Backup - mv ${PLIST} ${PLIST}.bak - cat ${PLIST}.bak | sed -e 's@MANTIDPATH@@g' | sed -e 's@/Applications/MantidPlot.app/Contents/MacOS@@g' > ${PLIST} -fi - -# ------------------------------------------------------------------------- -# -# Remove MANTIDPATH references from .profile (but back it up) -# -# ------------------------------------------------------------------------- -PROFILE=${HOME}/.profile -if [ -f ${PROFILE} ]; then - # Backup - mv ${PROFILE} ${PROFILE}.bak - cat ${PROFILE}.bak | sed -e 's@export MANTIDPATH=/Applications/MantidPlot.app/Contents/MacOS@@g' | sed -e 's@:$MANTIDPATH@@g' > ${PROFILE} -fi - diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 228c25d21c06..d9031d92911e 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -192,6 +192,7 @@ #include "MantidQtAPI/ManageUserDirectories.h" #include "MantidQtAPI/Message.h" +#include "MantidQtMantidWidgets/CatalogHelper.h" #include "MantidQtMantidWidgets/CatalogSearch.h" #include "MantidQtMantidWidgets/FitPropertyBrowser.h" #include "MantidQtMantidWidgets/MessageDisplay.h" @@ -17472,7 +17473,7 @@ void ApplicationWindow::panOnPlot() void ApplicationWindow::CatalogLogin() { // Executes the catalog login algorithm, and returns true if user can login. - if (mantidUI->isValidCatalogLogin()) + if (MantidQt::MantidWidgets::CatalogHelper().isValidCatalogLogin()) { icat->addAction(actionCatalogSearch); icat->addAction(actionCatalogPublish); @@ -17497,7 +17498,7 @@ void ApplicationWindow::CatalogSearch() void ApplicationWindow::CatalogPublish() { - mantidUI->catalogPublishDialog(); + MantidQt::MantidWidgets::CatalogHelper().catalogPublishDialog(); } void ApplicationWindow::CatalogLogout() diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp index b5ec5fef21b9..79c16a180c73 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp @@ -60,8 +60,7 @@ m_workspace(AnalysisDataService::Instance().retrieveWS(wsName.t m_ragged(true), m_autoscaling(autoscaling), m_maskedColor(100,100,100), -m_failedColor(200,200,200), -m_sampleActor(NULL) +m_failedColor(200,200,200) { // settings loadSettings(); @@ -98,12 +97,6 @@ m_sampleActor(NULL) // this adds actors for all instrument components to the scene and fills in m_detIDs m_scene.addActor(new CompAssemblyActor(*this,instrument->getComponentID())); - FindComponentVisitor findVisitor(instrument->getSample()->getComponentID()); - accept(findVisitor,GLActor::Finish); - const ObjComponentActor* samplePosActor = dynamic_cast(findVisitor.getActor()); - - m_sampleActor = new SampleActor(*this,sharedWorkspace->sample(),samplePosActor); - m_scene.addActor(m_sampleActor); if ( !m_showGuides ) { // hide guide and other components @@ -191,11 +184,6 @@ bool InstrumentActor::accept(GLActorVisitor& visitor, VisitorAcceptRule rule) { bool ok = m_scene.accept(visitor, rule); visitor.visit(this); - SetVisibilityVisitor* vv = dynamic_cast(&visitor); - if (vv && m_sampleActor) - { - m_sampleActor->setVisibility(m_sampleActor->getSamplePosActor()->isVisible()); - } invalidateDisplayLists(); return ok; } diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h index aadf8f74a13b..8937739e984e 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h @@ -219,8 +219,6 @@ class InstrumentActor: public GLActor GLColor m_failedColor; /// The collection of actors for the instrument components GLActorCollection m_scene; - /// A pointer to the sample actor - SampleActor* m_sampleActor; static double m_tolerance; diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp index df86026d75df..e11aa49ae72a 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp @@ -336,7 +336,7 @@ void InstrumentWindow::setSurfaceType(int type) // Surface factory { Mantid::Geometry::Instrument_const_sptr instr = m_instrumentActor->getInstrument(); - Mantid::Geometry::IObjComponent_const_sptr sample = instr->getSample(); + Mantid::Geometry::IComponent_const_sptr sample = instr->getSample(); Mantid::Kernel::V3D sample_pos = sample->getPos(); Mantid::Kernel::V3D axis; // define the axis diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp index 0f4579c17013..77ad6fc08c9b 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp @@ -1091,7 +1091,7 @@ Table* MantidUI::createDetectorTable(const QString & wsName, const Mantid::API:: t->setHeaderColType(); // Cache some frequently used values - IObjComponent_const_sptr sample = ws->getInstrument()->getSample(); + IComponent_const_sptr sample = ws->getInstrument()->getSample(); bool signedThetaParamRetrieved(false), showSignedTwoTheta(false); //If true, signedVersion of the two theta value should be displayed for( int row = 0; row < nrows; ++row ) { @@ -2072,36 +2072,6 @@ void MantidUI::enableSaveNexus(const QString& wsName) appWindow()->enablesaveNexus(wsName); } -/** - * Executes the catalog login algorithm. - * Returns true if login was a success. - */ -bool MantidUI::isValidCatalogLogin() -{ - auto catalogAlgorithm = this->createAlgorithm("CatalogLogin"); - auto loginDialog = this->createAlgorithmDialog(catalogAlgorithm); - - if(loginDialog->exec() == QDialog::Accepted) - { - if (catalogAlgorithm->execute()) return true; - } - return false; -} - -/** - * Creates a publishing dialog GUI and runs the publishing algorithm when "Run" is pressed. - */ -void MantidUI::catalogPublishDialog() -{ - auto catalogAlgorithm = this->createAlgorithm("CatalogPublish"); - auto publishDialog = this->createAlgorithmDialog(catalogAlgorithm); - - if(publishDialog->exec() == QDialog::Accepted) - { - catalogAlgorithm->executeAsync(); - } -} - /** This method is sueful for saving the currently loaded workspaces to project file on save. * saves the names of all the workspaces loaded into mantid workspace tree * into a string and calls save nexus on each workspace to save the data to a nexus file. diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h index e200e9173cde..c2aa6644b0d6 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h @@ -290,11 +290,6 @@ class MantidUI:public QObject void saveProject(bool save); void enableSaveNexus(const QString & wsName); - /// Verifies if the Catalog login was a success. - bool isValidCatalogLogin(); - /// Create a publishing dialog. - void catalogPublishDialog(); - signals: //A signal to indicate that we want a script to produce a dialog void showPropertyInputDialog(const QString & algName); diff --git a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h index 9d72c313455f..1cca999ed64d 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h +++ b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h @@ -33,7 +33,7 @@ namespace MantidQt File change history is stored at: . Code Documentation is available at: */ - class CatalogPublishDialog : public MantidQt::API::AlgorithmDialog + class CatalogPublishDialog : public API::AlgorithmDialog { Q_OBJECT @@ -52,6 +52,8 @@ namespace MantidQt void workspaceSelected(const QString& wsName); /// Set the "FileName" property when a file is selected from the file browser. void fileSelected(); + /// Diables fields on dialog to improve usability + void disableDialog(); /// Set session property when user selects an investigation to publish to. void setSessionProperty(int index); diff --git a/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp b/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp index bde739387917..1cad4d1c3eed 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp +++ b/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp @@ -10,8 +10,6 @@ #include "MantidQtAPI/AlgorithmInputHistory.h" #include "MantidQtMantidWidgets/DataSelector.h" -#include - namespace MantidQt { namespace CustomDialogs @@ -22,7 +20,7 @@ namespace MantidQt * Default constructor. * @param parent :: Parent dialog. */ - CatalogPublishDialog::CatalogPublishDialog(QWidget *parent) : MantidQt::API::AlgorithmDialog(parent), m_uiForm() {} + CatalogPublishDialog::CatalogPublishDialog(QWidget *parent) : API::AlgorithmDialog(parent), m_uiForm() {} /// Initialise the layout void CatalogPublishDialog::initLayout() @@ -60,40 +58,44 @@ namespace MantidQt auto workspace = Mantid::API::WorkspaceFactory::Instance().createTable(); auto session = Mantid::API::CatalogManager::Instance().getActiveSessions(); - if (!session.empty()) + // We need to catch the exception to prevent a fatal error. + try { - // Cast a catalog to a catalogInfoService to access downloading functionality. - auto catalogInfoService = boost::dynamic_pointer_cast( - Mantid::API::CatalogManager::Instance().getCatalog(session.front()->getSessionId())); - // Check if the catalog created supports publishing functionality. - if (!catalogInfoService) throw std::runtime_error("The catalog that you are using does not support publishing."); - // Populate the workspace with investigations that the user has CREATE access to. - workspace = catalogInfoService->getPublishInvestigations(); + if (!session.empty()) + { + // Cast a catalog to a catalogInfoService to access downloading functionality. + auto catalogInfoService = boost::dynamic_pointer_cast( + Mantid::API::CatalogManager::Instance().getCatalog(session.front()->getSessionId())); + // Check if the catalog created supports publishing functionality. + if (!catalogInfoService) throw std::runtime_error("The catalog that you are using does not support publishing."); + // Populate the workspace with investigations that the user has CREATE access to. + workspace = catalogInfoService->getPublishInvestigations(); + } } - - // The user is not an investigator on any investigations and cannot publish - // or they are not logged into the catalog then update the related message.. - if (workspace->rowCount() == 0) + catch(std::runtime_error& e) { - setOptionalMessage("You cannot publish datafiles as you are not an investigator on any investigations or are not logged into the catalog."); - // Disable the input fields and run button to prevent user from running algorithm. - m_uiForm.scrollArea->setDisabled(true); - m_uiForm.runBtn->setDisabled(true); - return; + setOptionalMessage(e.what()); } - // Populate the form with investigations that the user can publish to. - for (size_t row = 0; row < workspace->rowCount(); row++) + if (workspace->rowCount() > 0) { - m_uiForm.investigationNumberCb->addItem(QString::fromStdString(workspace->getRef("InvestigationID",row))); - // Add better tooltip for ease of use (much easier to recall the investigation if title and instrument are also provided). - m_uiForm.investigationNumberCb->setItemData(static_cast(row), + // Populate the form with investigations that the user can publish to. + for (size_t row = 0; row < workspace->rowCount(); row++) + { + m_uiForm.investigationNumberCb->addItem(QString::fromStdString(workspace->getRef("InvestigationID",row))); + // Added tooltips to improve usability. + m_uiForm.investigationNumberCb->setItemData(static_cast(row), QString::fromStdString("The title of the investigation is: \"" + workspace->getRef("Title",row) + - "\".\nThe instrument of the investigation is: \"" + workspace->getRef("Instrument",row)) + "\".", - Qt::ToolTipRole); - // Set the user role to the sessionID. - m_uiForm.investigationNumberCb->setItemData(static_cast(row), + "\".\nThe instrument of the investigation is: \"" + workspace->getRef("Instrument",row)) + "\".", + Qt::ToolTipRole); + // Set the user role to the sessionID. + m_uiForm.investigationNumberCb->setItemData(static_cast(row), QString::fromStdString(workspace->getRef("SessionID",row)),Qt::UserRole); + } + } + else + { + disableDialog(); } } @@ -124,6 +126,15 @@ namespace MantidQt setPropertyValue("FileName", true); } + /** + * Diables fields on dialog to improve usability + */ + void CatalogPublishDialog::disableDialog() + { + m_uiForm.scrollArea->setDisabled(true); + m_uiForm.runBtn->setDisabled(true); + } + /** * Set/Update the sessionID of the `Session` property when * the user selects an investigation from the combo-box. diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp index 8e783e0eb2ea..6430a3d00c46 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp @@ -555,7 +555,7 @@ void MantidEV::selectWorkspace_slot() errorMessage("Previous operation still running, please wait until it is finished"); return; } - + std::string file_name = m_uiForm.EventFileName_ledt->text().trimmed().toStdString(); if (m_uiForm.convertToMDGroupBox->isChecked()) { if (!m_uiForm.loadDataGroupBox->isChecked()) @@ -566,12 +566,13 @@ void MantidEV::selectWorkspace_slot() return; } } - - std::string file_name = m_uiForm.EventFileName_ledt->text().trimmed().toStdString(); - if (file_name.empty()) + else { - errorMessage("Specify the name of an event file to load."); - return; + if (file_name.empty()) + { + errorMessage("Specify the name of an event file to load."); + return; + } } double minQ; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp index b006aaf72847..29163957e7e9 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp @@ -1155,9 +1155,9 @@ void SANSRunWindow::componentLOQDistances(boost::shared_ptrgetInstrument(); if( !instr ) return; - Mantid::Geometry::IObjComponent_const_sptr source = instr->getSource(); + Mantid::Geometry::IComponent_const_sptr source = instr->getSource(); if( source == boost::shared_ptr() ) return; - Mantid::Geometry::IObjComponent_const_sptr sample = instr->getSample(); + Mantid::Geometry::IComponent_const_sptr sample = instr->getSample(); if( sample == boost::shared_ptr() ) return; lms = source->getPos().distance(sample->getPos()) * 1000.; diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/CatalogHelper.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/CatalogHelper.h index 7fde3b004290..f0394e4ee0c9 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/CatalogHelper.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/CatalogHelper.h @@ -2,13 +2,13 @@ #define MANTIDQTWIDGETS_CATALOGHELPER_H_ #include "MantidAPI/AlgorithmManager.h" -#include +#include "WidgetDllOption.h" namespace MantidQt { namespace MantidWidgets { - class CatalogHelper + class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS CatalogHelper { public: @@ -34,6 +34,10 @@ namespace MantidQt const std::map &inputFields); /// Creates a time_t value from an input date ("23/06/2003") for comparison. time_t getTimevalue(const std::string& inputDate); + /// Executes the catalog login algorithm and returns true if user can login. + bool isValidCatalogLogin(); + /// Create a publishing dialog. + void catalogPublishDialog(); private: /// Creates an algorithm with the name provided. diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/CatalogHelper.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/CatalogHelper.cpp index e43c98661d9d..87898fbc80d3 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/CatalogHelper.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/CatalogHelper.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace MantidQt { @@ -246,6 +247,39 @@ namespace MantidQt return Mantid::Kernel::DateAndTime(isoDate).to_time_t(); } + /** + * Opens auto-generated dialog, and executes the catalog login algorithm. + * Returns true if login was a success. + */ + bool CatalogHelper::isValidCatalogLogin() + { + auto catalogAlgorithm = createCatalogAlgorithm("CatalogLogin"); + API::InterfaceManager interface; + auto loginDialog = interface.createDialog(catalogAlgorithm.get()); + + if(loginDialog->exec() == QDialog::Accepted) + { + executeAsynchronously(catalogAlgorithm); + if (catalogAlgorithm->isExecuted()) return true; + } + return false; + } + + /** + * Creates a publishing dialog GUI and runs the publishing algorithm when "Run" is pressed. + */ + void CatalogHelper::catalogPublishDialog() + { + auto catalogAlgorithm = createCatalogAlgorithm("CatalogPublish"); + API::InterfaceManager interface; + auto publishDialog = interface.createDialog(catalogAlgorithm.get()); + + if(publishDialog->exec() == QDialog::Accepted) + { + executeAsynchronously(catalogAlgorithm); + } + } + /** * Obtain the algorithm documentation for the given property. * @param properties :: A list of properties for a provided algorithm. diff --git a/Code/Mantid/MantidQt/SpectrumViewer/src/MatrixWSDataSource.cpp b/Code/Mantid/MantidQt/SpectrumViewer/src/MatrixWSDataSource.cpp index 6d3cbb847095..6d9b91a2bd11 100644 --- a/Code/Mantid/MantidQt/SpectrumViewer/src/MatrixWSDataSource.cpp +++ b/Code/Mantid/MantidQt/SpectrumViewer/src/MatrixWSDataSource.cpp @@ -292,14 +292,14 @@ void MatrixWSDataSource::GetInfoList( double x, return; } - IObjComponent_const_sptr source = instrument->getSource(); + IComponent_const_sptr source = instrument->getSource(); if ( source == 0 ) { ErrorHandler::Error("No SOURCE on instrument in MatrixWorkspace"); return; } - IObjComponent_const_sptr sample = instrument->getSample(); + IComponent_const_sptr sample = instrument->getSample(); if ( sample == 0 ) { ErrorHandler::Error("No SAMPLE on instrument in MatrixWorkspace"); diff --git a/Code/Mantid/docs/qtassistant/algorithm_help.py b/Code/Mantid/docs/qtassistant/algorithm_help.py index a4a0102bd827..2ec16b41fcd0 100644 --- a/Code/Mantid/docs/qtassistant/algorithm_help.py +++ b/Code/Mantid/docs/qtassistant/algorithm_help.py @@ -109,7 +109,7 @@ def process_algorithm(name, versions, qhp, outputdir, fetchimages, **kwargs): # if num_versions > 0: htmlfile.h2("Version %d" % version) - alg = mantid.FrameworkManager.createAlgorithm(name, version) + alg = mantid.AlgorithmManager.create(name, version) categories.extend(alg.categories()) htmlfile.h3("Summary") diff --git a/Code/Mantid/docs/qtassistant/make_algorithms_help.py b/Code/Mantid/docs/qtassistant/make_algorithms_help.py index d2878af4b854..c2e6d86ff41e 100755 --- a/Code/Mantid/docs/qtassistant/make_algorithms_help.py +++ b/Code/Mantid/docs/qtassistant/make_algorithms_help.py @@ -107,7 +107,7 @@ def process(algos, qhp, outputdir, options): for name in algos.keys(): versions = algos[name] - alg = mantid.FrameworkManager.createAlgorithm(name, versions[-1]) + alg = mantid.AlgorithmManager.create(name, versions[-1]) alias = alg.alias().strip() alg_categories = alg.categories() try: @@ -134,7 +134,7 @@ def process(algos, qhp, outputdir, options): letter_groups[letter].append((str(name), versions)) # add in the alias - alias = mantid.FrameworkManager.createAlgorithm(name, versions[-1]).alias().strip() + alias = mantid.AlgorithmManager.create(name, versions[-1]).alias().strip() if len(alias) > 0: letter = str(name)[0].upper() if not letter_groups.has_key(letter): diff --git a/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml b/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml index 75ec44032da2..840a36165da5 100644 --- a/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml +++ b/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml @@ -86,7 +86,7 @@ - + @@ -100,12 +100,26 @@ + + + + + + + + + + + + + + diff --git a/Code/Mantid/scripts/Inelastic/IndirectCommon.py b/Code/Mantid/scripts/Inelastic/IndirectCommon.py index a6e7e6a96c19..459f34300349 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectCommon.py +++ b/Code/Mantid/scripts/Inelastic/IndirectCommon.py @@ -1,8 +1,8 @@ from mantid.simpleapi import * from mantid import config, logger from IndirectImport import import_mantidplot -import sys, platform, os.path, math, datetime, re - +import sys, os.path, math, datetime, re + def StartTime(prog): logger.notice('----------') message = 'Program ' + prog +' started @ ' + str(datetime.datetime.now()) @@ -21,50 +21,67 @@ def loadInst(instrument): LoadEmptyInstrument(Filename=idf, OutputWorkspace=ws) def loadNexus(filename): - '''Loads a Nexus file into a workspace with the name based on the + ''' + Loads a Nexus file into a workspace with the name based on the filename. Convenience function for not having to play around with paths - in every function.''' + in every function. + ''' name = os.path.splitext( os.path.split(filename)[1] )[0] LoadNexus(Filename=filename, OutputWorkspace=name) return name - -def getInstrRun(file): - mo = re.match('([a-zA-Z]+)([0-9]+)',file) - instr_and_run = mo.group(0) # instr name + run number - instr = mo.group(1) # instrument prefix - run = mo.group(2) # run number as string - return instr,run - -def getWSprefix(wsname,runfile=None): - '''Returns a string of the form '__' on which - all of our other naming conventions are built. - The workspace is used to get the instrument parameters. If the runfile - string is given it is expected to be a string with instrument prefix - and run number. If it is empty then the workspace name is assumed to - contain this information + +def getInstrRun(ws_name): + ''' + Get the instrument name and run number from a workspace. + + @param ws_name - name of the workspace + @return tuple of form (instrument, run number) + ''' + ws = mtd[ws_name] + run_number = str(ws.getRunNumber()) + if run_number == '0': + #attempt to parse run number off of name + match = re.match('([a-zA-Z]+)([0-9]+)', ws_name) + if match: + run_number = match.group(2) + else: + raise RuntimeError("Could not find run number associated with workspace.") + + instrument = ws.getInstrument().getName() + facility = config.getFacility() + instrument = facility.instrument(instrument).filePrefix(int(run_number)) + instrument = instrument.lower() + return instrument, run_number + +def getWSprefix(wsname): + ''' + Returns a string of the form '__' on which + all of our other naming conventions are built. The workspace is used to get the + instrument parameters. ''' if wsname == '': return '' - if runfile is None: - runfile = wsname + ws = mtd[wsname] facility = config['default.facility'] + ws_run = ws.getRun() if 'facility' in ws_run: facility = ws_run.getLogData('facility').value - if facility == 'ILL': - inst = ws.getInstrument().getName() - runNo = ws.getRun()['run_number'].value - run_name = inst + '_'+ runNo + + (instrument, run_number) = getInstrRun(wsname) + if facility == 'ILL': + run_name = instrument + '_'+ run_number else: - (instr, run) = getInstrRun(runfile) - run_name = instr + run + run_name = instrument + run_number + try: analyser = ws.getInstrument().getStringParameter('analyser')[0] reflection = ws.getInstrument().getStringParameter('reflection')[0] except IndexError: analyser = '' reflection = '' + prefix = run_name + '_' + analyser + reflection + '_' return prefix diff --git a/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py b/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py index 6fb7d90c7645..b9b58a8a850a 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py +++ b/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py @@ -224,38 +224,47 @@ def confitSeq(inputWS, func, startX, endX, ftype, bgd, temperature=None, specMin # Elwin ############################################################################## -def GetTemperature(root,tempWS,log_type,Verbose): - (instr, run) = getInstrRun(root) - run_name = instr+run - log_name = run_name+'_'+log_type +def GetTemperature(root, tempWS, log_type, Verbose): + (instr, run_number) = getInstrRun(tempWS) + + facility = config.getFacility() + pad_num = facility.instrument(instr).zeroPadding(int(run_number)) + zero_padding = '0' * (pad_num - len(run_number)) + + run_name = instr + zero_padding + run_number + log_name = run_name.upper() + '.log' + run = mtd[tempWS].getRun() - unit1 = 'Temperature' # default values - unit2 = 'K' - if log_type in run: # test logs in WS + unit = ['Temperature', 'K'] + if log_type in run: + # test logs in WS tmp = run[log_type].value temp = tmp[len(tmp)-1] - xval = temp - mess = ' Run : '+run_name +' ; Temperature in log = '+str(temp) - else: # logs not in WS - logger.notice('Log parameter not found') - log_file = log_name+'.txt' - log_path = FileFinder.getFullPath(log_file) - if (log_path == ''): # log file does not exists - mess = ' Run : '+run_name +' ; Temperature file not found' - xval = int(run_name[-3:]) - unit1 = 'Run-number' - unit2 = 'last 3 digits' - else: # get from log file + + if Verbose: + mess = ' Run : '+run_name +' ; Temperature in log = '+str(temp) + logger.notice(mess) + else: + # logs not in WS + logger.warning('Log parameter not found in workspace. Searching for log file.') + log_path = FileFinder.getFullPath(log_name) + + if log_path != '': + # get temperature from log file LoadLog(Workspace=tempWS, Filename=log_path) run_logs = mtd[tempWS].getRun() - tmp = run_logs[log_name].value + tmp = run_logs[log_type].value temp = tmp[len(tmp)-1] - xval = temp mess = ' Run : '+run_name+' ; Temperature in file = '+str(temp) - if Verbose: - logger.notice(mess) - unit = [unit1,unit2] - return xval,unit + logger.warning(mess) + else: + # can't find log file + temp = int(run_name[-3:]) + unit = ['Run-number', 'last 3 digits'] + mess = ' Run : '+run_name +' ; Temperature file not found' + logger.warning(mess) + + return temp,unit def elwin(inputFiles, eRange, log_type='sample', Normalise = False, Save=False, Verbose=False, Plot=False): @@ -278,7 +287,7 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, (root, ext) = os.path.splitext(file_name) LoadNexus(Filename=file, OutputWorkspace=tempWS) nsam,ntc = CheckHistZero(tempWS) - (xval, unit) = GetTemperature(root,tempWS,log_type,Verbose) + (xval, unit) = GetTemperature(root,tempWS,log_type, Verbose) if Verbose: logger.notice('Reading file : '+file) if ( len(eRange) == 4 ): @@ -288,7 +297,7 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, elif ( len(eRange) == 2 ): ElasticWindow(InputWorkspace=tempWS, Range1Start=eRange[0], Range1End=eRange[1], OutputInQ='__eq1', OutputInQSquared='__eq2') - (instr, last) = getInstrRun(root) + (instr, last) = getInstrRun(tempWS) q1 = np.array(mtd['__eq1'].readX(0)) i1 = np.array(mtd['__eq1'].readY(0)) e1 = np.array(mtd['__eq1'].readE(0)) @@ -298,7 +307,7 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, e2 = np.array(mtd['__eq2'].readE(0)) if (nr == 0): CloneWorkspace(InputWorkspace='__eq1', OutputWorkspace='__elf') - first = getWSprefix(tempWS,root) + first = getWSprefix(tempWS) datX1 = q1 datY1 = i1 datE1 = e1 @@ -562,7 +571,7 @@ def fury(samWorkspaces, res_file, rebinParam, RES=True, Save=False, Verbose=Fals ExtractFFTSpectrum(InputWorkspace='sam_data', OutputWorkspace='sam_fft', FFTPart=2) Divide(LHSWorkspace='sam_fft', RHSWorkspace='sam_int', OutputWorkspace='sam') # Create save file name - savefile = getWSprefix('sam_data', root) + 'iqt' + savefile = getWSprefix(samWs) + 'iqt' outWSlist.append(savefile) Divide(LHSWorkspace='sam', RHSWorkspace='res', OutputWorkspace=savefile) #Cleanup Sample Files @@ -791,7 +800,6 @@ def furyfitSeq(inputWS, func, ftype, startx, endx, intensities_constrained=False if Verbose: logger.notice(ws + ' output to file : '+fpath) - print Plot if ( Plot != 'None' ): furyfitPlotSeq(fitWS, Plot) @@ -996,13 +1004,16 @@ def msdfit(inputs, startX, endX, Save=False, Verbose=False, Plot=True): StartTime('msdFit') workdir = config['defaultsave.directory'] log_type = 'sample' - file = inputs[0] - (direct, filename) = os.path.split(file) - (root, ext) = os.path.splitext(filename) - (instr, first) = getInstrRun(filename) + + file_name = inputs[0] + base_name = os.path.basename(file_name) + (root,ext) = os.path.splitext(base_name) + if Verbose: - logger.notice('Reading Run : '+file) - LoadNexusProcessed(FileName=file, OutputWorkspace=root) + logger.notice('Reading Run : ' + file_name) + + LoadNexusProcessed(FileName=file_name, OutputWorkspace=root) + nHist = mtd[root].getNumberHistograms() file_list = [] run_list = [] diff --git a/Code/Mantid/scripts/Inelastic/IndirectDiffractionReduction.py b/Code/Mantid/scripts/Inelastic/IndirectDiffractionReduction.py index e24231a189ce..198a7e3ed653 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectDiffractionReduction.py +++ b/Code/Mantid/scripts/Inelastic/IndirectDiffractionReduction.py @@ -21,13 +21,13 @@ def _setup_steps(self): else: return - step = mantid.FrameworkManager.createAlgorithm("ConvertUnits") + step = mantid.AlgorithmManager.create("ConvertUnits") step.setPropertyValue("Target", "dSpacing") step.setPropertyValue("EMode", "Elastic") self.append_step(step) if self._rebin_string is not None: - step = mantid.FrameworkManager.createAlgorithm("Rebin") + step = mantid.AlgorithmManager.create("Rebin") step.setPropertyValue("Params", self._rebin_string) self.append_step(step) else: diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 2d4aad6ffbf5..da338b26483a 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -95,19 +95,37 @@ def _load_transmission(self, inst=None, is_can=False, extra_options=dict()): self._load(inst, is_can, extra_options) return + # the intension of the code below is a good idea. Hence the reason why + # I have left in the code but commented it out. As of this writing + # LoadNexusMonitors throws an error if LoadNexusMonitors is a histogram + # i.e. this algorithm only works for event files at present. The error + # gets presented in red to the user and causes confusion. When either + # LoadNexusMonitor can load histogram data as well or other equivalent + # change the code below which is not commented out can be deleted and + # the code commented out can be uncomment and modified as necessary + + self._load(inst, is_can, extra_options) + workspace = self._get_workspace_name() + if workspace in mtd: + outWs = mtd[workspace] + if isinstance(outWs, IEventWorkspace): + if workspace + "_monitors" in mtd: + RenameWorkspace(InputWorkspace=workspace + "_monitors", OutputWorkspace=workspace) + self.periods_in_file = 1 + self._wksp_name = workspace # For sans, in transmission, we care only about the monitors. Hence, - # by trying to load only the monitors we speed up the reduction process. - # besides, we avoid loading events which is uselles for transmission. - # it may fail, if the input file was not a nexus file, in this case, + # by trying to load only the monitors we speed up the reduction process. + # besides, we avoid loading events which is useless for transmission. + # it may fail, if the input file was not a nexus file, in this case, # it pass the job to the default _load method. - try: - outWs = LoadNexusMonitors(self._data_file, OutputWorkspace=workspace) - self.periods_in_file = 1 - self._wksp_name = workspace - except: - self._load(inst, is_can, extra_options) + #try: + # outWs = LoadNexusMonitors(self._data_file, OutputWorkspace=workspace) + # self.periods_in_file = 1 + # self._wksp_name = workspace + #except: + # self._load(inst, is_can, extra_options) def _load(self, inst = None, is_can=False, extra_options=dict()): """ diff --git a/Code/Mantid/scripts/reduction/instruments/example/example_reducer.py b/Code/Mantid/scripts/reduction/instruments/example/example_reducer.py index e886d4fae634..bc21b2554ddc 100644 --- a/Code/Mantid/scripts/reduction/instruments/example/example_reducer.py +++ b/Code/Mantid/scripts/reduction/instruments/example/example_reducer.py @@ -98,7 +98,7 @@ def pre_process(self): #r._first_step.setProperty("Separator", "Tab") # Set up an algorithm to be used as part of a reduction step - alg = mantid.api.FrameworkManager.createAlgorithm("Scale") + alg = mantid.api.AlgorithmManager.create("Scale") alg.setProperty("Factor",2.5) r.set_normalizer(alg) diff --git a/Code/Mantid/scripts/reduction/instruments/inelastic/direct_command_interface.py b/Code/Mantid/scripts/reduction/instruments/inelastic/direct_command_interface.py index 45ef2f3e3209..0bf7b3b04b5e 100644 --- a/Code/Mantid/scripts/reduction/instruments/inelastic/direct_command_interface.py +++ b/Code/Mantid/scripts/reduction/instruments/inelastic/direct_command_interface.py @@ -3,7 +3,7 @@ """ # Import the specific commands that we need import mantid -from mantid.api import FrameworkManager +from mantid.api import AlgorithmManager from reduction.command_interface import * from inelastic_reducer import InelasticReducer @@ -46,12 +46,12 @@ def DefaultLoader(): ReductionSingleton().set_loader(step) def FixEi(ei): - alg = FrameworkManager.createAlgorithm("InelasticFixEi") + alg = AlgorithmManager.create("InelasticFixEi") alg.setProperty("Ei", ei) ReductionSingleton().set_ei_calculator(alg) def CalculateEi(guess=None): - alg = FrameworkManager.createAlgorithm("InelasticCalcEi") + alg = AlgorithmManager.create("InelasticCalcEi") alg.setProperty("EiGuess",guess) ReductionSingleton().set_ei_calculator(alg) diff --git a/Code/Mantid/scripts/reduction/reducer.py b/Code/Mantid/scripts/reduction/reducer.py index b53eb329aa72..c97dadd6a999 100644 --- a/Code/Mantid/scripts/reduction/reducer.py +++ b/Code/Mantid/scripts/reduction/reducer.py @@ -79,7 +79,7 @@ def execute(self, reducer, inputworkspace=None, outputworkspace=None): else: data_file = self._data_file - alg = mantid.api.FrameworkManager.createAlgorithm(algorithm) + alg = mantid.api.AlgorithmManager.create(algorithm) if not isinstance(alg, mantid.api.AlgorithmProxy): raise RuntimeError, "Reducer expects an Algorithm object from FrameworkManager, found '%s'" % str(type(alg)) @@ -220,7 +220,7 @@ def execute(self, reducer, inputworkspace=None, outputworkspace=None): """ if outputworkspace is None: outputworkspace = inputworkspace - alg = mantid.FrameworkManager.createAlgorithm(algorithm) + alg = mantid.AlgorithmManager.create(algorithm) if not isinstance(alg, mantid.api.AlgorithmProxy): raise RuntimeError, "Reducer expects an Algorithm object from FrameworkManager, found '%s'" % str(type(alg)) diff --git a/Code/Tools/Valgrind/APITest.supp b/Code/Tools/Valgrind/APITest.supp new file mode 100644 index 000000000000..ba01b1409a39 --- /dev/null +++ b/Code/Tools/Valgrind/APITest.supp @@ -0,0 +1,19 @@ +{ + + Memcheck:Leak + ... + fun:pthread_create@@GLIBC_2.2.5 + fun:??? + fun:_ZN20AlgorithmManagerTest16testThreadSafetyEv + ... +} +{ + + Memcheck:Leak + ... + fun:pthread_create@@GLIBC_2.2.5 + fun:??? + fun:_ZN17MemoryManagerTest13test_parallelEv + ... +} +