diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h index 83147785439b..1a0bad10c7f7 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadParameterFile.h @@ -84,7 +84,7 @@ namespace Mantid /// Algorithm's category for identification overriding a virtual method virtual const std::string category() const { return "DataHandling\\Instrument";} - static void execManually(std::string filename, Mantid::API::ExperimentInfo_sptr localWorkspace); + static void execManually(bool useString, std::string filename, std::string parameterString, Mantid::API::ExperimentInfo_sptr localWorkspace); private: /// Sets documentation strings for this algorithm diff --git a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp index 9e81ce5b3132..63188bc98028 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadIDFFromNexus.cpp @@ -90,7 +90,7 @@ void LoadIDFFromNexus::runLoadParameterFile(const MatrixWorkspace_sptr & workspa const std::string paramFile = directory + instrumentName + "_Parameters.xml"; try { - LoadParameterFile::execManually(paramFile, workspace); + LoadParameterFile::execManually(false, paramFile,"", workspace); } catch ( std::runtime_error& ) { g_log.notice() << "File " << paramFile << " not found or un-parsable. " "However, the instrument has been loaded successfully.\n"; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp index f79f227b0f30..4aec499f0b65 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp @@ -237,7 +237,7 @@ namespace Mantid try { // To allow the use of ExperimentInfo instead of workspace, we call it manually - LoadParameterFile::execManually(fullPathParamIDF, m_workspace); + LoadParameterFile::execManually(false, fullPathParamIDF, "", m_workspace); g_log.debug("Parameters loaded successfully."); } catch (std::invalid_argument& e) { diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index fa30cca9b7b5..128ff57d5ba7 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -35,6 +35,7 @@ This algorithm allows instrument parameters to be specified in a separate file f #include #include #include +#include #include #include #include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" @@ -46,6 +47,7 @@ using Poco::XML::Node; using Poco::XML::NodeList; using Poco::XML::NodeIterator; using Poco::XML::NodeFilter; +using Poco::XML::AutoPtr; using Mantid::Geometry::InstrumentDefinitionParser; @@ -59,8 +61,8 @@ DECLARE_ALGORITHM(LoadParameterFile) /// Sets documentation strings for this algorithm void LoadParameterFile::initDocs() { - this->setWikiSummary("Loads instrument parameters into a [[workspace]]. where these parameters are associated component names as defined in Instrument Definition File ([[InstrumentDefinitionFile|IDF]])."); - this->setOptionalMessage("Loads instrument parameters into a workspace. where these parameters are associated component names as defined in Instrument Definition File (IDF)."); + this->setWikiSummary("Loads instrument parameters into a [[workspace]]. where these parameters are associated component names as defined in Instrument Definition File ([[InstrumentDefinitionFile|IDF]]) or a string consisting of the contents of such.."); + this->setOptionalMessage("Loads instrument parameters into a workspace. where these parameters are associated component names as defined in Instrument Definition File (IDF) or a string consisting of the contents of such."); } @@ -80,8 +82,9 @@ void LoadParameterFile::init() declareProperty( new WorkspaceProperty("Workspace","Anonymous",Direction::InOut), "The name of the workspace to load the instrument parameters into." ); - declareProperty(new FileProperty("Filename","", FileProperty::Load, ".xml"), - "The filename (including its full or relative path) of a parameter defintion file. The file extension must either be .xml or .XML."); + declareProperty(new FileProperty("Filename","", FileProperty::OptionalLoad, ".xml"), + "The filename (including its full or relative path) of a parameter definition file. The file extension must either be .xml or .XML."); + declareProperty("ParameterXML","","The parameter definition XML as a string."); } /** Executes the algorithm. Reading in the file and creating and populating @@ -95,31 +98,58 @@ void LoadParameterFile::exec() // Retrieve the filename from the properties std::string filename = getPropertyValue("Filename"); + // Retrieve the parameter XML string from the properties + const Property * const parameterXMLProperty = getProperty("ParameterXML"); // to check whether it is default + std::string parameterXML = getPropertyValue("ParameterXML"); + + // Check the two properties (at least one must be set) + if( filename.empty() && parameterXMLProperty->isDefault()){ + throw Kernel::Exception::FileError("Either the Filename or ParameterXML property of LoadParameterFile most be specified to load an IDF" , filename); + } + // Get the input workspace const MatrixWorkspace_sptr localWorkspace = getProperty("Workspace"); - execManually(filename, localWorkspace); + execManually(!parameterXMLProperty->isDefault(), filename, parameterXML, localWorkspace); } -void LoadParameterFile::execManually(std::string filename, Mantid::API::ExperimentInfo_sptr localWorkspace) +void LoadParameterFile::execManually(bool useString, std::string filename, std::string parameterXML, Mantid::API::ExperimentInfo_sptr localWorkspace) { - // TODO: Refactor to remove the need for the const cast + // TODO: Refactor to remove the need for the const cast (ticket #8521) Instrument_sptr instrument = boost::const_pointer_cast(localWorkspace->getInstrument()->baseInstrument()); // Set up the DOM parser and parse xml file DOMParser pParser; - Document* pDoc; - try - { - pDoc = pParser.parse(filename); - } - catch(Poco::Exception& exc) - { - throw Kernel::Exception::FileError(exc.displayText() + ". Unable to parse File:", filename); - } - catch(...) + AutoPtr pDoc; + + if(useString){ + try + { + pDoc = pParser.parseString(parameterXML); + } + catch(Poco::Exception& exc) + { + throw Kernel::Exception::FileError (exc.displayText() + ". Unable to parse parameter XML string","ParameterXML"); + } + catch(...) + { + throw Kernel::Exception::FileError("Unable to parse parameter XML string","ParameterXML"); + } + } + else { - throw Kernel::Exception::FileError("Unable to parse File:" , filename); + try + { + pDoc = pParser.parse(filename); + } + catch(Poco::Exception& exc) + { + throw Kernel::Exception::FileError(exc.displayText() + ". Unable to parse File:", filename); + } + catch(...) + { + throw Kernel::Exception::FileError("Unable to parse File:" , filename); + } } // Get pointer to root element @@ -136,7 +166,6 @@ void LoadParameterFile::execManually(std::string filename, Mantid::API::Experime // populate parameter map of workspace localWorkspace->populateInstrumentParameters(); - pDoc->release(); } } // namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h index 5c16406ed974..e6efa9b134b0 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadParameterFileTest.h @@ -30,24 +30,9 @@ class LoadParameterFileTest : public CxxTest::TestSuite void testExecIDF_for_unit_testing2() // IDF stands for Instrument Definition File { - LoadInstrument loaderIDF2; - - TS_ASSERT_THROWS_NOTHING(loaderIDF2.initialize()); - - //create a workspace with some sample data - wsName = "LoadParameterFileTestIDF2"; - Workspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D",1,1,1); - Workspace2D_sptr ws2D = boost::dynamic_pointer_cast(ws); - - //put this workspace in the data service - TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add(wsName, ws2D)); - // Path to test input file assumes Test directory checked out from SVN - loaderIDF2.setPropertyValue("Filename", "IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml"); - //inputFile = loaderIDF2.getPropertyValue("Filename"); - loaderIDF2.setPropertyValue("Workspace", wsName); - TS_ASSERT_THROWS_NOTHING(loaderIDF2.execute()); - TS_ASSERT( loaderIDF2.isExecuted() ); + // Create workspace wsName + load_IDF2(); // load in additional parameters LoadParameterFile loaderPF; @@ -91,6 +76,101 @@ class LoadParameterFileTest : public CxxTest::TestSuite } + void testExec_withIDFString() // Test use of string instead of file + { + + // Create workspace + load_IDF2(); + + // Define parameter XML string + std::string parameterXML = + "" + "" + " " + " " + " " + " " + " " + " " + ""; + + // load in additional parameters + LoadParameterFile loaderPF; + TS_ASSERT_THROWS_NOTHING(loaderPF.initialize()); + loaderPF.setPropertyValue("ParameterXML", parameterXML); + loaderPF.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderPF.execute()); + TS_ASSERT( loaderPF.isExecuted() ); + + // Get back the saved workspace + MatrixWorkspace_sptr output; + TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieveWS(wsName)); + + ParameterMap& paramMap = output->instrumentParameters(); + boost::shared_ptr i = output->getInstrument(); + boost::shared_ptr ptrDet = i->getDetector(1008); + TS_ASSERT_EQUALS( ptrDet->getID(), 1008); + TS_ASSERT_EQUALS( ptrDet->getName(), "combined translation6"); + Parameter_sptr param = paramMap.get(&(*ptrDet), "fjols"); + TS_ASSERT_DELTA( param->value(), 20.0, 0.0001); + param = paramMap.get(&(*ptrDet), "nedtur"); + TS_ASSERT_DELTA( param->value(), 77.0, 0.0001); + param = paramMap.get(&(*ptrDet), "fjols-test-paramfile"); + TS_ASSERT_DELTA( param->value(), 52.0, 0.0001); + + std::vector dummy = paramMap.getDouble("nickel-holder", "klovn"); + TS_ASSERT_DELTA( dummy[0], 1.0, 0.0001); + dummy = paramMap.getDouble("nickel-holder", "pos"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "rot"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "taabe"); + TS_ASSERT_DELTA (dummy[0], 200.0, 0.0001); + dummy = paramMap.getDouble("nickel-holder", "mistake"); + TS_ASSERT_EQUALS (dummy.size(), 0); + dummy = paramMap.getDouble("nickel-holder", "fjols-test-paramfile"); + TS_ASSERT_DELTA (dummy[0], 2010.0, 0.0001); + + AnalysisDataService::Instance().remove(wsName); + + } + + void test_failure_if_no_file_or_string() + { + // Create workspace + load_IDF2(); + + // Run algorithm without file or string properties set + LoadParameterFile loaderPF; + TS_ASSERT_THROWS_NOTHING(loaderPF.initialize()); + loaderPF.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderPF.execute()); + TS_ASSERT( ! loaderPF.execute() ) + } + + void load_IDF2() + { + LoadInstrument loaderIDF2; + + TS_ASSERT_THROWS_NOTHING(loaderIDF2.initialize()); + + //create a workspace with some sample data + wsName = "LoadParameterFileTestIDF2"; + Workspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D",1,1,1); + Workspace2D_sptr ws2D = boost::dynamic_pointer_cast(ws); + + //put this workspace in the data service + TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add(wsName, ws2D)); + + // Path to test input file assumes Test directory checked out from git + loaderIDF2.setPropertyValue("Filename", "IDFs_for_UNIT_TESTING/IDF_for_UNIT_TESTING2.xml"); + //inputFile = loaderIDF2.getPropertyValue("Filename"); + loaderIDF2.setPropertyValue("Workspace", wsName); + TS_ASSERT_THROWS_NOTHING(loaderIDF2.execute()); + TS_ASSERT( loaderIDF2.isExecuted() ); + + } + private: std::string inputFile;