diff --git a/Code/Mantid/Framework/API/CMakeLists.txt b/Code/Mantid/Framework/API/CMakeLists.txt index 7f546b2dfd96..8835e9543d7b 100644 --- a/Code/Mantid/Framework/API/CMakeLists.txt +++ b/Code/Mantid/Framework/API/CMakeLists.txt @@ -67,7 +67,7 @@ set ( SRC_FILES src/ImmutableCompositeFunction.cpp src/ImplicitFunctionParameterParserFactory.cpp src/ImplicitFunctionParserFactory.cpp - src/ImplictFunctionFactory.cpp + src/ImplicitFunctionFactory.cpp src/InstrumentDataService.cpp src/JointDomain.cpp src/LinearScale.cpp diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h index bbba909b9cc1..1ee14af82d2f 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDNode.h @@ -1,20 +1,34 @@ #ifndef IMD_NODE_H_ #define IMD_NODE_H_ -#include #include -#include "MantidKernel/ThreadScheduler.h" -#include "MantidAPI/IBoxControllerIO.h" -#include "MantidGeometry/MDGeometry/MDImplicitFunction.h" -#include "MantidGeometry/MDGeometry/MDDimensionExtents.h" -#include "MantidAPI/BoxController.h" -#include "MantidAPI/CoordTransform.h" +#include +#include +#include "MantidKernel/VMD.h" +#include "MantidGeometry/MDGeometry/MDTypes.h" namespace Mantid { +namespace Kernel +{ + class ISaveable; + class ThreadScheduler; +} + +namespace Geometry +{ + template + class MDDimensionExtents; + class MDImplicitFunction; +} + namespace API { +class BoxController; +class IBoxControllerIO; +class CoordTransform; + class IMDNode { /** This is an interface to MDBox or MDGridBox of an MDWorkspace diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/ImplicitFunctionParameter.h b/Code/Mantid/Framework/API/inc/MantidAPI/ImplicitFunctionParameter.h index 96d6b2926c09..91805a9a67e7 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/ImplicitFunctionParameter.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/ImplicitFunctionParameter.h @@ -70,16 +70,16 @@ namespace Mantid { using namespace Poco::XML; AutoPtr pDoc = new Document; - Element* paramElement = pDoc->createElement("Parameter"); + AutoPtr paramElement = pDoc->createElement("Parameter"); pDoc->appendChild(paramElement); - Element* typeElement = pDoc->createElement("Type"); - Text* typeText = pDoc->createTextNode(this->getName()); + AutoPtr typeElement = pDoc->createElement("Type"); + AutoPtr typeText = pDoc->createTextNode(this->getName()); typeElement->appendChild(typeText); paramElement->appendChild(typeElement); - Element* valueElement = pDoc->createElement("Value"); - Text* valueText = pDoc->createTextNode(valueXMLtext); + AutoPtr valueElement = pDoc->createElement("Value"); + AutoPtr valueText = pDoc->createTextNode(valueXMLtext); valueElement->appendChild(valueText); paramElement->appendChild(valueElement); diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/MDGeometry.h b/Code/Mantid/Framework/API/inc/MantidAPI/MDGeometry.h index 4480d541a526..7bc5005bce87 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/MDGeometry.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/MDGeometry.h @@ -1,20 +1,17 @@ #ifndef MANTID_API_MDGEOMETRY_H_ #define MANTID_API_MDGEOMETRY_H_ - -#include "MantidAPI/CoordTransform.h" -#include "MantidGeometry/MDGeometry/IMDDimension.h" -#include "MantidKernel/Exception.h" + #include "MantidKernel/System.h" #include "MantidKernel/VMD.h" +#include "MantidGeometry/MDGeometry/IMDDimension.h" #include "MantidAPI/AnalysisDataService.h" #include - namespace Mantid { namespace API { - + class CoordTransform; class IMDWorkspace; /** Describes the geometry (i.e. dimensions) of an IMDWorkspace. diff --git a/Code/Mantid/Framework/API/src/Algorithm.cpp b/Code/Mantid/Framework/API/src/Algorithm.cpp index 800f78aff5e6..bb8ff78c1c73 100644 --- a/Code/Mantid/Framework/API/src/Algorithm.cpp +++ b/Code/Mantid/Framework/API/src/Algorithm.cpp @@ -1247,6 +1247,8 @@ namespace Mantid // Don't make the new algorithm a child so that it's workspaces are stored correctly alg_sptr->setChild(false); + alg_sptr->setRethrows(true); + IAlgorithm* alg = alg_sptr.get(); // Set all non-workspace properties this->copyNonWorkspaceProperties(alg, int(entry)+1); @@ -1298,8 +1300,17 @@ namespace Mantid } // for each OutputWorkspace property // ------------ Execute the algo -------------- - if (!alg->execute()) - throw std::runtime_error("Execution of " + this->name() + " for group entry " + Strings::toString(entry+1) + " failed."); + try + { + alg->execute(); + } + catch(std::exception& e) + { + std::ostringstream msg; + msg << "Execution of " << this->name() << " for group entry " << (entry+1) << " failed: "; + msg << e.what(); // Add original message + throw std::runtime_error(msg.str()); + } // ------------ Fill in the output workspace group ------------------ // this has to be done after execute() because a workspace must exist diff --git a/Code/Mantid/Framework/API/src/BoxController.cpp b/Code/Mantid/Framework/API/src/BoxController.cpp index 001cb4219da9..8bdb8c2e0c98 100644 --- a/Code/Mantid/Framework/API/src/BoxController.cpp +++ b/Code/Mantid/Framework/API/src/BoxController.cpp @@ -117,34 +117,41 @@ namespace API std::string vecStr; element = pDoc->createElement("NumDims"); - element->appendChild( pDoc->createTextNode(boost::str(boost::format("%d") % this->getNDims())) ); + text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getNDims())); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("MaxId"); - element->appendChild( pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxId())) ); + text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxId())); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("SplitThreshold"); - element->appendChild( pDoc->createTextNode(boost::str(boost::format("%d") % this->getSplitThreshold())) ); + text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getSplitThreshold())); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("MaxDepth"); - element->appendChild( pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxDepth())) ); + text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxDepth())); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("SplitInto"); vecStr = Kernel::Strings::join( this->m_splitInto.begin(), this->m_splitInto.end(), ","); - element->appendChild( pDoc->createTextNode( vecStr ) ); + text = pDoc->createTextNode( vecStr ); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("NumMDBoxes"); vecStr = Kernel::Strings::join( this->m_numMDBoxes.begin(), this->m_numMDBoxes.end(), ","); - element->appendChild( pDoc->createTextNode( vecStr ) ); + text = pDoc->createTextNode( vecStr ); + element->appendChild( text ); pBoxElement->appendChild(element); element = pDoc->createElement("NumMDGridBoxes"); vecStr = Kernel::Strings::join( this->m_numMDGridBoxes.begin(), this->m_numMDGridBoxes.end(), ","); - element->appendChild( pDoc->createTextNode( vecStr ) ); + text = pDoc->createTextNode( vecStr ); + element->appendChild( text ); pBoxElement->appendChild(element); //Create a string representation of the DOM tree. @@ -182,7 +189,7 @@ namespace API { using namespace Poco::XML; Poco::XML::DOMParser pParser; - Poco::XML::Document* pDoc = pParser.parseString(xml); + Poco::AutoPtr pDoc = pParser.parseString(xml); Poco::XML::Element* pBoxElement = pDoc->documentElement(); std::string s; diff --git a/Code/Mantid/Framework/API/src/ImplictFunctionFactory.cpp b/Code/Mantid/Framework/API/src/ImplicitFunctionFactory.cpp similarity index 96% rename from Code/Mantid/Framework/API/src/ImplictFunctionFactory.cpp rename to Code/Mantid/Framework/API/src/ImplicitFunctionFactory.cpp index 3c963752e42f..ce05ad08e912 100644 --- a/Code/Mantid/Framework/API/src/ImplictFunctionFactory.cpp +++ b/Code/Mantid/Framework/API/src/ImplicitFunctionFactory.cpp @@ -42,7 +42,7 @@ namespace Mantid { using namespace Poco::XML; DOMParser pParser; - Document* pDoc = pParser.parseString(processXML); + Poco::AutoPtr pDoc = pParser.parseString(processXML); Element* pInstructionsXML = pDoc->documentElement(); ImplicitFunctionParser* funcParser = Mantid::API::ImplicitFunctionParserFactory::Instance().createImplicitFunctionParserFromXML(processXML); diff --git a/Code/Mantid/Framework/API/src/ImplicitFunctionParameterParserFactory.cpp b/Code/Mantid/Framework/API/src/ImplicitFunctionParameterParserFactory.cpp index ce3764aba2a9..7cd919d9ba7b 100644 --- a/Code/Mantid/Framework/API/src/ImplicitFunctionParameterParserFactory.cpp +++ b/Code/Mantid/Framework/API/src/ImplicitFunctionParameterParserFactory.cpp @@ -32,7 +32,7 @@ namespace Mantid { throw std::runtime_error("Expected passed element to be ParameterList."); } - Poco::XML::NodeList* parameters = parametersElement->getElementsByTagName("Parameter"); + Poco::AutoPtr parameters = parametersElement->getElementsByTagName("Parameter"); ImplicitFunctionParameterParser* paramParser = NULL; ImplicitFunctionParameterParser* nextParser = NULL; for(unsigned long i = 0 ; i < parameters->length(); i++) diff --git a/Code/Mantid/Framework/API/src/ImplicitFunctionParserFactory.cpp b/Code/Mantid/Framework/API/src/ImplicitFunctionParserFactory.cpp index 3d1ddeddb980..66189cbd305e 100644 --- a/Code/Mantid/Framework/API/src/ImplicitFunctionParserFactory.cpp +++ b/Code/Mantid/Framework/API/src/ImplicitFunctionParserFactory.cpp @@ -44,7 +44,7 @@ namespace Mantid ImplicitFunctionParameterParser* paramParser = Mantid::API::ImplicitFunctionParameterParserFactory::Instance().createImplicitFunctionParameterParserFromXML(parametersElement); functionParser->setParameterParser(paramParser); - Poco::XML::NodeList* childFunctions = functionElement->getElementsByTagName("Function"); + Poco::AutoPtr childFunctions = functionElement->getElementsByTagName("Function"); ImplicitFunctionParser* childParser = NULL; for(unsigned long i = 0; i < childFunctions->length(); i++) { @@ -74,7 +74,7 @@ namespace Mantid { using namespace Poco::XML; DOMParser pParser; - Document* pDoc = pParser.parseString(functionXML); + AutoPtr pDoc = pParser.parseString(functionXML); Element* pRootElem = pDoc->documentElement(); return createImplicitFunctionParserFromXML(pRootElem); diff --git a/Code/Mantid/Framework/API/src/MDGeometry.cpp b/Code/Mantid/Framework/API/src/MDGeometry.cpp index 00056b1f3ae5..94c84c6fad15 100644 --- a/Code/Mantid/Framework/API/src/MDGeometry.cpp +++ b/Code/Mantid/Framework/API/src/MDGeometry.cpp @@ -1,5 +1,6 @@ #include "MantidAPI/MDGeometry.h" #include "MantidKernel/System.h" +#include "MantidAPI/CoordTransform.h" #include "MantidGeometry/MDGeometry/MDGeometryXMLBuilder.h" #include "MantidGeometry/MDGeometry/IMDDimension.h" #include "MantidGeometry/MDGeometry/MDHistoDimension.h" diff --git a/Code/Mantid/Framework/API/test/AlgorithmTest.h b/Code/Mantid/Framework/API/test/AlgorithmTest.h index 438f18315673..725bf004f9c2 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmTest.h @@ -109,6 +109,40 @@ class AlgorithmWithValidateInputs : public Algorithm }; DECLARE_ALGORITHM(AlgorithmWithValidateInputs) +/** + * Algorithm which fails on specified workspace + */ +class FailingAlgorithm : public Algorithm +{ +public: + FailingAlgorithm() : Algorithm() {} + virtual ~FailingAlgorithm() {} + const std::string name() const { return "FailingAlgorithm"; } + int version() const { return 1; } + + static const std::string FAIL_MSG; + + void init() + { + declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input)); + declareProperty("WsNameToFail", ""); + } + + void exec() + { + std::string wsNameToFail = getPropertyValue("WsNameToFail"); + std::string wsName = getPropertyValue("InputWorkspace"); + + if ( wsName == wsNameToFail ) + { + throw std::runtime_error(FAIL_MSG); + } + } +}; + +const std::string FailingAlgorithm::FAIL_MSG("Algorithm failed as requested"); + +DECLARE_ALGORITHM(FailingAlgorithm) class AlgorithmTest : public CxxTest::TestSuite { @@ -699,7 +733,30 @@ class AlgorithmTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( ws1->readY(0)[0], 234 ); } + void test_processGroups_failOnGroupMemberErrorMessage() + { + makeWorkspaceGroup("A", "A_1,A_2,A_3"); + + FailingAlgorithm alg; + alg.initialize(); + alg.setRethrows(true); + alg.setLogging(false); + alg.setPropertyValue("InputWorkspace", "A"); + alg.setPropertyValue("WsNameToFail", "A_2"); + + try + { + alg.execute(); + TS_FAIL("Exception wasn't thrown"); + } + catch(std::runtime_error& e) + { + std::string msg(e.what()); + TSM_ASSERT("Error message should contain original error", + msg.find(FailingAlgorithm::FAIL_MSG) != std::string::npos); + } + } private: IAlgorithm_sptr runFromString(const std::string & input) diff --git a/Code/Mantid/Framework/API/test/VectorParameterParserTest.h b/Code/Mantid/Framework/API/test/VectorParameterParserTest.h index 5550f15b35f7..ece3e673a302 100644 --- a/Code/Mantid/Framework/API/test/VectorParameterParserTest.h +++ b/Code/Mantid/Framework/API/test/VectorParameterParserTest.h @@ -64,7 +64,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite { DOMParser pParser; std::string xmlToParse = "ConcreteVectorDblParam1, 2, 3"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorDblParamParser parser; @@ -87,7 +87,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite { DOMParser pParser; std::string xmlToParse = "SucessorVectorParameter1, 2, 3"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorDblParamParser parser; @@ -103,7 +103,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite DOMParser pParser; std::string xmlToParse = "SucessorVectorParameter1, 2, 3"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorDblParamParser parser; @@ -119,7 +119,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite { DOMParser pParser; std::string xmlToParse = "ConcreteVectorBoolParam1, 0, 1, 0"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorBoolParamParser parser; @@ -145,7 +145,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite { DOMParser pParser; std::string xmlToParse = "OTHER1, 0, 1, 0"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorBoolParamParser parser; @@ -156,7 +156,7 @@ class VectorParameterParserTest : public CxxTest::TestSuite { DOMParser pParser; std::string xmlToParse = "ConcreteVectorDblParam1, 0, 1, 0"; - Document* pDoc = pParser.parseString(xmlToParse); + Poco::AutoPtr pDoc = pParser.parseString(xmlToParse); Element* pRootElem = pDoc->documentElement(); ConcreteVectorDblParamParser parser; diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h index 266c77aba651..b96153c7ac1b 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h @@ -95,7 +95,7 @@ class DLLExport CheckWorkspacesMatch : public API::Algorithm void doPeaksComparison(API::IPeaksWorkspace_sptr tws1, API::IPeaksWorkspace_sptr tws2); void doTableComparison(API::ITableWorkspace_const_sptr tws1, API::ITableWorkspace_const_sptr tws2); void doMDComparison(API::Workspace_sptr w1, API::Workspace_sptr w2); - bool checkEventLists(DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2); + bool compareEventWorkspaces(DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2); bool checkData(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); bool checkAxes(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); bool checkSpectraMap(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); @@ -104,6 +104,11 @@ class DLLExport CheckWorkspacesMatch : public API::Algorithm bool checkSample(const API::Sample& sample1, const API::Sample& sample2); bool checkRunProperties(const API::Run& run1, const API::Run& run2); + /// Compare 2 EventsList + int compareEventsListInDetails(const DataObjects::EventList &el1, const DataObjects::EventList &el2, + double tolTof, double tolWeight, int64_t tolPulse, bool printdetails, + size_t& numdiffpulse, size_t& numdifftof, size_t& numdiffboth) const; + std::string result; ///< the result string API::Progress * prog; diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/GetEi2.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/GetEi2.h index 9e6acbb0be30..e4fefc3f70e9 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/GetEi2.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/GetEi2.h @@ -96,7 +96,7 @@ namespace Algorithms /// Conversion factor between time and energy double m_t_to_mev; /// The percentage deviation from the estimated peak time that defines the peak region - const double m_tof_window; + double m_tof_window; /// Number of std deviations to consider a peak const double m_peak_signif; /// Number of std deviations to consider a peak for the derivative diff --git a/Code/Mantid/Framework/Algorithms/src/ApplyDeadTimeCorr.cpp b/Code/Mantid/Framework/Algorithms/src/ApplyDeadTimeCorr.cpp index 1f8fa27ab607..a50117199aa1 100644 --- a/Code/Mantid/Framework/Algorithms/src/ApplyDeadTimeCorr.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ApplyDeadTimeCorr.cpp @@ -77,6 +77,11 @@ void ApplyDeadTimeCorr::exec() { double numGoodFrames = boost::lexical_cast(run.getProperty("goodfrm")->value()); + if (numGoodFrames == 0) + { + throw std::runtime_error("Number of good frames in the workspace is zero"); + } + // Duplicate the input workspace. Only need to change Y values based on dead time corrections IAlgorithm_sptr duplicate = createChildAlgorithm("CloneWorkspace"); duplicate->initialize(); diff --git a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp index 5eedd85c5ff1..fb67948ccff2 100644 --- a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp @@ -20,6 +20,7 @@ In the case of [[EventWorkspace]]s, they are checked to hold identical event lis #include "MantidAPI/IPeak.h" #include "MantidAPI/TableRow.h" #include "MantidDataObjects/EventWorkspace.h" +#include "MantidDataObjects/Events.h" #include "MantidGeometry/MDGeometry/IMDDimension.h" #include @@ -167,9 +168,12 @@ void CheckWorkspacesMatch::init() declareProperty("ToleranceRelErr",false, "Treat tolerance as relative error rather then the absolute error.\n"\ "This is only applicable to Matrix workspaces."); declareProperty("CheckAllData",false, "Usually checking data ends when first mismatch occurs. This forces algorithm to check all data and print mismatch to the debug log.\n"\ - "Very often such logs are huge so making it true should be the last option."); // Have this one false by default - it can be a lot of printing. + "Very often such logs are huge so making it true should be the last option."); + // Have this one false by default - it can be a lot of printing. - + declareProperty("NumberMismatchedSpectraToPrint", 1, "Number of mismatched spectra from lowest to be listed. "); + + declareProperty("DetailedPrintIndex", EMPTY_INT(), "Mismatched spectra that will be printed out in details. "); } @@ -287,7 +291,8 @@ void CheckWorkspacesMatch::doComparison() { prog = new Progress(this, 0.0, 1.0, numhist*5); - if ( ! checkEventLists(ews1, ews2) ) return; + // Compare event lists to see whether 2 event workspaces match each other + if ( ! compareEventWorkspaces(ews1, ews2) ) return; } else { @@ -321,58 +326,159 @@ void CheckWorkspacesMatch::doComparison() return; } -bool CheckWorkspacesMatch::checkEventLists(DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2) +//------------------------------------------------------------------------------------------------ +/** Check whether 2 event lists are identical + */ +bool CheckWorkspacesMatch::compareEventWorkspaces(DataObjects::EventWorkspace_const_sptr ews1, + DataObjects::EventWorkspace_const_sptr ews2) { - // Both will end up sorted anyway - ews1->sortAll(PULSETIMETOF_SORT, prog); - ews2->sortAll(PULSETIMETOF_SORT, prog); + bool checkallspectra = getProperty("CheckAllData"); + int numspec2print = getProperty("NumberMismatchedSpectraToPrint"); + int wsindex2print = getProperty("DetailedPrintIndex"); + // Compare number of spectra if (ews1->getNumberHistograms() != ews2->getNumberHistograms()) { result = "Mismatched number of histograms."; return false; } - // determine the tolerance for "tof" attribute of events - double ToleranceTOF = Tolerance; - // actual time-of flight is 50 nanoseconds - if ((ews1->getAxis(0)->unit()->label() == "microsecond") - || (ews2->getAxis(0)->unit()->label() == "microsecond")) + if (ews1->getEventType() != ews2->getEventType()) + { + result = "Mismatched type of events in the EventWorkspaces."; + return false; + } + + // Both will end up sorted anyway + ews1->sortAll(PULSETIMETOF_SORT, prog); + ews2->sortAll(PULSETIMETOF_SORT, prog); + + // Determine the tolerance for "tof" attribute and "weight" of events + double toleranceWeight = Tolerance; // Standard tolerance + int64_t tolerancePulse = 1; + double toleranceTOF = 0.05; + if ((ews1->getAxis(0)->unit()->label() != "microsecond") + || (ews2->getAxis(0)->unit()->label() != "microsecond")) { - ToleranceTOF = 0.05; + g_log.warning() << "Event workspace has unit as " << ews1->getAxis(0)->unit()->label() << " and " + << ews2->getAxis(0)->unit()->label() << ". Tolerance of TOF is set to 0.05 still. " + << "\n"; + toleranceTOF = 0.05; } + g_log.notice() << "TOF Tolerance = " << toleranceTOF << "\n"; bool mismatchedEvent = false; int mismatchedEventWI = 0; + + size_t numUnequalNumEventsSpectra = 0; + size_t numUnequalEvents = 0; + size_t numUnequalTOFEvents = 0; + size_t numUnequalPulseEvents = 0; + size_t numUnequalBothEvents = 0; + + std::vector vec_mismatchedwsindex; + PARALLEL_FOR2(ews1, ews2) - for (int i=0; i(ews1->getNumberHistograms()); ++i) - { + for (int i=0; i(ews1->getNumberHistograms()); i++) + { PARALLEL_START_INTERUPT_REGION - prog->report(); - if (!mismatchedEvent) // This guard will avoid checking unnecessarily + prog->report("EventLists"); + if (!mismatchedEvent || checkallspectra) // This guard will avoid checking unnecessarily { const EventList &el1 = ews1->getEventList(i); const EventList &el2 = ews2->getEventList(i); - if (!el1.equals(el2, ToleranceTOF, Tolerance, 1)) + bool printdetail = (i == wsindex2print); + if (printdetail) + { + g_log.information() << "Spectrum " << i << " is set to print out in details. " << "\n"; + } + + if (!el1.equals(el2, toleranceTOF, toleranceWeight, tolerancePulse)) { - PARALLEL_CRITICAL(mismatch) + size_t tempNumTof = 0; + size_t tempNumPulses = 0; + size_t tempNumBoth = 0; + + int tempNumUnequal = 0; + + if (el1.getNumberEvents() != el2.getNumberEvents()) + { + // Number of events are different + tempNumUnequal = -1; + } + else + { + tempNumUnequal = compareEventsListInDetails(el1, el2, toleranceTOF, toleranceWeight, tolerancePulse, printdetail, + tempNumPulses, tempNumTof, tempNumBoth); + } + mismatchedEvent = true; mismatchedEventWI = i; - } + PARALLEL_CRITICAL(CheckWorkspacesMatch) + { + if (tempNumUnequal == -1) + { + // 2 spectra have different number of events + ++ numUnequalNumEventsSpectra; + } + else + { + // 2 spectra have some events different to each other + numUnequalEvents += static_cast(tempNumUnequal); + numUnequalTOFEvents += tempNumTof; + numUnequalPulseEvents += tempNumPulses; + numUnequalBothEvents += tempNumBoth; + } + + vec_mismatchedwsindex.push_back(i); + } // Parallel critical region + + } // If elist 1 is not equal to elist 2 } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION + bool wsmatch; if ( mismatchedEvent) { std::ostringstream mess; - mess << "Mismatched event list at workspace index " << mismatchedEventWI; + if (checkallspectra) + { + if (numUnequalNumEventsSpectra > 0) + mess << "Total " << numUnequalNumEventsSpectra << " spectra have different number of events. " + << "\n"; + + mess << "Total " << numUnequalEvents << " (in " << ews1->getNumberEvents() << ") events are differrent. " + << numUnequalTOFEvents << " have different TOF; " << numUnequalPulseEvents << " have different pulse time; " + << numUnequalBothEvents << " have different in both TOF and pulse time. " << "\n"; + + mess << "Mismatched event lists include " << vec_mismatchedwsindex.size() << " of " + << "total " << ews1->getNumberHistograms() << " spectra. " << "\n"; + + std::sort(vec_mismatchedwsindex.begin(), vec_mismatchedwsindex.end()); + numspec2print = std::min(numspec2print, static_cast(vec_mismatchedwsindex.size())); + for (int i = 0; i < numspec2print; ++i) + { + mess << vec_mismatchedwsindex[i] << ", "; + if ( (i+1)%10 == 0 ) mess << "\n"; + } + } + else + { + mess << "Quick comparison shows 2 workspaces do not match. " + << "First found mismatched event list is at workspace index " << mismatchedEventWI; + } result = mess.str(); - return false; + wsmatch = false; + } + else + { + result = "Success!"; + wsmatch = true; } - return true; + return wsmatch; } /** Checks that the data matches @@ -412,7 +518,7 @@ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::M for ( int i = 0; i < static_cast(numHists); ++i ) { PARALLEL_START_INTERUPT_REGION - prog->report(); + prog->report("Histograms"); if ( resultBool || checkAllData ) // Avoid checking unnecessarily { @@ -754,6 +860,100 @@ bool CheckWorkspacesMatch::checkRunProperties(const API::Run& run1, const API::R return true; } +//------------------------------------------------------------------------------------------------ +/** Compare 2 different events list with detailed information output (Linear) + * It assumes that the number of events between these 2 are identical + * el1 :: event list 1 + * el2 :: event list 2 + * tolfTOF :: tolerance of Time-of-flight (in micro-second) + * tolWeight :: tolerance of weight for weighted neutron events + * tolPulse :: tolerance of pulse time (in nanosecond) + * NOTE: there is no need to compare the event type as it has been done by other tjype of check + * printdetails :: option for comparing. -1: simple, 0: full but no print, 1: full with print + * @return :: int. -1: different number of events; N > 0 : some + * events are not same + */ +int CheckWorkspacesMatch::compareEventsListInDetails(const EventList& el1, const EventList& el2, + double tolTof, double tolWeight, int64_t tolPulse, + bool printdetails, + size_t& numdiffpulse, size_t& numdifftof, size_t& numdiffboth) const +{ + // Check + if (el1.getNumberEvents() != el2.getNumberEvents()) + throw std::runtime_error("compareEventsListInDetails only work on 2 event lists with same " + "number of events."); + + // Initialize + numdiffpulse = 0; + numdifftof = 0; + numdiffboth = 0; + + // Compar + int returnint = 0; + // Compare event by event including all events + const std::vector& events1 = el1.getEvents(); + const std::vector& events2 = el2.getEvents(); + + size_t numdiffweight = 0; + + EventType etype = el1.getEventType(); + + size_t numevents = events1.size(); + for (size_t i = 0; i < numevents; ++i) + { + // Compare 2 individual events + const TofEvent& e1 = events1[i]; + const TofEvent& e2 = events2[i]; + + bool diffpulse = false; + bool difftof = false; + if (std::abs(e1.pulseTime().totalNanoseconds() - e2.pulseTime().totalNanoseconds()) > tolPulse) + { + diffpulse = true; + ++ numdiffpulse; + } + if (fabs(e1.tof()- e2.tof()) > tolTof) + { + difftof = true; + ++ numdifftof; + } + if (diffpulse && difftof) + ++ numdiffboth; + + if (etype == WEIGHTED) + { + if (fabs(e1.weight() - e2.weight()) > tolWeight) + ++ numdiffweight; + } + + bool same = (!diffpulse) && (!difftof); + if (!same) + { + returnint += 1; + if (printdetails) + { + std::stringstream outss; + outss << "Spectrum ? Event " << i << ": "; + if (diffpulse) + outss << "Diff-Pulse: " << e1.pulseTime() << " vs. " << e2.pulseTime() << "; "; + if (difftof) + outss << "Diff-TOF: " << e1.tof() << " vs. " << e2.tof() << ";"; + + g_log.information(outss.str()); + } + } + } // End of loop on all events + + if (numdiffweight > 0) + { + throw std::runtime_error("Detected mismatched events in weight. Implement this branch ASAP."); + } + + // anything that gets this far is equal within tolerances + return returnint; +} + + void CheckWorkspacesMatch::doPeaksComparison(API::IPeaksWorkspace_sptr tws1, API::IPeaksWorkspace_sptr tws2) { // Check some table-based stuff diff --git a/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp b/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp index 482ada249387..205f8b62922d 100644 --- a/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ExtractMaskToTable.cpp @@ -392,6 +392,12 @@ namespace Algorithms g_log.debug() << "[DB] There is no previously masked detectors." << ".\n"; } + if ( numdetids == 0 ) + { + // I don't know what should be done here + throw std::runtime_error("Empty detector ID list"); + } + // Convert vector to string stringstream spectralist; detid_t previd = maskeddetids[0]; diff --git a/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp b/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp index 0fbed883b3e3..ec8c6f79656a 100644 --- a/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp +++ b/Code/Mantid/Framework/Algorithms/src/GetEi2.cpp @@ -103,6 +103,14 @@ void GetEi2::init() declareProperty("Tzero", 0.0, "", Direction::Output); + auto inRange0toOne = boost::make_shared >(); + inRange0toOne->setLower(0.0); + inRange0toOne->setUpper(1.0); + declareProperty("PeakSearchRange",0.1,inRange0toOne, + "Specifies the relative TOF range where the algorithm tries to find the monitor peak. Search occurs within PEAK_TOF_Guess*(1+-PeakSearchRange) ranges.\n" + "Defaults are almost always sufficient but decrease this value for very narrow peaks and increase for wide.",Direction::Input); + + } /** Executes the algorithm @@ -113,8 +121,10 @@ void GetEi2::init() */ void GetEi2::exec() { - m_input_ws = getProperty("InputWorkspace"); - m_fixedei = getProperty("FixEi"); + m_input_ws = getProperty("InputWorkspace"); + m_fixedei = getProperty("FixEi"); + m_tof_window= getProperty("PeakSearchRange"); + double initial_guess = getProperty("EnergyEstimate"); //check if incident energy guess is left empty, and try to find it as EnergyRequest parameter if (initial_guess==EMPTY_DBL()) @@ -162,7 +172,7 @@ double GetEi2::calculateEi(const double initial_guess) while ( formula.find("incidentEnergy") != std::string::npos ) { - // check if more than one 'value' in m_eq + // check if more than one 'value' in m_eq size_t found = formula.find("incidentEnergy"); formula.replace(found, 14, guess.str()); } @@ -239,13 +249,14 @@ double GetEi2::calculateEi(const double initial_guess) if(!m_fixedei) { - throw std::invalid_argument("No peak found for the monitor"+boost::lexical_cast(i+1)+ " (at "+ - boost::lexical_cast(det_distances[i])+" metres).\n"); + throw std::invalid_argument("No peak found for the monitor with spectra num: "+boost::lexical_cast(spec_nums[i])+ " (at "+ + boost::lexical_cast(det_distances[i])+" metres from source).\n"); } else { - peak_times[i] = 0.0; - g_log.information() << "No peak found for monitor " << (i+1) << " (at " << det_distances[i] << " metres). Setting peak time to zero\n"; + peak_times[i] = peak_guess; + g_log.warning() << "No peak found for monitor with spectra num " << spec_nums[i] << " (at " << det_distances[i] << " metres).\n"; + g_log.warning() << "Using guess time found from energy estimate of Peak = " << peak_times[i] << " microseconds\n"; } } if(i == 0) @@ -387,8 +398,13 @@ double GetEi2::calculatePeakWidthAtHalfHeight(API::MatrixWorkspace_sptr data_ws, const MantidVec & Es = data_ws->readE(0); MantidVec::const_iterator peakIt = std::max_element(Ys.begin(), Ys.end()); + double bkg_val = *std::min_element(Ys.begin(), Ys.end()); + if (*peakIt == bkg_val) + { + throw std::invalid_argument("No peak in the range specified as minimal and maximal values of the function are equal "); + } MantidVec::difference_type iPeak = peakIt - Ys.begin(); - double peakY = Ys[iPeak]; + double peakY = Ys[iPeak]-bkg_val; double peakE = Es[iPeak]; const std::vector::size_type nxvals = Xs.size(); @@ -397,7 +413,7 @@ double GetEi2::calculatePeakWidthAtHalfHeight(API::MatrixWorkspace_sptr data_ws, int64_t im = static_cast(iPeak-1); for( ; im >= 0; --im ) { - const double ratio = Ys[im]/peakY; + const double ratio = (Ys[im]-bkg_val)/peakY; const double ratio_err = std::sqrt( std::pow(Es[im],2) + std::pow(ratio*peakE,2) )/peakY; if ( ratio < (1.0/prominence - m_peak_signif*ratio_err) ) { @@ -408,7 +424,7 @@ double GetEi2::calculatePeakWidthAtHalfHeight(API::MatrixWorkspace_sptr data_ws, std::vector::size_type ip = iPeak+1; for( ; ip < nxvals; ip++ ) { - const double ratio = Ys[ip]/peakY; + const double ratio = (Ys[ip]-bkg_val)/peakY; const double ratio_err = std::sqrt( std::pow(Es[ip], 2) + std::pow(ratio*peakE, 2) )/peakY; if ( ratio < (1.0/prominence - m_peak_signif*ratio_err) ) diff --git a/Code/Mantid/Framework/Algorithms/test/ExtractMaskToTableTest.h b/Code/Mantid/Framework/Algorithms/test/ExtractMaskToTableTest.h index e3eaa7bc9db5..f40e1544c2bf 100644 --- a/Code/Mantid/Framework/Algorithms/test/ExtractMaskToTableTest.h +++ b/Code/Mantid/Framework/Algorithms/test/ExtractMaskToTableTest.h @@ -244,6 +244,22 @@ class ExtractMaskToTableTest : public CxxTest::TestSuite TS_ASSERT_DELTA(xxmax, 78910.5, 0.0001); TS_ASSERT_EQUALS(specstr, expectedspec2); + // Call algorithm second time with the same arguments + ExtractMaskToTable alg1; + alg1.initialize(); + + // Set up properties + alg1.setProperty("InputWorkspace", "TestWorkspace2"); + alg1.setProperty("MaskTableWorkspace", "MaskTable2"); + alg1.setProperty("OutputWorkspace", "MaskTable2"); + alg1.setProperty("XMin", 1234.0); + alg1.setProperty("XMax", 12345.6); + + // Execute + alg1.execute(); + // Returns not executed but doesn't crash + TS_ASSERT( !alg1.isExecuted() ); + // Clean AnalysisDataService::Instance().remove("TestWorkspace2"); AnalysisDataService::Instance().remove("MaskTable2"); diff --git a/Code/Mantid/Framework/Algorithms/test/GetEiTest.h b/Code/Mantid/Framework/Algorithms/test/GetEiTest.h index 5d5b8388c415..bdf8db9a7f16 100644 --- a/Code/Mantid/Framework/Algorithms/test/GetEiTest.h +++ b/Code/Mantid/Framework/Algorithms/test/GetEiTest.h @@ -172,7 +172,7 @@ class GetEiTest : public CxxTest::TestSuite AnalysisDataService::Instance().remove(outputName); } - void test_peak_time_is_zero_when_ei_fixed_and_no_peak_found() + void test_peak_time_is_guess_time_when_ei_fixed_and_no_peak_found() { const bool includePeaks(false); MatrixWorkspace_sptr testWS = createTestWorkspaceWithMonitors(includePeaks); @@ -185,7 +185,7 @@ class GetEiTest : public CxxTest::TestSuite if(alg) { const double firstMonPeak=alg->getProperty("FirstMonitorPeak"); - TS_ASSERT_DELTA(firstMonPeak, 0.0, 1e-12); + TS_ASSERT_DELTA(firstMonPeak, 6493.4402, 1e-4); } AnalysisDataService::Instance().remove(outputName); diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadHKL.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadHKL.h index 20a7f21c64e6..f15cc56e15fc 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadHKL.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadHKL.h @@ -13,7 +13,7 @@ namespace Mantid namespace Crystal { - /** LoadHKL : Load an ISAW-style .peaks file + /** LoadHKL : Load an ISAW-style .hkl file * into a PeaksWorkspace * * @author Vickie Lynch, SNS diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/NormaliseVanadium.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/NormaliseVanadium.h index add46ac61dba..af5e17b3bc72 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/NormaliseVanadium.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/NormaliseVanadium.h @@ -66,6 +66,8 @@ class DLLExport NormaliseVanadium : public API::Algorithm API::MatrixWorkspace_sptr m_inputWS; ///< A pointer to the input workspace protected: + /// Sets documentation strings for this algorithm + virtual void initDocs(); /// Initialisation code void init(); /// Execution code diff --git a/Code/Mantid/Framework/Crystal/src/LoadHKL.cpp b/Code/Mantid/Framework/Crystal/src/LoadHKL.cpp index 40c453f57653..09f838eeca0b 100644 --- a/Code/Mantid/Framework/Crystal/src/LoadHKL.cpp +++ b/Code/Mantid/Framework/Crystal/src/LoadHKL.cpp @@ -1,5 +1,35 @@ /*WIKI* +Loads an ASCII .hkl file to a PeaksWorkspace. +File has same format that works successfully in GSAS and SHELX from ISAW: + +hklFile.write('%4d%4d%4d%8.2f%8.2f%4d%8.4f%7.4f%7d%7d%7.4f%4d%9.5f%9.4f\n'% (H, K, L, FSQ, SIGFSQ, hstnum, WL, TBAR, CURHST, SEQNUM, TRANSMISSION, DN, TWOTH, DSP)) + +HKL is flipped by -1 due to different q convention in ISAW vs Mantid. + +FSQ = integrated intensity of peak (scaled) + +SIGFSQ = sigma from integrating peak + +hstnum = number of sample orientation (starting at 1) + +WL = wavelength of peak + +TBAR = output of absorption correction (-log(transmission)/mu) + +CURHST = run number of sample + +SEQNUM = peak number (unique number for each peak in file) + +TRANSMISSION = output of absorption correction (exp(-mu*tbar)) + +DN = detector bank number + +TWOTH = two-theta scattering angle + +DSP = d-Spacing of peak (Angstroms)/TR + +Last line must have all 0's *WIKI*/ #include "MantidAPI/FileProperty.h" @@ -50,8 +80,8 @@ namespace Crystal /// Sets documentation strings for this algorithm void LoadHKL::initDocs() { - this->setWikiSummary("Loads a ASCII .hkl file to a PeaksWorkspace."); - this->setOptionalMessage("Save a PeaksWorkspace to a ASCII .hkl file."); + this->setWikiSummary("Loads an ASCII .hkl file to a PeaksWorkspace."); + this->setOptionalMessage("Loads an ASCII .hkl file to a PeaksWorkspace."); } //---------------------------------------------------------------------------------------------- diff --git a/Code/Mantid/Framework/Crystal/src/NormaliseVanadium.cpp b/Code/Mantid/Framework/Crystal/src/NormaliseVanadium.cpp index 954eb78f248b..009cf757da53 100644 --- a/Code/Mantid/Framework/Crystal/src/NormaliseVanadium.cpp +++ b/Code/Mantid/Framework/Crystal/src/NormaliseVanadium.cpp @@ -1,5 +1,5 @@ /*WIKI* - +Normalises all spectra of workspace to a specified wavelength. Following A.J.Schultz's anvred, scales the vanadium spectra. *WIKI*/ //---------------------------------------------------------------------- @@ -35,6 +35,13 @@ using namespace DataObjects; NormaliseVanadium::NormaliseVanadium() : API::Algorithm() {} +/// Sets documentation strings for this algorithm +void NormaliseVanadium::initDocs() +{ + this->setWikiSummary("Normalises all spectra to a specified wavelength."); + this->setOptionalMessage("Normalises all spectra to a specified wavelength."); +} + void NormaliseVanadium::init() { // The input workspace must have an instrument and units of wavelength @@ -49,7 +56,7 @@ void NormaliseVanadium::init() auto mustBePositive = boost::make_shared >(); mustBePositive->setLower(0.0); declareProperty("Wavelength", 1.0, mustBePositive, - "Divide by vanadium at this wavelength"); + "Normalizes spectra to this wavelength"); } diff --git a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp index 6ae20492f691..3638e2381227 100644 --- a/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp +++ b/Code/Mantid/Framework/Crystal/src/OptimizeLatticeForCellType.cpp @@ -23,6 +23,7 @@ and keep the value in the sequence with the smallest relative change. #include "MantidGeometry/Crystal/OrientedLattice.h" #include "MantidGeometry/Crystal/IndexingUtils.h" #include "MantidGeometry/Instrument/RectangularDetector.h" +#include "MantidGeometry/Crystal/ReducedCell.h" #include #include #include @@ -73,15 +74,16 @@ namespace Mantid declareProperty(new WorkspaceProperty("PeaksWorkspace","",Direction::InOut), "An input PeaksWorkspace with an instrument."); std::vector cellTypes; - cellTypes.push_back("Cubic" ); - cellTypes.push_back("Tetragonal" ); - cellTypes.push_back("Orthorhombic"); - cellTypes.push_back("Hexagonal"); - cellTypes.push_back("Rhombohedral"); + cellTypes.push_back(ReducedCell::CUBIC() ); + cellTypes.push_back(ReducedCell::TETRAGONAL() ); + cellTypes.push_back(ReducedCell::ORTHORHOMBIC()); + cellTypes.push_back(ReducedCell::HEXAGONAL()); + cellTypes.push_back(ReducedCell::RHOMBOHEDRAL()); + cellTypes.push_back(ReducedCell::MONOCLINIC()); cellTypes.push_back("Monoclinic ( a unique )"); cellTypes.push_back("Monoclinic ( b unique )"); cellTypes.push_back("Monoclinic ( c unique )"); - cellTypes.push_back("Triclinic"); + cellTypes.push_back(ReducedCell::TRICLINIC()); declareProperty("CellType", cellTypes[0],boost::make_shared(cellTypes), "Select the cell type."); declareProperty( "Apply", false, "Re-index the peaks"); @@ -182,31 +184,31 @@ namespace Mantid } fit_alg->setPropertyValue("Function", fun_str.str()); - if (cell_type == "Cubic") + if (cell_type == ReducedCell::CUBIC()) { std::ostringstream tie_str; tie_str << "p1=p0,p2=p0,p3=90,p4=90,p5=90"; fit_alg->setProperty("Ties", tie_str.str()); } - else if (cell_type == "Tetragonal") + else if (cell_type == ReducedCell::TETRAGONAL()) { std::ostringstream tie_str; tie_str << "p1=p0,p3=90,p4=90,p5=90"; fit_alg->setProperty("Ties", tie_str.str()); } - else if (cell_type == "Orthorhombic") + else if (cell_type == ReducedCell::ORTHORHOMBIC()) { std::ostringstream tie_str; tie_str << "p3=90,p4=90,p5=90"; fit_alg->setProperty("Ties", tie_str.str()); } - else if (cell_type == "Rhombohedral") + else if (cell_type == ReducedCell::RHOMBOHEDRAL()) { std::ostringstream tie_str; tie_str << "p1=p0,p2=p0,p4=p3,p5=p3"; fit_alg->setProperty("Ties", tie_str.str()); } - else if (cell_type == "Hexagonal") + else if (cell_type == ReducedCell::HEXAGONAL()) { std::ostringstream tie_str; tie_str << "p1=p0,p3=90,p4=90,p5=120"; @@ -218,7 +220,7 @@ namespace Mantid tie_str << "p4=90,p5=90"; fit_alg->setProperty("Ties", tie_str.str()); } - else if (cell_type == "Monoclinic ( b unique )") + else if (cell_type == ReducedCell::MONOCLINIC() || cell_type == "Monoclinic ( b unique )") { std::ostringstream tie_str; tie_str << "p3=90,p5=90"; @@ -258,23 +260,23 @@ namespace Mantid OrientedLattice o_lattice; o_lattice.setUB( UBnew ); - if (cell_type == "Cubic") + if (cell_type == ReducedCell::CUBIC()) { o_lattice.setError(sigabc[0],sigabc[0],sigabc[0],0,0,0); } - else if (cell_type == "Tetragonal") + else if (cell_type == ReducedCell::TETRAGONAL()) { o_lattice.setError(sigabc[0],sigabc[0],sigabc[1],0,0,0); } - else if (cell_type == "Orthorhombic") + else if (cell_type == ReducedCell::ORTHORHOMBIC()) { o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],0,0,0); } - else if (cell_type == "Rhombohedral") + else if (cell_type == ReducedCell::RHOMBOHEDRAL()) { o_lattice.setError(sigabc[0],sigabc[0],sigabc[0],sigabc[1],sigabc[1],sigabc[1]); } - else if (cell_type == "Hexagonal") + else if (cell_type == ReducedCell::HEXAGONAL()) { o_lattice.setError(sigabc[0],sigabc[0],sigabc[1],0,0,0); } @@ -282,7 +284,7 @@ namespace Mantid { o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],sigabc[3],0,0); } - else if (cell_type == "Monoclinic ( b unique )") + else if (cell_type == ReducedCell::MONOCLINIC() || cell_type == "Monoclinic ( b unique )") { o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],0,sigabc[3],0); @@ -291,7 +293,7 @@ namespace Mantid { o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],0,0,sigabc[3]); } - else if (cell_type == "Triclinic") + else if (cell_type == ReducedCell::TRICLINIC()) { o_lattice.setError(sigabc[0],sigabc[1],sigabc[2],sigabc[3],sigabc[4],sigabc[5]); } @@ -338,7 +340,7 @@ namespace Mantid { std::vector lattice_parameters; lattice_parameters.assign (6,0); - if (cell_type == "Cubic") + if (cell_type == ReducedCell::CUBIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; @@ -348,7 +350,7 @@ namespace Mantid lattice_parameters[4] = 90; lattice_parameters[5] = 90; } - else if (cell_type == "Tetragonal") + else if (cell_type == ReducedCell::TETRAGONAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; @@ -358,7 +360,7 @@ namespace Mantid lattice_parameters[4] = 90; lattice_parameters[5] = 90; } - else if (cell_type == "Orthorhombic") + else if (cell_type == ReducedCell::ORTHORHOMBIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; @@ -368,7 +370,7 @@ namespace Mantid lattice_parameters[4] = 90; lattice_parameters[5] = 90; } - else if (cell_type == "Rhombohedral") + else if (cell_type == ReducedCell::RHOMBOHEDRAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; @@ -378,7 +380,7 @@ namespace Mantid lattice_parameters[4] = params[1]; lattice_parameters[5] = params[1]; } - else if (cell_type == "Hexagonal") + else if (cell_type == ReducedCell::HEXAGONAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; @@ -398,7 +400,7 @@ namespace Mantid lattice_parameters[4] = 90; lattice_parameters[5] = 90; } - else if (cell_type == "Monoclinic ( b unique )") + else if (cell_type == ReducedCell::MONOCLINIC() || cell_type == "Monoclinic ( b unique )") { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; @@ -418,7 +420,7 @@ namespace Mantid lattice_parameters[4] = 90; lattice_parameters[5] = params[3]; } - else if (cell_type == "Triclinic") + else if (cell_type == ReducedCell::TRICLINIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; @@ -617,7 +619,8 @@ namespace Mantid { x.push_back(Params[1]); x.push_back(Params[2]); - if(cell_type.compare(13,1,"a")==0)x.push_back( Params[3]); + if(cell_type.length() < 13)x.push_back(Params[4]); //default is b + else if(cell_type.compare(13,1,"a")==0)x.push_back( Params[3]); else if(cell_type.compare(13,1,"b")==0)x.push_back(Params[4]); else if(cell_type.compare(13,1,"c")==0)x.push_back(Params[5]); } diff --git a/Code/Mantid/Framework/CurveFitting/src/PlotPeakByLogValue.cpp b/Code/Mantid/Framework/CurveFitting/src/PlotPeakByLogValue.cpp index 05b17fd5f034..e8cde7b01513 100644 --- a/Code/Mantid/Framework/CurveFitting/src/PlotPeakByLogValue.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/PlotPeakByLogValue.cpp @@ -117,6 +117,13 @@ namespace Mantid "Cost functions to use for fitting. Cost functions available are 'Least squares' and 'Ignore positive peaks'", Direction::InOut); declareProperty("CreateOutput", false, "Set to true to create output workspaces with the results of the fit(default is false)."); + + declareProperty("OutputCompositeMembers",false, + "If true and CreateOutput is true then the value of each member of a Composite Function is also output."); + + declareProperty(new Kernel::PropertyWithValue("ConvolveMembers", false), + "If true and OutputCompositeMembers is true members of any Convolution are output convolved\n" + "with corresponding resolution"); } /** @@ -134,6 +141,8 @@ namespace Mantid bool individual = getPropertyValue("FitType") == "Individual"; bool passWSIndexToFunction = getProperty("PassWSIndexToFunction"); bool createFitOutput = getProperty("CreateOutput"); + bool outputCompositeMembers = getProperty("OutputCompositeMembers"); + bool outputConvolvedMembers = getProperty("ConvolveMembers"); std::string baseName = getPropertyValue("OutputWorkspace"); bool isDataName = false; // if true first output column is of type string and is the data source name @@ -271,6 +280,8 @@ namespace Mantid fit->setPropertyValue("CostFunction",getPropertyValue("CostFunction")); fit->setProperty("CalcErrors",true); fit->setProperty("CreateOutput",createFitOutput); + fit->setProperty("OutputCompositeMembers", outputCompositeMembers); + fit->setProperty("ConvolveMembers",outputConvolvedMembers); fit->setProperty("Output", wsBaseName); fit->execute(); diff --git a/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp b/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp index c01518d766ab..e48303a46d91 100644 --- a/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp @@ -136,6 +136,11 @@ void TabulatedFunction::setAttribute(const std::string& attName,const IFunction: if (attName == "FileName") { std::string fileName = value.asUnquotedString(); + if ( fileName.empty() ) + { + storeAttributeValue( "FileName", Attribute("",true)); + return; + } FileValidator fval; std::string error = fval.isValid(fileName); if (error == "") @@ -152,9 +157,13 @@ void TabulatedFunction::setAttribute(const std::string& attName,const IFunction: } else if (attName == "Workspace") { - storeAttributeValue( attName, value ); - storeAttributeValue( "FileName", Attribute("",true)); - loadWorkspace( value.asString() ); + std::string wsName = value.asString(); + if ( !wsName.empty() ) + { + storeAttributeValue( attName, value ); + storeAttributeValue( "FileName", Attribute("",true)); + loadWorkspace( wsName ); + } } else { diff --git a/Code/Mantid/Framework/CurveFitting/test/PlotPeakByLogValueTest.h b/Code/Mantid/Framework/CurveFitting/test/PlotPeakByLogValueTest.h index a4b8a125c487..b194f691b945 100644 --- a/Code/Mantid/Framework/CurveFitting/test/PlotPeakByLogValueTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/PlotPeakByLogValueTest.h @@ -15,6 +15,7 @@ #include "MantidAPI/FunctionFactory.h" #include "MantidAPI/WorkspaceGroup.h" #include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/UnitFactory.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" #include @@ -389,6 +390,53 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite TS_ASSERT( fits->getNames().size() == 3 ); } + + void test_createOutputWithExtraOutputOptions() + { + auto ws = createTestWorkspace(); + AnalysisDataService::Instance().add( "PLOTPEAKBYLOGVALUETEST_WS", ws ); + PlotPeakByLogValue alg; + alg.initialize(); + alg.setPropertyValue("Input","PLOTPEAKBYLOGVALUETEST_WS,v0:2"); + alg.setPropertyValue("OutputWorkspace","PlotPeakResult"); + alg.setProperty("PassWSIndexToFunction",true); + alg.setProperty("CreateOutput", true); + alg.setProperty("OutputCompositeMembers", true); + alg.setProperty("ConvolveMembers", true); + alg.setPropertyValue("Function","name=LinearBackground,A0=0,A1=0;" + "(composite=Convolution,FixResolution=true,NumDeriv=true;" + "name=Resolution,Workspace=PLOTPEAKBYLOGVALUETEST_WS,WorkspaceIndex=0;" + "name=Gaussian,Height=3000,PeakCentre=6493,Sigma=50;);"); + alg.execute(); + + TS_ASSERT( alg.isExecuted() ); + + TWS_type result = WorkspaceCreationHelper::getWS("PlotPeakResult"); + TS_ASSERT( result ); + + auto matrices = AnalysisDataService::Instance().retrieveWS("PlotPeakResult_NormalisedCovarianceMatrices"); + auto params = AnalysisDataService::Instance().retrieveWS("PlotPeakResult_Parameters"); + auto fits = AnalysisDataService::Instance().retrieveWS("PlotPeakResult_Workspaces"); + + TS_ASSERT( matrices ); + TS_ASSERT( params ); + TS_ASSERT( fits ); + + TS_ASSERT( matrices->getNames().size() == 2 ); + TS_ASSERT( params->getNames().size() == 2 ); + TS_ASSERT( fits->getNames().size() == 2 ); + + auto wsNames = fits->getNames(); + for (size_t i=0; i< wsNames.size(); ++i) + { + auto fit = AnalysisDataService::Instance().retrieveWS(wsNames[i]); + TS_ASSERT( fit ); + TS_ASSERT( fit->getNumberHistograms() == 5); + } + + AnalysisDataService::Instance().clear(); + } + private: WorkspaceGroup_sptr m_wsg; @@ -415,6 +463,36 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite } } + MatrixWorkspace_sptr createTestWorkspace() + { + const int numHists(2); + const int numBins(2000); + MatrixWorkspace_sptr testWS = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(numHists, numBins, true); + testWS->getAxis(0)->unit() = Mantid::Kernel::UnitFactory::Instance().create("TOF"); + MantidVecPtr xdata; + xdata.access().resize(numBins+1); + // Update X data to a sensible values. Looks roughly like the MARI binning + // Update the Y values. We don't care about errors here + + // We'll simply use a gaussian as a test + const double peakOneCentre(6493.0), sigmaSqOne(250*250.), peakTwoCentre(10625.), sigmaSqTwo(50*50); + const double peakOneHeight(3000.), peakTwoHeight(1000.); + for( int i = 0; i <= numBins; ++i) + { + const double xValue = 5.0 + 5.5*i; + if( i < numBins ) + { + testWS->dataY(0)[i] = peakOneHeight * exp(-0.5*pow(xValue - peakOneCentre, 2.)/sigmaSqOne); + testWS->dataY(1)[i] = peakTwoHeight * exp(-0.5*pow(xValue - peakTwoCentre, 2.)/sigmaSqTwo); + + } + xdata.access()[i] = xValue; + } + testWS->setX(0, xdata); + testWS->setX(1, xdata); + return testWS; + } + void deleteData() { FrameworkManager::Instance().deleteWorkspace(m_wsg->getName()); diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index b8cd20a8dbaf..4fffc9832d78 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -99,6 +99,7 @@ set ( SRC_FILES src/SNSDataArchive.cpp src/SNSDataArchiveICAT2.cpp src/SaveAscii.cpp + src/SaveANSTOAscii.cpp src/SaveAscii2.cpp src/SaveCSV.cpp src/SaveCalFile.cpp @@ -223,6 +224,7 @@ set ( INC_FILES inc/MantidDataHandling/RotateInstrumentComponent.h inc/MantidDataHandling/SNSDataArchive.h inc/MantidDataHandling/SNSDataArchiveICAT2.h + inc/MantidDataHandling/SaveANSTOAscii.h inc/MantidDataHandling/SaveAscii.h inc/MantidDataHandling/SaveAscii2.h inc/MantidDataHandling/SaveCSV.h @@ -345,6 +347,7 @@ set ( TEST_FILES RotateInstrumentComponentTest.h SNSDataArchiveICAT2Test.h SNSDataArchiveTest.h + SaveANSTOAsciiTest.h SaveAscii2Test.h SaveAsciiTest.h SaveCSVTest.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadDetectorsGroupingFile.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadDetectorsGroupingFile.h index 86b7752264c7..a8a5ba52c891 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadDetectorsGroupingFile.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadDetectorsGroupingFile.h @@ -7,6 +7,12 @@ #include +namespace Poco { namespace XML { + class Document; + class Element; + class Node; +}} + namespace Mantid { namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h index 397152c669d0..c7c4fc2a8b04 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFullprofResolution.h @@ -5,6 +5,11 @@ #include "MantidAPI/Algorithm.h" #include "MantidDataObjects/TableWorkspace.h" +namespace Poco { namespace XML { + class Document; + class Element; +}} + namespace Mantid { namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h index d0649d402d17..19fba7fcc9a1 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h @@ -11,7 +11,7 @@ namespace Mantid namespace DataHandling { - /** LoadLLB : TODO: DESCRIPTION + /** LoadLLB : Loads an LLB MIBEMOL TOF NeXus file into a Workspace2D with the given name. Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMask.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMask.h index e0b862bff306..2409ec79ef68 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMask.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMask.h @@ -6,6 +6,10 @@ #include "MantidAPI/MatrixWorkspace.h" #include "MantidDataObjects/MaskWorkspace.h" +namespace Poco { namespace XML { + class Document; + class Element; +}} namespace Mantid { diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveANSTOAscii.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveANSTOAscii.h new file mode 100644 index 000000000000..0a6cebe4c705 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveANSTOAscii.h @@ -0,0 +1,49 @@ +#ifndef MANTID_DATAHANDLING_SAVEANSTOASCII_H_ +#define MANTID_DATAHANDLING_SAVEANSTOASCII_H_ + +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidAPI/Algorithm.h" + +namespace Mantid +{ + namespace DataHandling + { + class DLLExport SaveANSTOAscii : public API::Algorithm + { + public: + /// Default constructor + SaveANSTOAscii(); + /// Destructor + ~SaveANSTOAscii() {} + /// Algorithm's name for identification overriding a virtual method + virtual const std::string name() const { return "SaveANSTOAscii"; } + /// Algorithm's version for identification overriding a virtual method + virtual int version() const { return 1; } + /// Algorithm's category for identification overriding a virtual method + virtual const std::string category() const { return "DataHandling\\Text"; } + + private: + /// Sets documentation strings for this algorithm + virtual void initDocs(); + /// Overwrites Algorithm method. + void init(); + /// Overwrites Algorithm method + void exec(); + /// returns true if the value is NaN + bool checkIfNan(const double& value) const; + /// returns true if the value if + or - infinity + bool checkIfInfinite(const double& value) const; + /// print the appropriate value to file + void outputval (double val, std::ofstream & file, bool leadingSep = true); + ///static reference to the logger class + static Kernel::Logger& g_log; + char m_sep; + API::MatrixWorkspace_const_sptr m_ws; + }; + + } // namespace DataHandling +} // namespace Mantid + +#endif /* MANTID_DATAHANDLING_SAVEANSTO_H_ */ diff --git a/Code/Mantid/Framework/DataHandling/src/Load.cpp b/Code/Mantid/Framework/DataHandling/src/Load.cpp index 1c7fe2098e89..da2106b76c42 100644 --- a/Code/Mantid/Framework/DataHandling/src/Load.cpp +++ b/Code/Mantid/Framework/DataHandling/src/Load.cpp @@ -553,8 +553,9 @@ namespace Mantid const std::vector< Property*> &props = loader->getProperties(); for (unsigned int i = 0; i < props.size(); ++i) { - if (props[i]->direction() == Direction::Output && - dynamic_cast(props[i]) ) + auto wsProp = dynamic_cast(props[i]); + + if (wsProp && !wsProp->isOptional() && props[i]->direction() == Direction::Output ) { if ( props[i]->value().empty() ) props[i]->setValue("LoadChildWorkspace"); } diff --git a/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp b/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp index 06b5a419fa3f..a45aaaecf9a7 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp @@ -1,6 +1,12 @@ /*WIKI* - TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page. - *WIKI*/ + +Loads an LLB MIBEMOL TOF NeXus file into a [[Workspace2D]] with the given name. + +This loader calculates the elastic peak position (EPP) on the fly. + +To date this algorithm only supports the MIBEMOL instrument. + +*WIKI*/ #include "MantidDataHandling/LoadLLB.h" #include "MantidAPI/FileProperty.h" diff --git a/Code/Mantid/Framework/DataHandling/src/SaveANSTOAscii.cpp b/Code/Mantid/Framework/DataHandling/src/SaveANSTOAscii.cpp new file mode 100644 index 000000000000..f22afbe4111a --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/src/SaveANSTOAscii.cpp @@ -0,0 +1,159 @@ +/*WIKI* +SaveANSTOAscii is an export-only Acii-based save format with no associated loader. It is based on a python script by Maximilian Skoda, written for the ISIS Reflectometry GUI +==== Limitations ==== +While Files saved with SaveANSTOAscii can be loaded back into mantid using LoadAscii, the resulting workspaces won't be usful as the data written by SaveANSTOAscii is not in the normal X,Y,E,DX format. +*WIKI*/ +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidDataHandling/SaveANSTOAscii.h" +#include "MantidKernel/UnitFactory.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidAPI/FileProperty.h" +#include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/VisibleWhenProperty.h" +#include "MantidKernel/ListValidator.h" +#include +#include +#include +#include +#include + +namespace Mantid +{ + namespace DataHandling + { + // Register the algorithm into the algorithm factory + DECLARE_ALGORITHM(SaveANSTOAscii) + + /// Sets documentation strings for this algorithm + void SaveANSTOAscii::initDocs() + { + this->setWikiSummary("Saves a 2D [[workspace]] to a comma separated ascii file. "); + this->setOptionalMessage("Saves a 2D workspace to a ascii file."); + } + + using namespace Kernel; + using namespace API; + + // Initialise the logger + Logger& SaveANSTOAscii::g_log = Logger::get("SaveANSTOAscii"); + + /// Empty constructor + SaveANSTOAscii::SaveANSTOAscii() + { + } + + /// Initialisation method. + void SaveANSTOAscii::init() + { + declareProperty(new WorkspaceProperty<>("InputWorkspace", + "",Direction::Input), "The name of the workspace containing the data you want to save to a ANSTO file."); + + std::vector exts; + exts.push_back(".txt"); + declareProperty(new FileProperty("Filename", "", FileProperty::Save, exts), + "The filename of the output ANSTO file."); + m_sep = '\t'; + } + + /** + * Executes the algorithm. + */ + void SaveANSTOAscii::exec() + { + std::string filename = getProperty("Filename"); + std::ofstream file(filename.c_str()); + if (!file) + { + g_log.error("Unable to create file: " + filename); + throw Exception::FileError("Unable to create file: " , filename); + } + m_ws = getProperty("InputWorkspace"); + g_log.information("FILENAME: " + filename); + auto title ='#'+ m_ws->getTitle(); + const std::vector & xTemp = m_ws->readX(0); + const size_t xlength = xTemp.size() - 1; + std::vector XData(xlength, 0); + for (size_t i = 0; i < xlength; ++i) + { + XData[i]=(xTemp[i]+xTemp[i+1])/2.0; + } + const std::vector & yData = m_ws->readY(0); + const std::vector & eData = m_ws->readE(0); + double qres = (XData[1]-XData[0])/XData[1]; + g_log.information("Constant dq/q from file: " + boost::lexical_cast(qres)); + file << std::scientific; + for (size_t i = 0; i < xlength; ++i) + { + double dq = XData[i]*qres; + outputval(XData[i], file, false); + outputval(yData[i], file); + outputval(eData[i], file); + outputval(dq, file); + file << std::endl; + } + file.close(); + } + + void SaveANSTOAscii::outputval (double val, std::ofstream & file, bool leadingSep) + { + bool nancheck = checkIfNan(val); + bool infcheck = checkIfInfinite(val); + if (leadingSep) + { + if (!nancheck && !infcheck) + { + file << m_sep << val; + } + else if (nancheck) + { + //not a number - output nan + file << m_sep << "nan"; + } + else if (infcheck) + { + //infinite - output 'inf' + file << m_sep << "inf"; + } + else + { + //not valid, nan or inf - so output 'und' + file << m_sep << "und"; + } + } + else + { + if (!nancheck && !infcheck) + { + file << val; + } + else if (nancheck) + { + //not a number - output nan + file << "nan"; + } + else if (infcheck) + { + //infinite - output 'inf' + file << "inf"; + } + else + { + //not valid, nan or inf - so output 'und' + file << "und"; + } + } + } + + bool SaveANSTOAscii::checkIfNan(const double& value) const + { + return (boost::math::isnan(value)); + } + + bool SaveANSTOAscii::checkIfInfinite(const double& value) const + { + return (std::abs(value) == std::numeric_limits::infinity()); + } + } // namespace DataHandling +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp b/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp index 78e91303869f..e2653648f78e 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveNXSPE.cpp @@ -38,8 +38,6 @@ namespace Mantid using namespace Kernel; using namespace API; - //const double SaveNXSPE::MASK_FLAG = -1e30; - // const double SaveNXSPE::MASK_FLAG = std::numeric_limits::quiet_NaN(); const double SaveNXSPE::MASK_ERROR = 0.0; // works fine but there were cases that some compilers crush on this (VS2008 in mixed .net environment ?) @@ -60,8 +58,7 @@ namespace Mantid /** * Initialise the algorithm */ - void - SaveNXSPE::init() + void SaveNXSPE::init() { auto wsValidator = boost::make_shared() ; wsValidator->add(boost::make_shared("DeltaE")); @@ -72,53 +69,37 @@ namespace Mantid "", Direction::Input, wsValidator), "The name of the workspace to save."); - std::vector < std::string > exts; - exts.push_back(".nxspe"); - - declareProperty(new API::FileProperty("Filename", "", FileProperty::Save, - exts), + declareProperty(new API::FileProperty("Filename", "", FileProperty::Save, std::vector(1,".nxspe")), "The name of the NXSPE file to write, as a full or relative path"); - // if the value is not set, one should better have it invalid, e.g. NaN - declareProperty("Efixed",SaveNXSPE::MASK_FLAG, - "Value of the fixed energy to write into NXSPE file."); - - declareProperty("Psi", SaveNXSPE::MASK_FLAG, boost::make_shared(), - "Value of PSI to write into NXSPE file."); - - declareProperty("KiOverKfScaling", true, - "Flags in the file whether Ki/Kf scaling has been done or not."); + declareProperty("Efixed", EMPTY_DBL(), "Value of the fixed energy to write into NXSPE file."); + declareProperty("Psi", EMPTY_DBL(), "Value of PSI to write into NXSPE file."); + declareProperty("KiOverKfScaling", true, "Flags in the file whether Ki/Kf scaling has been done or not."); // optional par or phx file - std::vector fileExts(2); - fileExts[0]=".par"; - fileExts[1]=".phx"; - declareProperty(new FileProperty("ParFile","not_used.par",FileProperty::OptionalLoad, fileExts), - "If provided, will replace detectors parameters in resulting nxspe file with the values taken from the file. \n\ - Should be used only if the parameters, calculated by the [[FindDetectorsPar]] algorithm are not suitable for some reason. \n\ - See [[FindDetectorsPar]] description for the details."); + std::vector fileExts(2); + fileExts[0]=".par"; + fileExts[1]=".phx"; + declareProperty(new FileProperty("ParFile","not_used.par",FileProperty::OptionalLoad, fileExts), + "If provided, will replace detectors parameters in resulting nxspe file with the values taken from the file. \n\ + Should be used only if the parameters, calculated by the [[FindDetectorsPar]] algorithm are not suitable for some reason. \n\ + See [[FindDetectorsPar]] description for the details."); } /** * Execute the algorithm */ - void - SaveNXSPE::exec() + void SaveNXSPE::exec() { - using namespace Mantid::API; - - double efixed = 0.0; - // Retrieve the input workspace const MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); // Do the full check for common binning if (!WorkspaceHelpers::commonBoundaries(inputWS)) - { - g_log.error("The input workspace must have common bins"); - throw std::invalid_argument( - "The input workspace must have common bins"); - } + { + g_log.error("The input workspace must have common bins"); + throw std::invalid_argument("The input workspace must have common bins"); + } // Number of spectra const int nHist = static_cast(inputWS->getNumberHistograms()); @@ -126,8 +107,7 @@ namespace Mantid this->nBins = inputWS->blocksize(); // Get a pointer to the sample - Geometry::IObjComponent_const_sptr sample = - inputWS->getInstrument()->getSample(); + Geometry::IObjComponent_const_sptr sample = inputWS->getInstrument()->getSample(); // Retrieve the filename from the properties this->filename = getPropertyValue("Filename"); @@ -154,38 +134,37 @@ namespace Mantid nxFile.makeGroup("NXSPE_info", "NXcollection", true); // Get the value out of the property first - efixed = getProperty("Efixed"); + double efixed = getProperty("Efixed"); + if ( isEmpty(efixed) ) efixed = MASK_FLAG; // Now lets check to see if the workspace nows better. // TODO: Check that this is the way round we want to do it. const API::Run & run = inputWS->run(); if (run.hasProperty("Ei")) - { - Kernel::Property* propEi = run.getProperty("Ei"); - efixed = boost::lexical_cast(propEi->value()); - } + { + Kernel::Property* propEi = run.getProperty("Ei"); + efixed = boost::lexical_cast(propEi->value()); + } nxFile.writeData("fixed_energy", efixed); nxFile.openData("fixed_energy"); nxFile.putAttr("units", "meV"); nxFile.closeData(); double psi = getProperty("Psi"); - if (psi != EMPTY_DBL()) - { - nxFile.writeData("psi", psi); - nxFile.openData("psi"); - nxFile.putAttr("units", "degrees"); - nxFile.closeData(); - } + if ( isEmpty(psi) ) psi = MASK_FLAG; + nxFile.writeData("psi", psi); + nxFile.openData("psi"); + nxFile.putAttr("units", "degrees"); + nxFile.closeData(); bool kikfScaling = getProperty("KiOverKfScaling"); if (kikfScaling) - { - nxFile.writeData("ki_over_kf_scaling", 1); - } + { + nxFile.writeData("ki_over_kf_scaling", 1); + } else - { - nxFile.writeData("ki_over_kf_scaling", 0); - } + { + nxFile.writeData("ki_over_kf_scaling", 0); + } nxFile.closeGroup(); // NXSPE_info @@ -260,70 +239,70 @@ namespace Mantid // Create a progress reporting object Progress progress(this,0,1,100); const int progStep = (int)(ceil(nHist/100.0)); - Geometry::IDetector_const_sptr det; + Geometry::IDetector_const_sptr det; // Loop over spectra for (int i = 0; i < nHist; i++) - { - try{ // detector exist - det =inputWS->getDetector(i); - // Check that we aren't writing a monitor... - if (!det->isMonitor()) - { - Geometry::IDetector_const_sptr det = inputWS->getDetector(i); - - if (!det->isMasked()) - { - // no masking... - // Open the data - nxFile.openData("data"); - slab_start[0] = i; - nxFile.putSlab(const_cast (inputWS->readY(i)), - slab_start, slab_size); - // Close the data - nxFile.closeData(); - - // Open the error - nxFile.openData("error"); - //MantidVec& tmparr = const_cast(inputWS->dataE(i)); - //nxFile.putSlab((void*)(&(tmparr[0])), slab_start, slab_size); - nxFile.putSlab(const_cast (inputWS->readE(i)), - slab_start, slab_size); - // Close the error - nxFile.closeData(); - } - else - { - // Write a masked value... - // Open the data - nxFile.openData("data"); - slab_start[0] = i; - nxFile.putSlab(masked_data, slab_start, slab_size); - // Close the data - nxFile.closeData(); - - // Open the error - nxFile.openData("error"); - nxFile.putSlab(masked_error, slab_start, slab_size); - // Close the error - nxFile.closeData(); - } - } - }catch(Exception::NotFoundError&) + { + try{ // detector exist + det =inputWS->getDetector(i); + // Check that we aren't writing a monitor... + if (!det->isMonitor()) + { + Geometry::IDetector_const_sptr det = inputWS->getDetector(i); + + if (!det->isMasked()) { - // Catch if no detector. Next line tests whether this happened - test placed - // outside here because Mac Intel compiler doesn't like 'continue' in a catch - // in an openmp block. + // no masking... + // Open the data + nxFile.openData("data"); + slab_start[0] = i; + nxFile.putSlab(const_cast (inputWS->readY(i)), + slab_start, slab_size); + // Close the data + nxFile.closeData(); + + // Open the error + nxFile.openData("error"); + //MantidVec& tmparr = const_cast(inputWS->dataE(i)); + //nxFile.putSlab((void*)(&(tmparr[0])), slab_start, slab_size); + nxFile.putSlab(const_cast (inputWS->readE(i)), + slab_start, slab_size); + // Close the error + nxFile.closeData(); + } + else + { + // Write a masked value... + // Open the data + nxFile.openData("data"); + slab_start[0] = i; + nxFile.putSlab(masked_data, slab_start, slab_size); + // Close the data + nxFile.closeData(); + + // Open the error + nxFile.openData("error"); + nxFile.putSlab(masked_error, slab_start, slab_size); + // Close the error + nxFile.closeData(); } - // If no detector found, skip onto the next spectrum - if ( !det ) continue; - - // make regular progress reports and check for canceling the algorithm - if ( i % progStep == 0 ) - { - progress.report(); } + }catch(Exception::NotFoundError&) + { + // Catch if no detector. Next line tests whether this happened - test placed + // outside here because Mac Intel compiler doesn't like 'continue' in a catch + // in an openmp block. } - // execute the ChildAlgorithm to calculate the detector's parameters; + // If no detector found, skip onto the next spectrum + if ( !det ) continue; + + // make regular progress reports and check for canceling the algorithm + if ( i % progStep == 0 ) + { + progress.report(); + } + } + // execute the ChildAlgorithm to calculate the detector's parameters; IAlgorithm_sptr spCalcDetPar = this->createChildAlgorithm("FindDetectorsPar", 0, 1, true, 1); spCalcDetPar->initialize(); diff --git a/Code/Mantid/Framework/DataHandling/test/LoadTest.h b/Code/Mantid/Framework/DataHandling/test/LoadTest.h index 75298d3bd32d..e0d7a66c547d 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadTest.h @@ -548,6 +548,38 @@ class LoadTest : public CxxTest::TestSuite TS_ASSERT(wsg); TS_ASSERT_EQUALS(wsg->getNames().size(), 2); } + + void test_additionalOutputWorkspaces_mandatory() + { + // TODO: This is supposed to be a test for load algorithm with additional _mandatory_ output + // workspace properties, which should be set to something by Load so the concrete algorithm + // can actually be run. At the present moment, I wasn't able to find any algorithms with + // such properties, so please feel free to write this one when it becomes possible. + } + + void test_additionalOutputWorkspaces_optional_notRequested() + { + Load loader; + loader.initialize(); + loader.setPropertyValue("Filename", "MUSR15189"); + loader.setPropertyValue("OutputWorkspace", "LoadTest_Output"); + TS_ASSERT_THROWS_NOTHING(loader.execute()); + + TS_ASSERT_EQUALS(3, AnalysisDataService::Instance().size()); + } + + void test_additionalOutputWorskpaces_optional_requested() + { + Load loader; + loader.initialize(); + loader.setPropertyValue("Filename", "MUSR15189"); + loader.setPropertyValue("OutputWorkspace", "LoadTest_Output"); + loader.setPropertyValue("DetectorGroupingTable", "LoadTest_DetectorGrouping"); + loader.setPropertyValue("DeadTimeTable", "LoadTest_DeadTimeTable"); + TS_ASSERT_THROWS_NOTHING(loader.execute()); + + TS_ASSERT_EQUALS(9, AnalysisDataService::Instance().size()); + } }; diff --git a/Code/Mantid/Framework/DataHandling/test/SaveANSTOAsciiTest.h b/Code/Mantid/Framework/DataHandling/test/SaveANSTOAsciiTest.h new file mode 100644 index 000000000000..a99f99dee7a8 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/test/SaveANSTOAsciiTest.h @@ -0,0 +1,224 @@ +#ifndef SAVEANSTOASCIITEST_H_ +#define SAVEANSTOASCIITEST_H_ + +#include +#include "MantidDataHandling/SaveANSTOAscii.h" +#include "MantidDataObjects/Workspace2D.h" +#include "MantidAPI/AlgorithmManager.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include +#include +#include + +using namespace Mantid::API; +using namespace Mantid::DataHandling; +using namespace Mantid::DataObjects; + +class SaveANSTOAsciiTest : public CxxTest::TestSuite +{ + +public: + + static SaveANSTOAsciiTest *createSuite() { return new SaveANSTOAsciiTest(); } + static void destroySuite(SaveANSTOAsciiTest *suite) { delete suite; } + + SaveANSTOAsciiTest() + { + m_filename = "SaveANSTOAsciiTestFile.txt"; + m_name = "SaveANSTOAsciiWS"; + for (int i = 1; i < 11; ++i) + { + //X, Y and E get [1,2,3,4,5,6,7,8,9,10] + //0 gets [0,0,0,0,0,0,0,0,0,0] and is used to make sure there is no problem with divide by zero + m_dataX.push_back(i); + m_dataY.push_back(i); + m_dataE.push_back(i); + m_data0.push_back(0); + } + } + ~SaveANSTOAsciiTest() + { + } + + void testExec() + { + //create a new workspace and then delete it later on + createWS(); + + Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveANSTOAscii"); + alg->setPropertyValue("InputWorkspace", m_name); + alg->setPropertyValue("Filename", m_filename); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + + if ( ! alg->isExecuted() ) + { + TS_FAIL("Could not run SaveANSTOAscii"); + } + m_long_filename= alg->getPropertyValue("Filename"); + // has the algorithm written a file to disk? + TS_ASSERT( Poco::File(m_long_filename).exists() ); + std::ifstream in(m_long_filename.c_str()); + std::string fullline; + getline(in,fullline); + std::vector columns; + boost::split(columns, fullline, boost::is_any_of("\t"), boost::token_compress_on); + TS_ASSERT_EQUALS(columns.size(),4); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(0)), 1.5, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(1)), 1, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(2)), 1, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(3)), 0.6, 0.01); + in.close(); + + cleanupafterwards(); + } + void testNoX() + { + //create a new workspace and then delete it later on + createWS(true); + + Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveANSTOAscii"); + alg->setPropertyValue("InputWorkspace", m_name); + alg->setPropertyValue("Filename", m_filename); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + + if ( ! alg->isExecuted() ) + { + TS_FAIL("Could not run SaveANSTOAscii"); + } + m_long_filename= alg->getPropertyValue("Filename"); + // has the algorithm written a file to disk? + TS_ASSERT( Poco::File(m_long_filename).exists() ); + std::ifstream in(m_long_filename.c_str()); + std::string fullline; + getline(in,fullline); + std::vector columns; + boost::split(columns, fullline, boost::is_any_of("\t"), boost::token_compress_on); + TS_ASSERT_EQUALS(columns.size(),4); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(0)), 0, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(1)), 1, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(2)), 1, 0.01); + TS_ASSERT((columns.at(3) == "nan") || (columns.at(3) == "inf")); + in.close(); + + cleanupafterwards(); + } + void testNoY() + { + //create a new workspace and then delete it later on + createWS(false,true); + + Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveANSTOAscii"); + alg->setPropertyValue("InputWorkspace", m_name); + alg->setPropertyValue("Filename", m_filename); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + + if ( ! alg->isExecuted() ) + { + TS_FAIL("Could not run SaveANSTOAscii"); + } + m_long_filename= alg->getPropertyValue("Filename"); + // has the algorithm written a file to disk? + TS_ASSERT( Poco::File(m_long_filename).exists() ); + std::ifstream in(m_long_filename.c_str()); + std::string fullline; + getline(in,fullline); + std::vector columns; + boost::split(columns, fullline, boost::is_any_of("\t"), boost::token_compress_on); + TS_ASSERT_EQUALS(columns.size(),4); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(0)), 1.5, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(1)), 0, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(2)), 1, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(3)), 0.6, 0.01); + in.close(); + + cleanupafterwards(); + } + void testNoE() + { + //create a new workspace and then delete it later on + createWS(false,false,true); + + Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveANSTOAscii"); + alg->setPropertyValue("InputWorkspace", m_name); + alg->setPropertyValue("Filename", m_filename); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + + if ( ! alg->isExecuted() ) + { + TS_FAIL("Could not run SaveANSTOAscii"); + } + m_long_filename= alg->getPropertyValue("Filename"); + // has the algorithm written a file to disk? + TS_ASSERT( Poco::File(m_long_filename).exists() ); + std::ifstream in(m_long_filename.c_str()); + std::string fullline; + getline(in,fullline); + std::vector columns; + boost::split(columns, fullline, boost::is_any_of("\t"), boost::token_compress_on); + TS_ASSERT_EQUALS(columns.size(),4); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(0)), 1.5, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(1)), 1, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(2)), 0, 0.01); + TS_ASSERT_DELTA(boost::lexical_cast(columns.at(3)), 0.6, 0.01); + in.close(); + + cleanupafterwards(); + } + + void test_fail_invalid_workspace() + { + Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveANSTOAscii"); + alg->setRethrows(true); + TS_ASSERT(alg->isInitialized()); + TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename)); + m_long_filename= alg->getPropertyValue("Filename"); //Get absolute path + TS_ASSERT_THROWS_ANYTHING(alg->setPropertyValue("InputWorkspace", "NotARealWS")); + TS_ASSERT_THROWS_ANYTHING(alg->execute()); + + // the algorithm shouldn't have written a file to disk + TS_ASSERT( !Poco::File(m_long_filename).exists() ); + } +private: + void createWS(bool zeroX = false, bool zeroY = false, bool zeroE = false) + { + MatrixWorkspace_sptr ws = WorkspaceCreationHelper::Create2DWorkspace(1,10); + AnalysisDataService::Instance().addOrReplace(m_name, ws); + //Check if any of X, Y or E should be zeroed to check for divide by zero or similiar + if (zeroX) + { + ws->dataX(0) = m_data0; + } + else + { + ws->dataX(0) = m_dataX; + } + + if (zeroY) + { + ws->dataY(0) = m_data0; + } + else + { + ws->dataY(0) = m_dataY; + } + + if (zeroE) + { + ws->dataE(0) = m_data0; + } + else + { + ws->dataE(0) = m_dataE; + } + } + void cleanupafterwards() + { + Poco::File(m_long_filename).remove(); + AnalysisDataService::Instance().remove(m_name); + } + std::string m_filename, m_name, m_long_filename; + std::vector m_dataX, m_dataY, m_dataE, m_data0; +}; + + +#endif /*SAVEANSTOTEST_H_*/ diff --git a/Code/Mantid/Framework/DataObjects/src/Peak.cpp b/Code/Mantid/Framework/DataObjects/src/Peak.cpp index 4b7f887fad3a..a536f4a294d3 100644 --- a/Code/Mantid/Framework/DataObjects/src/Peak.cpp +++ b/Code/Mantid/Framework/DataObjects/src/Peak.cpp @@ -392,7 +392,7 @@ namespace DataObjects V3D detDir = detPos - samplePos; double two_theta = detDir.angle(beamDir); - + // In general case (2*pi/d)^2=k_i^2+k_f^2-2*k_i*k_f*cos(two_theta) // E_i,f=k_i,f^2*hbar^2/(2 m) return 1e10*PhysicalConstants::h/sqrt(2.0*PhysicalConstants::NeutronMass*PhysicalConstants::meV) @@ -541,8 +541,8 @@ namespace DataObjects { // Set the detector ID, the row, col, etc. this->setDetectorID(det->getID()); - // HOWEVER, we retain the old detector position because we assume that is a little more precise. - detPos = samplePos + beam * detPos.norm(); + // The old detector position is not more precise if it comes from FindPeaksMD + detPos = det->getPos(); return true; } return false; diff --git a/Code/Mantid/Framework/Geometry/test/ConvexPolygonTest.h b/Code/Mantid/Framework/Geometry/test/ConvexPolygonTest.h index 8a31e9791bcb..dacf44c14212 100644 --- a/Code/Mantid/Framework/Geometry/test/ConvexPolygonTest.h +++ b/Code/Mantid/Framework/Geometry/test/ConvexPolygonTest.h @@ -44,7 +44,7 @@ class ConvexPolygonTest : public CxxTest::TestSuite origin = origin->insert(new Vertex2D(1.0,1.0)); origin = origin->insert(new Vertex2D(0.0,1.0)); - TS_ASSERT_THROWS_NOTHING(new ConvexPolygon(origin)); + TS_ASSERT_THROWS_NOTHING(ConvexPolygon poly(origin)); } void test_Building_With_Head_Vertex_Gives_Correct_Number_Of_Vertices() diff --git a/Code/Mantid/Framework/Geometry/test/InstrumentTest.h b/Code/Mantid/Framework/Geometry/test/InstrumentTest.h index 2f21c0cc4162..6c32e7b6157b 100644 --- a/Code/Mantid/Framework/Geometry/test/InstrumentTest.h +++ b/Code/Mantid/Framework/Geometry/test/InstrumentTest.h @@ -454,9 +454,9 @@ class InstrumentTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( inst->getValidToDate(), validTo); // Try the parametrized copy constructor ParameterMap_sptr map(new ParameterMap()); - Instrument * inst2 = new Instrument(boost::dynamic_pointer_cast(inst), map); - TS_ASSERT_EQUALS( inst2->getValidFromDate(), validFrom); - TS_ASSERT_EQUALS( inst2->getValidToDate(), validTo); + Instrument inst2(boost::dynamic_pointer_cast(inst), map); + TS_ASSERT_EQUALS( inst2.getValidFromDate(), validFrom); + TS_ASSERT_EQUALS( inst2.getValidToDate(), validTo); } void test_getMinMaxDetectorIDs() diff --git a/Code/Mantid/Framework/Geometry/test/MDImplicitFunctionTest.h b/Code/Mantid/Framework/Geometry/test/MDImplicitFunctionTest.h index c80124bf3e79..30e20cf7699f 100644 --- a/Code/Mantid/Framework/Geometry/test/MDImplicitFunctionTest.h +++ b/Code/Mantid/Framework/Geometry/test/MDImplicitFunctionTest.h @@ -1,13 +1,9 @@ #ifndef MANTID_MDALGORITHMS_MDIMPLICITFUNCTIONTEST_H_ #define MANTID_MDALGORITHMS_MDIMPLICITFUNCTIONTEST_H_ -#include "MantidKernel/System.h" -#include "MantidKernel/Timer.h" +#include #include "MantidGeometry/MDGeometry/MDImplicitFunction.h" -#include "MantidGeometry/MDGeometry/MDPlane.h" #include -#include -#include using namespace Mantid::Geometry; using namespace Mantid; @@ -109,9 +105,9 @@ class MDImplicitFunctionTest : public CxxTest::TestSuite * @param vertexes :: returns the vertex array * @return also a bare-array version of the same thing */ - coord_t * make2DVertexSquare(std::vector > & vertexes, double x1, double y1, double x2, double y2) + boost::shared_array make2DVertexSquare(std::vector > & vertexes, double x1, double y1, double x2, double y2) { - coord_t * out = new coord_t[8]; + auto out = boost::shared_array(new coord_t[8]); vertexes.clear(); add2DVertex(vertexes, x1,y1); out[0] = static_cast(x1); out[1] = static_cast(y1); @@ -154,67 +150,67 @@ class MDImplicitFunctionTest : public CxxTest::TestSuite // 3 ways to do the same thing std::vector > vertexes; - coord_t * bareVertexes; + boost::shared_array bareVertexes; bareVertexes = make2DVertexSquare(vertexes, 1.2, 0.2, 1.8, 0.8); TSM_ASSERT("Box that is to the right; not touching", !f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box that is to the right; not touching", !f.isBoxTouching( bareVertexes, 4) ); - TSM_ASSERT("Box that is to the right; not touching", f.boxContact( bareVertexes, 4) == MDImplicitFunction::NOT_TOUCHING ); + TSM_ASSERT("Box that is to the right; not touching", !f.isBoxTouching( bareVertexes.get(), 4) ); + TSM_ASSERT("Box that is to the right; not touching", f.boxContact( bareVertexes.get(), 4) == MDImplicitFunction::NOT_TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.2, 1.2, 0.8, 1.8); TSM_ASSERT("Box that is above; not touching", !f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box that is above; not touching", !f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box that is above; not touching", f.boxContact( bareVertexes, 4) == MDImplicitFunction::NOT_TOUCHING ); + TSM_ASSERT("Box that is above; not touching", !f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box that is above; not touching", f.boxContact( bareVertexes.get(), 4) == MDImplicitFunction::NOT_TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.8, 0.8, 1.8, 1.8); TSM_ASSERT("Box with one corner touching in the upper right; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box with one corner touching in the upper right; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box with one corner touching in the upper right; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box with one corner touching in the upper right; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box with one corner touching in the upper right; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.8, 0.2, 1.8, 0.8); TSM_ASSERT("Box with both right-hand vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box with both right-hand vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box with both right-hand vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box with both right-hand vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box with both right-hand vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.8, -1.0, 1.8, +3.0); TSM_ASSERT("Box overlapping on the right side, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box overlapping on the right side, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box overlapping on the right side, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box overlapping on the right side, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box overlapping on the right side, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, -2.0, -1.0, 0.2, +3.0); TSM_ASSERT("Box overlapping on the left side, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box overlapping on the left side, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box overlapping on the left side, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box overlapping on the left side, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box overlapping on the left side, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, -2.0, 0.9, +3.0, +3.0); TSM_ASSERT("Box overlapping on the top side, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box overlapping on the top side, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box overlapping on the top side, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box overlapping on the top side, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box overlapping on the top side, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, -2.0, -3.0, +3.0, +0.1); TSM_ASSERT("Box overlapping on the bottom side, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box overlapping on the bottom side, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box overlapping on the bottom side, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box overlapping on the bottom side, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box overlapping on the bottom side, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, -2.0, -2.0, 3.0, 3.0); TSM_ASSERT("Box bigger than region on all directions, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box bigger than region on all directions, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box bigger than region on all directions, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Box bigger than region on all directions, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box bigger than region on all directions, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.5, -10.0, 0.55, +10.0); TSM_ASSERT("Narrow box passing through the middle, no vertexes inside; touches", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Narrow box passing through the middle, no vertexes inside; touches", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Narrow box passing through the middle, no vertexes inside; touches", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::TOUCHING ); + TSM_ASSERT("Narrow box passing through the middle, no vertexes inside; touches", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Narrow box passing through the middle, no vertexes inside; touches", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.5, 1.1, 0.55, +10.0); TSM_ASSERT("Narrow box but above; not touching", !f.isBoxTouching( vertexes) ); - TSM_ASSERT("Narrow box but above; not touching", !f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Narrow box but above; not touching", f.boxContact( bareVertexes, 4) == MDImplicitFunction::NOT_TOUCHING ); + TSM_ASSERT("Narrow box but above; not touching", !f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Narrow box but above; not touching", f.boxContact( bareVertexes.get(), 4) == MDImplicitFunction::NOT_TOUCHING ); bareVertexes = make2DVertexSquare(vertexes, 0.1, 0.1, 0.9, 0.9); TSM_ASSERT("Box that is completely within region; touches ", f.isBoxTouching( vertexes) ); - TSM_ASSERT("Box that is completely within region; touches ", f.isBoxTouching( bareVertexes, 4 ) ); - TSM_ASSERT("Box that is completely within region; touches ", f.boxContact( bareVertexes, 4 ) == MDImplicitFunction::CONTAINED ); + TSM_ASSERT("Box that is completely within region; touches ", f.isBoxTouching( bareVertexes.get(), 4 ) ); + TSM_ASSERT("Box that is completely within region; touches ", f.boxContact( bareVertexes.get(), 4 ) == MDImplicitFunction::CONTAINED ); vertexes.clear(); add2DVertex(vertexes, 3.0, -0.1); diff --git a/Code/Mantid/Framework/Geometry/test/ObjCompAssemblyTest.h b/Code/Mantid/Framework/Geometry/test/ObjCompAssemblyTest.h index 71090196e252..30809b726d62 100644 --- a/Code/Mantid/Framework/Geometry/test/ObjCompAssemblyTest.h +++ b/Code/Mantid/Framework/Geometry/test/ObjCompAssemblyTest.h @@ -57,8 +57,8 @@ class ObjCompAssemblyTest : public CxxTest::TestSuite void testAddBad() { ObjCompAssembly bank("BankName"); - Component* det1 = new Component("Det1Name"); - TS_ASSERT_THROWS(bank.add(det1),Mantid::Kernel::Exception::InstrumentDefinitionError); + Component det1("Det1Name"); + TS_ASSERT_THROWS(bank.add(&det1),Mantid::Kernel::Exception::InstrumentDefinitionError); } void testAdd() diff --git a/Code/Mantid/Framework/Geometry/test/ObjComponentTest.h b/Code/Mantid/Framework/Geometry/test/ObjComponentTest.h index fb753e9634b5..103aca384541 100644 --- a/Code/Mantid/Framework/Geometry/test/ObjComponentTest.h +++ b/Code/Mantid/Framework/Geometry/test/ObjComponentTest.h @@ -293,9 +293,8 @@ class ObjComponentTest : public CxxTest::TestSuite TS_ASSERT_DELTA(point.Z(),-31.5,1e-6); } - ObjComponent * MakeWithScaleFactor(ObjComponent * parent, double X, double Y, double Z) + ObjComponent * MakeWithScaleFactor(const ObjComponent * parent, ParameterMap * map, double X, double Y, double Z) { - ParameterMap * map = new ParameterMap; ObjComponent * ret = new ObjComponent(parent, map); map->addV3D(ret, "sca", V3D(X,Y,Z)); return ret; @@ -303,32 +302,37 @@ class ObjComponentTest : public CxxTest::TestSuite void testIsValidWithScaleFactor() { - ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent ocyl_base("ocyl", createCappedCylinder()); + ObjComponent * ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0,1.0,1.0); TS_ASSERT(ocyl->isValid(V3D(2.4,0.0,0.0))); TS_ASSERT(ocyl->isValid(V3D(-6.4,0.0,0.0))); TS_ASSERT(!ocyl->isValid(V3D(2.5,0.0,0.0))); TS_ASSERT(!ocyl->isValid(V3D(-6.5,0.0,0.0))); TS_ASSERT(ocyl->isValid(V3D(2.3,0.0,0.0))); TS_ASSERT(ocyl->isValid(V3D(-6.3,0.0,0.0))); + delete ocyl; } void testIsOnSideWithScaleFactor() { - ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent ocyl_base("ocyl", createCappedCylinder()); + ObjComponent * ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0,1.0,1.0); TS_ASSERT(ocyl->isOnSide(V3D(2.4,0.0,0.0))); TS_ASSERT(ocyl->isOnSide(V3D(-6.4,0.0,0.0))); TS_ASSERT(!ocyl->isOnSide(V3D(2.5,0.0,0.0))); TS_ASSERT(!ocyl->isOnSide(V3D(-6.5,0.0,0.0))); TS_ASSERT(!ocyl->isOnSide(V3D(2.3,0.0,0.0))); TS_ASSERT(!ocyl->isOnSide(V3D(-6.3,0.0,0.0))); + delete ocyl; } void testInterceptSurfaceWithScaleFactor() { - ObjComponent * ocyl_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * ocyl = MakeWithScaleFactor(ocyl_base, 2.0,1.0,3.0); + ParameterMap map; + ObjComponent ocyl_base("ocyl", createCappedCylinder()); + ObjComponent * ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0,1.0,3.0); Track trackScale(V3D(-6.5,0,0),V3D(1.0,0,0)); TS_ASSERT_EQUALS( ocyl->interceptSurface(trackScale), 1 ); @@ -350,60 +354,70 @@ class ObjComponentTest : public CxxTest::TestSuite TS_ASSERT_DELTA(itscaleW->distFromStart, 6.5, 1e-6); TS_ASSERT_EQUALS(itscaleW->entryPoint, V3D(0,0,-1.5)); TS_ASSERT_EQUALS(itscaleW->exitPoint, V3D(0,0,+1.5)); + delete ocyl; } void testBoundingBoxWithScaleFactor() { - ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent A_base("ocyl", createCappedCylinder()); + ObjComponent * A = MakeWithScaleFactor( &A_base, &map, 2.0,1.0,1.0); BoundingBox bbox; A->getBoundingBox(bbox); TS_ASSERT_DELTA(bbox.xMax(), 2.4,0.00001); TS_ASSERT_DELTA(bbox.xMin(),-6.4,0.00001); + delete A; } void testPointInObjectWithScaleFactor() { - ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent A_base("ocyl", createCappedCylinder()); + ObjComponent * A = MakeWithScaleFactor( &A_base, &map, 2.0,1.0,1.0); V3D scalept; TS_ASSERT_EQUALS(A->getPointInObject(scalept),1); TS_ASSERT_DELTA(scalept.X(),0.0,1e-6); TS_ASSERT_DELTA(scalept.Y(),0.0,1e-6); TS_ASSERT_DELTA(scalept.Z(),0.0,1e-6); + delete A; } void testPointInObjectWithScaleFactor2() { - ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder()); - A_base->setRot(Quat(90.0,V3D(0,0,1))); - ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent A_base("ocyl", createCappedCylinder()); + A_base.setRot(Quat(90.0,V3D(0,0,1))); + ObjComponent * A = MakeWithScaleFactor( &A_base, &map, 2.0,1.0,1.0); V3D scalept(0,0,0); TS_ASSERT_EQUALS(A->getPointInObject(scalept),1); TS_ASSERT_DELTA(scalept.X(), 0.0,1e-6); TS_ASSERT_DELTA(scalept.Y(), 0.0,1e-6); TS_ASSERT_DELTA(scalept.Z(), 0.0,1e-6); + delete A; } void testPointInObjectWithScaleFactorAndWithOffset() { - ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder()); - A_base->setPos(10,0,0); - ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent A_base("ocyl", createCappedCylinder()); + A_base.setPos(10,0,0); + ObjComponent * A = MakeWithScaleFactor( &A_base, &map, 2.0,1.0,1.0); V3D scalept(0,0,0); TS_ASSERT_EQUALS(A->getPointInObject(scalept),1); TS_ASSERT_DELTA(scalept.X(), 10.0,1e-6); TS_ASSERT_DELTA(scalept.Y(), 0.0,1e-6); TS_ASSERT_DELTA(scalept.Z(), 0.0,1e-6); + delete A; } void testSolidAngleCappedCylinderWithScaleFactor() { - ObjComponent * A_base = new ObjComponent("ocyl", createCappedCylinder()); - ObjComponent * A = MakeWithScaleFactor( A_base, 2.0,1.0,1.0); + ParameterMap map; + ObjComponent A_base("ocyl", createCappedCylinder()); + ObjComponent * A = MakeWithScaleFactor( &A_base, &map, 2.0,1.0,1.0); - A_base->setPos(10,0,0); - A_base->setRot(Quat(90.0,V3D(0,0,1))); + A_base.setPos(10,0,0); + A_base.setRot(Quat(90.0,V3D(0,0,1))); double satol=3e-3; // tolerance for solid angle // this point should be 0.5 above the cylinder on its axis of sym @@ -415,7 +429,7 @@ class ObjComponentTest : public CxxTest::TestSuite // Add a parent with a rotation of its own; Component parent("parent",V3D(0,10,0),Quat(0.0,V3D(0,1,0))); - A_base->setParent(&parent); + A_base.setParent(&parent); // See testSolidAngleCappedCylinder in ObjectTest - these tests are a subset of them // assume this is the same position as above @@ -426,6 +440,7 @@ class ObjComponentTest : public CxxTest::TestSuite // Calling on an ObjComponent without an associated geometric object will throw ObjComponent B("noShape"); TS_ASSERT_THROWS( B.solidAngle(V3D(1,2,3)), Exception::NullPointerException ) + delete A; } private: diff --git a/Code/Mantid/Framework/Geometry/test/ParComponentFactoryTest.h b/Code/Mantid/Framework/Geometry/test/ParComponentFactoryTest.h index 94f6e1d46663..cb19f15c94ef 100644 --- a/Code/Mantid/Framework/Geometry/test/ParComponentFactoryTest.h +++ b/Code/Mantid/Framework/Geometry/test/ParComponentFactoryTest.h @@ -26,6 +26,7 @@ class ParComponentFactoryTest : public CxxTest::TestSuite boost::shared_ptr pdet; TS_ASSERT_THROWS_NOTHING( pdet = ParComponentFactory::createDetector(det, map) ); TS_ASSERT(pdet); + delete map; } void test_createInstrument() diff --git a/Code/Mantid/Framework/Geometry/test/ParInstrumentTest.h b/Code/Mantid/Framework/Geometry/test/ParInstrumentTest.h index 65c44cdc9c6a..398be3c41dce 100644 --- a/Code/Mantid/Framework/Geometry/test/ParInstrumentTest.h +++ b/Code/Mantid/Framework/Geometry/test/ParInstrumentTest.h @@ -35,6 +35,8 @@ class ParInstrumentTest : public CxxTest::TestSuite instrument->markAsMonitor(det3.get()); pmap.reset(new ParameterMap); + delete source; + delete sample; } void test_Constructor_Throws_With_Invalid_Pointers() diff --git a/Code/Mantid/Framework/Geometry/test/ParametrizedComponentTest.h b/Code/Mantid/Framework/Geometry/test/ParametrizedComponentTest.h index da9fc10ccc71..8120ae5740aa 100644 --- a/Code/Mantid/Framework/Geometry/test/ParametrizedComponentTest.h +++ b/Code/Mantid/Framework/Geometry/test/ParametrizedComponentTest.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "MantidGeometry/Instrument/Component.h" #include "MantidGeometry/IComponent.h" #include "MantidKernel/V3D.h" @@ -98,6 +99,7 @@ class ParametrizedComponentTest : public CxxTest::TestSuite TS_ASSERT_THROWS_NOTHING(typeName= paramComp->getParameterType(m_quatName)); TS_ASSERT_EQUALS(ParameterMap::pQuat(),typeName); + delete paramComp; cleanUpComponent(); } @@ -131,6 +133,7 @@ class ParametrizedComponentTest : public CxxTest::TestSuite TS_ASSERT_EQUALS(paramNames.size(), 4); checkBaseParameterNamesExist(paramNames); + delete paramComp; cleanUpComponent(); } @@ -213,7 +216,7 @@ class ParametrizedComponentTest : public CxxTest::TestSuite Component * createSingleParameterizedComponent() { m_parentComp = new Component("Parent",V3D(1,1,1)); - m_paramMap = boost::shared_ptr(new ParameterMap(), NoDeleting()); + m_paramMap = boost::make_shared(); m_paramMap->add("string", m_parentComp, m_strName, m_strValue); m_paramMap->add("double", m_parentComp, m_dblName, m_dblValue); @@ -227,7 +230,7 @@ class ParametrizedComponentTest : public CxxTest::TestSuite void createParameterizedTree() { m_parentComp = new Component("Parent",V3D(1,1,1)); - m_paramMap = boost::shared_ptr(new ParameterMap(), NoDeleting()); + m_paramMap = boost::make_shared(); m_paramMap->add("string", m_parentComp, m_strName, m_strValue); m_paramMap->add("double", m_parentComp, m_dblName, m_dblValue); diff --git a/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h b/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h index 15a3b54ea1bb..19fd67ab1a5d 100644 --- a/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h +++ b/Code/Mantid/Framework/Geometry/test/RectangularDetectorTest.h @@ -74,9 +74,9 @@ class RectangularDetectorTest : public CxxTest::TestSuite // Now test the parametrized version of that ParameterMap_sptr pmap( new ParameterMap() ); - RectangularDetector *pq = new RectangularDetector(q, pmap.get()); - TS_ASSERT_EQUALS(pq->getPos(), V3D(2, 3, 4)); - TS_ASSERT_EQUALS(pq->getRelativeRot(), Quat(1, 0, 0, 0)); + RectangularDetector pq(q, pmap.get()); + TS_ASSERT_EQUALS(pq.getPos(), V3D(2, 3, 4)); + TS_ASSERT_EQUALS(pq.getRelativeRot(), Quat(1, 0, 0, 0)); delete parent; } diff --git a/Code/Mantid/Framework/Geometry/test/Vertex2DTest.h b/Code/Mantid/Framework/Geometry/test/Vertex2DTest.h index d1fb6473c594..1dd7f399781c 100644 --- a/Code/Mantid/Framework/Geometry/test/Vertex2DTest.h +++ b/Code/Mantid/Framework/Geometry/test/Vertex2DTest.h @@ -59,7 +59,10 @@ class Vertex2DTest : public CxxTest::TestSuite void test_Insert_Yields_Next_As_Inserted_Vertex() { - makeThreeVertexChain(true, false); + auto v2d = makeThreeVertexChain(true, false); + delete v2d->next()->next(); + delete v2d->next(); + delete v2d; } void test_Remove_Returns_An_Isolated_Vertex() @@ -77,7 +80,10 @@ class Vertex2DTest : public CxxTest::TestSuite pIter.advance(); TS_ASSERT_EQUALS(pIter.point(), V2D(1.0,1.0)); pIter.advance(); //Back to the start - TS_ASSERT_EQUALS(pIter.point(), V2D()); + TS_ASSERT_EQUALS(pIter.point(), V2D()); + delete start->next()->next(); + delete start->next(); + delete start; } private: @@ -123,6 +129,9 @@ class Vertex2DTest : public CxxTest::TestSuite UNUSED_ARG(removedTwo); TS_ASSERT_EQUALS(origin->next(), origin); TS_ASSERT_EQUALS(origin->previous(), origin); + delete origin; + delete third; + delete two; return NULL; } else diff --git a/Code/Mantid/Framework/LiveData/src/SNSLiveEventDataListener.cpp b/Code/Mantid/Framework/LiveData/src/SNSLiveEventDataListener.cpp index 0c84363b84b7..4a461d02c904 100644 --- a/Code/Mantid/Framework/LiveData/src/SNSLiveEventDataListener.cpp +++ b/Code/Mantid/Framework/LiveData/src/SNSLiveEventDataListener.cpp @@ -473,7 +473,7 @@ namespace LiveData Poco::XML::DOMParser parser; Poco::AutoPtr doc = parser.parseString( m_instrumentXML); - const Poco::XML::NodeList *nodes = doc->getElementsByTagName( "parameter"); + const Poco::AutoPtr nodes = doc->getElementsByTagName( "parameter"); // Oddly, NodeLists don't seem to have any provision for iterators. Also, // the length() function actually traverses the list to get the count, // so we should probably call it once and store it in a variable instead @@ -482,7 +482,7 @@ namespace LiveData for (long unsigned i = 0; i < nodesLength; i++) { Poco::XML::Node *node = nodes->item( i); - const Poco::XML::NodeList *childNodes = node->childNodes(); + const Poco::AutoPtr childNodes = node->childNodes(); long unsigned childNodesLength = childNodes->length(); for (long unsigned j=0; j < childNodesLength; j++) @@ -491,7 +491,7 @@ namespace LiveData if (childNode->nodeName() == "logfile") { // Found one! - Poco::XML::NamedNodeMap *attr = childNode->attributes(); + Poco::AutoPtr attr = childNode->attributes(); long unsigned attrLength = attr->length(); for (long unsigned k = 0; k < attrLength; k++) { @@ -501,14 +501,9 @@ namespace LiveData m_requiredLogs.push_back( attrNode->nodeValue()); } } - - attr->release(); } } - childNodes->release(); - } - nodes->release(); } // Check to see if we can complete the initialzation steps diff --git a/Code/Mantid/Framework/LiveData/test/ADARAPacketTest.h b/Code/Mantid/Framework/LiveData/test/ADARAPacketTest.h index 867664b2f75a..294cebe69ab1 100644 --- a/Code/Mantid/Framework/LiveData/test/ADARAPacketTest.h +++ b/Code/Mantid/Framework/LiveData/test/ADARAPacketTest.h @@ -4,9 +4,10 @@ #include #include "MantidLiveData/ADARA/ADARAParser.h" -#include "boost/shared_ptr.hpp" -#include "Poco/DOM/DOMParser.h" // for parsing the XML device descriptions - +#include +#include // for parsing the XML device descriptions +#include +#include // All of the sample packets that we need to run the tests are defined in the following // header. The packets can get pretty long, which is why I didn't want them cluttering @@ -91,7 +92,7 @@ class ADARAPacketTest : public CxxTest::TestSuite, { // Basic XML validation Poco::XML::DOMParser parser; - TS_ASSERT_THROWS_NOTHING( parser.parseMemory( pkt->description().c_str(), pkt->description().length())); + TS_ASSERT_THROWS_NOTHING( Poco::AutoPtr doc = parser.parseMemory( pkt->description().c_str(), pkt->description().length()) ); } } diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmIDProxy.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmIDProxy.h new file mode 100644 index 000000000000..a4266e25c12c --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmIDProxy.h @@ -0,0 +1,50 @@ +#ifndef MANTID_PYTHONINTERFACE_ALGORITHMIDPROXY_H_ +#define MANTID_PYTHONINTERFACE_ALGORITHMIDPROXY_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: + */ +#include "MantidAPI/IAlgorithm.h" // for AlgorithmID typedef + +namespace Mantid +{ + namespace PythonInterface + { + /** + * Provides a concrete type to wrap & return AlgorithmIDs that are actually + * just typedefs for void* + */ + struct AlgorithmIDProxy + { + /// Construct with existing pointer + explicit AlgorithmIDProxy(API::AlgorithmID p) : id(p) + {} + + bool operator==(const AlgorithmIDProxy & rhs) + { + return (id == rhs.id); + } + /// held ID value + API::AlgorithmID id; + }; + } +} + +#endif /* MANTID_PYTHONINTERFACE_ALGORITHMIDPROXY_H_ */ diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h index 59376c71523f..cbbd5ec7cbb6 100644 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/PythonAlgorithm/AlgorithmWrapper.h @@ -59,6 +59,10 @@ namespace Mantid virtual const std::string category() const; /// A default category, chosen if there is no override std::string defaultCategory() const; + /// Allow the isRunning method to be overridden + virtual bool isRunning() const; + /// Allow the cancel method to be overridden + virtual void cancel(); /// Returns the validateInputs result of the algorithm. std::map validateInputs(); ///@} @@ -81,6 +85,8 @@ namespace Mantid /// The Python portion of the object PyObject *m_self; + /// A pointer to an overridden isRunning method + PyObject *m_isRunningObj; }; } } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp index 7d491ac9b70f..c501b5edb2e4 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp @@ -1,17 +1,61 @@ #include "MantidAPI/AlgorithmManager.h" +#include "MantidPythonInterface/api/AlgorithmIDProxy.h" #include #include +#include #include #include #include -using Mantid::API::AlgorithmManagerImpl; -using Mantid::API::AlgorithmManager; +using namespace Mantid::API; +using Mantid::PythonInterface::AlgorithmIDProxy; using namespace boost::python; namespace { + /** + * Return the algorithm identified by the given ID. A wrapper version that takes a + * AlgorithmIDProxy that wraps a AlgorithmID + * @param self The calling object + * @param id An algorithm ID + */ + IAlgorithm_sptr getAlgorithm(AlgorithmManagerImpl &self, AlgorithmIDProxy idHolder) + { + return self.getAlgorithm(idHolder.id); + } + + /** + * Remove the algorithm identified by the given ID from the list of managed algorithms. + * A wrapper version that takes a AlgorithmIDProxy that wraps a AlgorithmID + * @param self The calling object + * @param id An algorithm ID + */ + void removeById(AlgorithmManagerImpl &self, AlgorithmIDProxy idHolder) + { + return self.removeById(idHolder.id); + } + + /** + * @param self A reference to the calling object + * @param algName The name of the algorithm + * @return A python list of managed algorithms that are currently running + */ + boost::python::list runningInstancesOf(AlgorithmManagerImpl &self, const std::string & algName) + { + boost::python::list algs; + auto mgrAlgs = self.runningInstancesOf(algName); + for(auto iter = mgrAlgs.begin(); iter != mgrAlgs.end(); ++iter) + { + // boost 1.41 (RHEL6) can't handle registering IAlgorithm_const_sptr so we + // have to cast to IAlgorithm_sptr and then convert to Python + // The constness is pretty-irrelevant by this point anyway + algs.append(boost::const_pointer_cast(*iter)); + } + + return algs; + } + ///@cond //------------------------------------------------------------------------------------------------------ /// Define overload generators @@ -26,6 +70,20 @@ void export_AlgorithmManager() .def("create", &AlgorithmManagerImpl::create, create_overloads((arg("name"), arg("version")), "Creates a managed algorithm.")) .def("createUnmanaged", &AlgorithmManagerImpl::createUnmanaged, createUnmanaged_overloads((arg("name"), arg("version")), "Creates an unmanaged algorithm.")) + .def("size", &AlgorithmManagerImpl::size, "Returns the number of managed algorithms") + .def("setMaxAlgorithms", &AlgorithmManagerImpl::setMaxAlgorithms, + "Set the maximum number of allowed managed algorithms") + .def("getAlgorithm", &getAlgorithm, + "Return the algorithm instance identified by the given id.") + .def("removeById", &removeById, "Remove an algorithm from the managed list") + .def("newestInstanceOf", &AlgorithmManagerImpl::newestInstanceOf, + "Returns the newest created instance of the named algorithm") + .def("runningInstancesOf", &runningInstancesOf, + "Returns a list of managed algorithm instances that are currently executing") + .def("clear", &AlgorithmManagerImpl::clear, "Clears the current list of managed algorithms") + .def("cancelAll", &AlgorithmManagerImpl::cancelAll, + "Requests that all currently running algorithms be cancelled") + .def("Instance", &AlgorithmManager::Instance, return_value_policy(), "Returns a reference to the AlgorithmManager singleton") .staticmethod("Instance") 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 f65cc3338691..20c82257b24f 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IAlgorithm.cpp @@ -2,6 +2,7 @@ #pragma warning( disable: 4250 ) // Disable warning regarding inheritance via dominance, we have no way around it with the design #endif #include "MantidAPI/IAlgorithm.h" +#include "MantidPythonInterface/api/AlgorithmIDProxy.h" #ifdef _MSC_VER #pragma warning( default: 4250 ) #endif @@ -13,13 +14,16 @@ #include #include #include +#include #include using Mantid::Kernel::IPropertyManager; using Mantid::Kernel::Property; using Mantid::Kernel::Direction; +using Mantid::API::AlgorithmID; using Mantid::API::IAlgorithm; using Mantid::API::IAlgorithm_sptr; +using Mantid::PythonInterface::AlgorithmIDProxy; using Mantid::PythonInterface::Policies::VectorToNumpy; using namespace boost::python; @@ -209,16 +213,35 @@ namespace return result; } + /** + * @param self A reference to the calling object + * @return An AlgorithmID wrapped in a AlgorithmIDProxy container or None if there is + * no ID + */ + PyObject * getAlgorithmID(IAlgorithm & self) + { + AlgorithmID id = self.getAlgorithmID(); + if(id) return to_python_value()(AlgorithmIDProxy(id)); + else Py_RETURN_NONE; + } + } void export_ialgorithm() { + class_("AlgorithmID", no_init) + .def(self == self) + ; + + // --------------------------------- IAlgorithm ------------------------------------------------ register_ptr_to_python>(); - class_, boost::noncopyable>("IAlgorithm", "Interface for all algorithms", no_init) + class_, + boost::noncopyable>("IAlgorithm", "Interface for all algorithms", no_init) .def("name", &IAlgorithm::name, "Returns the name of the algorithm") .def("alias", &IAlgorithm::alias, "Return the aliases for the algorithm") .def("version", &IAlgorithm::version, "Returns the version number of the algorithm") + .def("cancel", &IAlgorithm::cancel, "Request that the algorithm stop running") .def("category", &IAlgorithm::category, "Returns the category containing the algorithm") .def("categories", &IAlgorithm::categories, "Returns the list of categories this algorithm belongs to") .def("workspaceMethodName",&IAlgorithm::workspaceMethodName, @@ -227,6 +250,7 @@ void export_ialgorithm() "Returns a set of class names that will have the method attached. Empty list indicates all types") .def("workspaceMethodInputProperty", &IAlgorithm::workspaceMethodInputProperty, "Returns the name of the input workspace property used by the calling object") + .def("getAlgorithmID", &getAlgorithmID, "Returns a unique identifier for this algorithm object") .def("getOptionalMessage", &IAlgorithm::getOptionalMessage, "Returns the optional user message attached to the algorithm") .def("getWikiSummary", &IAlgorithm::getWikiSummary, "Returns the summary found on the wiki page") .def("getWikiDescription", &IAlgorithm::getWikiDescription, "Returns the description found on the wiki page using wiki markup") @@ -237,7 +261,8 @@ void export_ialgorithm() "such that the mandatory properties are first followed by the optional ones.") .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("isExecuted", &IAlgorithm::isExecuted, "Returns True if the algorithm has been executed successfully, 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("setAlwaysStoreInADS", &IAlgorithm::setAlwaysStoreInADS, diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp index 3190efea6112..a055041e2110 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/PythonAlgorithm/AlgorithmWrapper.cpp @@ -21,8 +21,17 @@ namespace Mantid * @param self A reference to the calling Python object */ AlgorithmWrapper::AlgorithmWrapper(PyObject* self) - : PythonAlgorithm(), m_self(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"); } /** @@ -65,6 +74,38 @@ namespace Mantid 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 */ diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/USANSSimulation.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/USANSSimulation.py new file mode 100644 index 000000000000..4f2b96b0737e --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/USANSSimulation.py @@ -0,0 +1,141 @@ +"""*WIKI* +Simulate a USANS workspace. + +A matrix workspace is created for a given analyzer angle. A list of wavelength peaks coming out +of the monochromator can be specified. The width of those peaks can also be specified. + +Both the main detector and the transmission detector are filled with compatible signals +according to a dummy transmission curve. + +The amplitude of the signal in the main detector is given by a sphere model. + +A monitor workspace is created with a fake beam profile. +*WIKI*""" +from mantid.simpleapi import * +from mantid.api import * +from mantid.kernel import * +import math +import numpy + +class USANSSimulation(PythonAlgorithm): + + def category(self): + return "SANS" + + def name(self): + return "USANSSimulation" + + def PyInit(self): + self.declareProperty("TwoTheta", 0.01, "Scattering angle in degrees") + self.declareProperty(FloatArrayProperty("WavelengthPeaks", values=[0.9, 1.2, 1.8, 3.6], + direction=Direction.Input), "Wavelength peaks out of the monochromator") + + # Model parameters + self.declareProperty("SphereRadius", 200.0, "Radius for the sphere model (Angstrom)") + self.declareProperty("Background", 0.0, "Background") + self.declareProperty("SigmaPeak", 0.01, "Width of the wavelength peaks") + + self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output workspace") + self.declareProperty(MatrixWorkspaceProperty("MonitorWorkspace", "", Direction.Output), "Output monitor workspace") + + def PyExec(self): + workspace = self.getPropertyValue("OutputWorkspace") + out_ws = CreateSimulationWorkspace(Instrument="USANS", + BinParams="0,50,32000", + UnitX="TOF", + OutputWorkspace=workspace) + + data_x = out_ws.dataX(0) + mon_ws_name = self.getPropertyValue("MonitorWorkspace") + mon_ws = CreateWorkspace(dataX=data_x, dataY=numpy.zeros(len(data_x)-1), + UnitX="TOF", OutputWorkspace=mon_ws_name) + mon_y = mon_ws.dataY(0) + mon_e = mon_ws.dataE(0) + + # Number of pixels for the main detector + n_pixels = out_ws.getNumberHistograms()/2 + # Clean up the workspace + for j in range(n_pixels): + data_y = out_ws.dataY(j) + for i in range(len(data_y)): + data_y[i] = 0.0 + + # Fill monitor workspace with fake beam profile + for i in range(len(data_x)-1): + wl_i = 0.0039560/30.0*(data_x[i]+data_x[i+1])/2.0 + mon_y[i] = 1000.0*math.exp(-wl_i) + mon_e[i] = math.sqrt(mon_y[i]) + + # Add analyzer theta value and monochromator angle theta_b in logs + two_theta = self.getProperty("TwoTheta").value + theta_b = 70.0 + theta = theta_b + two_theta + out_ws.getRun().addProperty("AnalyzerTheta", theta, 'degree', True) + out_ws.getRun().addProperty("TwoTheta", two_theta, 'degree', True) + out_ws.getRun().addProperty("MonochromatorTheta", theta_b, 'degree', True) + + # List of wavelength peaks, and width of the peaks + wl_peaks = self.getProperty("WavelengthPeaks").value + sigma = self.getProperty("SigmaPeak").value + + for wl in wl_peaks: + q = 6.28*math.sin(two_theta)/wl + Logger.get("USANS").notice( "wl = %g; Q = %g" % (wl, q)) + + for i in range(len(data_x)-1): + wl_i = 0.0039560/30.0*(data_x[i]+data_x[i+1])/2.0 + + # Scale the I(q) by a Gaussian to simulate the wavelength peaks selected by the monochromator + flux = 1.0e6/(sigma*math.sqrt(2.0*math.pi))*math.exp(-(wl_i-wl)*(wl_i-wl)/(2.0*sigma*sigma)) + + # Multiply by beam profile + flux *= mon_y[i] + + # Account for transmission + flux *= math.exp(-wl_i/2.0) + + # Transmission detector + for j in range(n_pixels, 2*n_pixels): + det_pos = out_ws.getInstrument().getDetector(j).getPos() + r = math.sqrt(det_pos.Y()*det_pos.Y()+det_pos.X()*det_pos.X()) + sigma = 0.01 + scale = math.exp(-r*r/(2.0*sigma*sigma)) + data_y = out_ws.dataY(j) + data_y[i] += int(scale*flux) + data_e = out_ws.dataE(j) + data_e[i] = math.sqrt(data_e[i]*data_e[i]+scale*scale*flux*flux) + + # Compute I(q) and store the results + q_i = q*wl/wl_i + i_q = self._sphere_model(q_i, scale=flux) + + for j in range(n_pixels): + det_pos = out_ws.getInstrument().getDetector(j).getPos() + r = math.sqrt(det_pos.Y()*det_pos.Y()+det_pos.X()*det_pos.X()) + sigma = 0.01 + scale = math.exp(-r*r/(2.0*sigma*sigma)) + + data_y = out_ws.dataY(j) + data_y[i] += int(i_q*scale) + data_e = out_ws.dataE(j) + data_e[i] = math.sqrt(data_e[i]*data_e[i]+i_q*i_q*scale*scale) + + self.setProperty("OutputWorkspace", out_ws) + self.setProperty("MonitorWorkspace", mon_ws) + + def _sphere_model(self, q, scale): + """ + Return I(q) for a sphere model + @param q: q-value + @param scale: normalization factor to give I(q) + """ + radius = self.getProperty("SphereRadius").value + bck = self.getProperty("Background").value + qr = q*radius + bes = 3.0*(math.sin(qr)-qr*math.cos(qr))/(qr*qr*qr) if not qr == 0.0 else 1.0 + vol = 4.0*math.pi/3.0*radius*radius*radius + f2 = vol*bes*bes*1.0e-6 + return(scale*f2+bck) + +############################################################################################# +AlgorithmFactory.subscribe(USANSSimulation()) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Moments.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Moments.py deleted file mode 100644 index 1d0c4bba59b3..000000000000 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/Moments.py +++ /dev/null @@ -1,60 +0,0 @@ -"""*WIKI* - -Calculates the n^{th} moment M_n of S(Q,w) where M_n is the integral of w^n*S(Q,w) over all w for n=0 to 4. - -*WIKI*""" -# Algorithm to start Bayes programs -from mantid.simpleapi import * -from mantid.api import PythonAlgorithm, AlgorithmFactory -from mantid.kernel import StringListValidator, StringMandatoryValidator -from mantid import config -import os.path - -class Moments(PythonAlgorithm): - - def category(self): - return "Workflow\\MIDAS;PythonAlgorithms" - - def PyInit(self): - self.setOptionalMessage("Calculates the nth moment of S(q,w)") - self.setWikiSummary("Calculates the nth moment of S(q,w)") - - self.declareProperty(name='InputType',defaultValue='File',validator=StringListValidator(['File','Workspace']), doc='Origin of data input - File or Workspace') - self.declareProperty(name='Instrument',defaultValue='iris',validator=StringListValidator(['irs','iris','osi','osiris']), doc='Instrument') - self.declareProperty(name='Analyser',defaultValue='graphite002',validator=StringListValidator(['graphite002','graphite004']), doc='Analyser & reflection') - self.declareProperty(name='SamNumber',defaultValue='',validator=StringMandatoryValidator(), doc='Sample run number') - self.declareProperty(name='EnergyMin', defaultValue=-0.5, doc='Minimum energy for fit. Default=-0.5') - self.declareProperty(name='EnergyMax', defaultValue=0.5, doc='Maximum energy for fit. Default=0.5') - self.declareProperty(name='MultiplyBy', defaultValue=1.0, doc='Scale factor to multiply S(Q,w). Default=1.0') - self.declareProperty('Verbose',defaultValue=True, doc='Switch Verbose Off/On') - self.declareProperty('Plot',defaultValue=True, doc='Switch Plot Off/On') - self.declareProperty('Save',defaultValue=False, doc='Switch Save result to nxs file Off/On') - - def PyExec(self): - - self.log().information('Moments calculation') - inType = self.getPropertyValue('InputType') - prefix = self.getPropertyValue('Instrument') - ana = self.getPropertyValue('Analyser') - sn = self.getPropertyValue('SamNumber') - sam = prefix+sn+'_'+ana+'_sqw' - emin = self.getPropertyValue('EnergyMin') - emax = self.getPropertyValue('EnergyMax') - erange = [float(emin), float(emax)] - factor = self.getPropertyValue('MultiplyBy') - factor = float(factor) - - verbOp = self.getProperty('Verbose').value - plotOp = self.getProperty('Plot').value - saveOp = self.getProperty('Save').value - workdir = config['defaultsave.directory'] - if inType == 'File': - spath = os.path.join(workdir, sam+'.nxs') # path name for sample nxs file - self.log().notice('Input from File : '+spath) - LoadNexus(Filename=spath, OutputWorkspace=sam) - else: - self.log().notice('Input from Workspace : '+sam) - from IndirectEnergyConversion import SqwMoments - SqwMoments(sam,erange,factor,verbOp,plotOp,saveOp) - -AlgorithmFactory.subscribe(Moments) # Register algorithm with Mantid diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SofQWMoments.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SofQWMoments.py new file mode 100644 index 000000000000..5f38ee345a27 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/SofQWMoments.py @@ -0,0 +1,139 @@ +"""*WIKI* + +Calculates the n^{th} moment M_n of y(Q,w) where M_n is the integral of w^n*y(Q,w) over all w for n=0 to 4. + +*WIKI*""" +# Algorithm to start Bayes programs +from mantid.simpleapi import * +from mantid.api import PythonAlgorithm, AlgorithmFactory, MatrixWorkspaceProperty, WorkspaceGroupProperty +from mantid.kernel import Direction +from mantid import logger + +import os.path +import numpy as np + +class SofQWMoments(PythonAlgorithm): + + def category(self): + return "Workflow\\MIDAS;PythonAlgorithms" + + def PyInit(self): + self.setOptionalMessage("Calculates the nth moment of y(q,w)") + self.setWikiSummary("Calculates the nth moment of y(q,w)") + + self.declareProperty(MatrixWorkspaceProperty("Sample", "", Direction.Input), doc="Sample to use.") + self.declareProperty(name='EnergyMin', defaultValue=-0.5, doc='Minimum energy for fit. Default=-0.5') + self.declareProperty(name='EnergyMax', defaultValue=0.5, doc='Maximum energy for fit. Default=0.5') + self.declareProperty(name='Scale', defaultValue=1.0, doc='Scale factor to multiply y(Q,w). Default=1.0') + self.declareProperty(name='Verbose', defaultValue=False, doc='Switch Verbose Off/On') + self.declareProperty(name='Plot', defaultValue=False, doc='Switch Plot Off/On') + self.declareProperty(name='Save', defaultValue=False, doc='Switch Save result to nxs file Off/On') + + self.declareProperty(WorkspaceGroupProperty("OutputWorkspace", "", Direction.Output), doc="group_workspace workspace that includes all calculated moments.") + + def PyExec(self): + from IndirectCommon import CheckHistZero, CheckElimits, StartTime, EndTime, getDefaultWorkingDirectory + + sample_workspace = self.getPropertyValue('Sample') + output_workspace = self.getPropertyValue('OutputWorkspace') + factor = self.getProperty('Scale').value + emin = self.getProperty('EnergyMin').value + emax = self.getProperty('EnergyMax').value + erange = [emin, emax] + + Verbose = self.getProperty('Verbose').value + Plot = self.getProperty('Plot').value + Save = self.getProperty('Save').value + + StartTime('SofQWMoments') + num_spectra,num_w = CheckHistZero(sample_workspace) + + if Verbose: + text = 'Sample %s has %d Q values & %d w values' % (sample_workspace, num_spectra, num_w) + logger.notice(text) + + x = np.asarray(mtd[sample_workspace].readX(0)) + CheckElimits(erange,x) + + samWS = '__temp_sqw_moments_cropped' + CropWorkspace(InputWorkspace=sample_workspace, OutputWorkspace=samWS, XMin=erange[0], XMax=erange[1]) + + if Verbose: + logger.notice('Energy range is %f to %f' % (erange[0], erange[1])) + + if factor > 0.0: + Scale(InputWorkspace=samWS, OutputWorkspace=samWS, Factor=factor, Operation='Multiply') + if Verbose: + logger.notice('y(q,w) scaled by %f' % factor) + + #calculate delta x + ConvertToPointData(InputWorkspace=samWS, OutputWorkspace=samWS) + x = np.asarray(mtd[samWS].readX(0)) + x_workspace = CreateWorkspace(OutputWorkspace="__temp_sqw_moments_x", DataX=x, DataY=x, UnitX="DeltaE") + + #calculate moments + m0 = output_workspace + '_M0' + m1 = output_workspace + '_M1' + m2 = output_workspace + '_M2' + m3 = output_workspace + '_M3' + m4 = output_workspace + '_M4' + + Multiply(x_workspace, samWS, OutputWorkspace=m1) + Multiply(x_workspace, m1, OutputWorkspace=m2) + Multiply(x_workspace, m2, OutputWorkspace=m3) + Multiply(x_workspace, m3, OutputWorkspace=m4) + DeleteWorkspace(m3) + + ConvertToHistogram(InputWorkspace=samWS, OutputWorkspace=samWS) + Integration(samWS, OutputWorkspace=m0) + + moments = [m1, m2, m4] + for moment_ws in moments: + ConvertToHistogram(InputWorkspace=moment_ws, OutputWorkspace=moment_ws) + Integration(moment_ws, OutputWorkspace=moment_ws) + Divide(moment_ws, m0, OutputWorkspace=moment_ws) + + DeleteWorkspace(samWS) + DeleteWorkspace(x_workspace) + + #create output workspace + extensions = ['_M0', '_M1', '_M2', '_M4'] + for ext in extensions: + ws_name = output_workspace+ext + Transpose(InputWorkspace=ws_name, OutputWorkspace=ws_name) + ConvertToHistogram(InputWorkspace=ws_name, OutputWorkspace=ws_name) + ConvertUnits(InputWorkspace=ws_name, OutputWorkspace=ws_name, Target='MomentumTransfer', EMode='Indirect') + + CopyLogs(InputWorkspace=sample_workspace, OutputWorkspace=ws_name) + AddSampleLog(Workspace=ws_name, LogName="energy_min", LogType="Number", LogText=str(emin)) + AddSampleLog(Workspace=ws_name, LogName="energy_max", LogType="Number", LogText=str(emax)) + AddSampleLog(Workspace=ws_name, LogName="scale_factor", LogType="Number", LogText=str(factor)) + + #group ouput workspace + group_workspaces = ','.join([output_workspace+ext for ext in extensions]) + GroupWorkspaces(InputWorkspaces=group_workspaces,OutputWorkspace=output_workspace) + + if Save: + workdir = getDefaultWorkingDirectory() + opath = os.path.join(workdir,output_workspace+'.nxs') + SaveNexusProcessed(InputWorkspace=output_workspace, Filename=opath) + + if Verbose: + logger.notice('Output file : ' + opath) + + if Plot: + self._plot_moments(output_workspace) + + self.setProperty("OutputWorkspace", output_workspace) + + EndTime('SofQWMoments') + + def _plot_moments(self, inputWS): + from IndirectImport import import_mantidplot + mp = import_mantidplot() + + mp.plotSpectrum(inputWS+'_M0',0) + mp.plotSpectrum([inputWS+'_M2',inputWS+'_M4'],0) + +# Register algorithm with Mantid +AlgorithmFactory.subscribe(SofQWMoments) 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 98c299103581..2f8b919c9c1a 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmFactoryTest.py @@ -1,6 +1,14 @@ import unittest +import testhelpers -from mantid.api import AlgorithmFactory +from mantid.api import AlgorithmFactory, PythonAlgorithm + +class IsAnAlgorithm(PythonAlgorithm): + def PyInit(self): + pass + +class NotAnAlgorithm(object): + pass class AlgorithmFactoryTest(unittest.TestCase): @@ -15,5 +23,12 @@ def test_get_registered_algs_returns_dictionary_of_known_algorithms(self): self.assertEquals( len(all_algs['LoadRaw']), 3 ) self.assertEquals( all_algs['LoadRaw'], [1,2,3] ) + def test_algorithm_subscription_with_valid_object_succeeds(self): + testhelpers.assertRaisesNothing(self, AlgorithmFactory.subscribe, IsAnAlgorithm) + + def test_algorithm_registration_with_invalid_object_throws(self): + self.assertRaises(ValueError, AlgorithmFactory.subscribe, NotAnAlgorithm) + + if __name__ == '__main__': unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmManagerTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmManagerTest.py index 382312027e31..761ee95d540b 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmManagerTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmManagerTest.py @@ -1,16 +1,8 @@ import unittest import testhelpers -from mantid.api import AlgorithmManager -from mantid.api import (IAlgorithm, Algorithm, AlgorithmProxy, PythonAlgorithm, - AlgorithmFactory) -import sys +from mantid.api import (AlgorithmManager, IAlgorithm, Algorithm, AlgorithmProxy) -class IsAnAlgorithm(PythonAlgorithm): - def PyInit(self): - pass - -class NotAnAlgorithm(object): - pass +import sys class AlgorithmManagerTest(unittest.TestCase): @@ -36,17 +28,71 @@ def test_managed_cppalg_isinstance_of_AlgorithmProxy(self): def test_unmanaged_cppalg_isinstance_of_Algorithm(self): alg = AlgorithmManager.createUnmanaged("ConvertUnits") self.assertTrue(isinstance(alg, Algorithm)) + + def test_size_reports_number_of_managed_algorithms(self): + old_size = AlgorithmManager.size() + new_alg = AlgorithmManager.create("ConvertUnits") + new_size = AlgorithmManager.size() + self.assertTrue(new_size == old_size + 1) + + def test_getAlgorithm_returns_correct_instance(self): + returned_instance = AlgorithmManager.create("ConvertUnits") + id = returned_instance.getAlgorithmID() + mgr_instance = AlgorithmManager.getAlgorithm(id) + self.assertEquals(id, mgr_instance.getAlgorithmID()) - def test_pyalg_isinstance_of_Algorithm(self): - alg = IsAnAlgorithm() - self.assertTrue(isinstance(alg, Algorithm)) - self.assertTrue(isinstance(alg, IAlgorithm)) + def test_removeById_removes_correct_instance(self): + alg = AlgorithmManager.create("ConvertUnits") + alg2 = AlgorithmManager.create("ConvertUnits") + AlgorithmManager.removeById(alg.getAlgorithmID()) + self.assertEquals(None, AlgorithmManager.getAlgorithm(alg.getAlgorithmID())) + self.assertNotEqual(None, AlgorithmManager.getAlgorithm(alg2.getAlgorithmID())) + + def test_newestInstanceOf_returns_correct_instance(self): + alg = AlgorithmManager.create("ConvertUnits") + alg2 = AlgorithmManager.create("ConvertUnits") + alg3 = AlgorithmManager.newestInstanceOf("ConvertUnits") + + self.assertEquals(alg2.getAlgorithmID(), alg3.getAlgorithmID()) + self.assertNotEqual(alg.getAlgorithmID(), alg3.getAlgorithmID()) - def test_algorithm_subscription_with_valid_object_succeeds(self): - testhelpers.assertRaisesNothing(self, AlgorithmFactory.subscribe, IsAnAlgorithm) + def test_runningInstancesOf_returns_python_list(self): + algs = AlgorithmManager.runningInstancesOf("ConvertUnits") + self.assertTrue(isinstance(algs, list)) + + import threading + class AlgThread(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.algorithm = AlgorithmManager.create("Pause") + def run(self): + self.algorithm.initialize() + self.algorithm.setProperty("Duration", -1.0) #forever + self.algorithm.execute() + # end class + pause_thread = AlgThread() + try: + pause_thread.start() + while not pause_thread.algorithm.isRunning(): + pass + # should now be running + algs = AlgorithmManager.runningInstancesOf("Pause") + self.assertTrue(isinstance(algs, list)) + self.assertEquals(1, len(algs)) + except: + pause_thread.algorithm.cancel() + pause_thread.join() + raise + finally: + pause_thread.algorithm.cancel() + pause_thread.join() + + + def test_clear_removes_all_managed_algorithms(self): + AlgorithmManager.clear() + new_size = AlgorithmManager.size() + self.assertEquals(0, new_size) - def test_algorithm_registration_with_invalid_object_throws(self): - self.assertRaises(ValueError, AlgorithmFactory.subscribe, NotAnAlgorithm) if __name__ == '__main__': unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmTest.py index df1cee49bbb8..7a7bdaafa396 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AlgorithmTest.py @@ -1,7 +1,9 @@ import unittest -from mantid.api import AlgorithmManager +from mantid.api import AlgorithmID, AlgorithmManager from testhelpers import run_algorithm +########################################################### + class AlgorithmTest(unittest.TestCase): _load = None @@ -39,6 +41,7 @@ def test_execute_succeeds_with_valid_props(self): data = [1.0,2.0,3.0] alg = run_algorithm('CreateWorkspace',DataX=data,DataY=data,NSpec=1,UnitX='Wavelength',child=True) self.assertEquals(alg.isExecuted(), True) + self.assertEquals(alg.isRunning(), False) self.assertEquals(alg.getProperty('NSpec').value, 1) self.assertEquals(type(alg.getProperty('NSpec').value), int) self.assertEquals(alg.getProperty('NSpec').name, 'NSpec') @@ -47,7 +50,28 @@ def test_execute_succeeds_with_valid_props(self): as_str = str(alg) self.assertEquals(as_str, "CreateWorkspace.1(OutputWorkspace=UNUSED_NAME_FOR_CHILD,DataX=1,2,3,DataY=1,2,3,UnitX=Wavelength)") - + + def test_getAlgorithmID_returns_AlgorithmID_object(self): + alg = AlgorithmManager.createUnmanaged('Load') + self.assertEquals(AlgorithmID, type(alg.getAlgorithmID())) + + def test_AlgorithmID_compares_by_value(self): + alg = AlgorithmManager.createUnmanaged('Load') + id = alg.getAlgorithmID() + self.assertEquals(id, id) # equals itself + alg2 = AlgorithmManager.createUnmanaged('Load') + id2 = alg2.getAlgorithmID() + self.assertNotEqual(id2, id) + + def test_cancel_does_nothing_to_executed_algorithm(self): + data = [1.0] + alg = run_algorithm('CreateWorkspace',DataX=data,DataY=data,NSpec=1,UnitX='Wavelength',child=True) + self.assertEquals(alg.isExecuted(), True) + self.assertEquals(alg.isRunning(), False) + alg.cancel() + self.assertEquals(alg.isExecuted(), True) + self.assertEquals(alg.isRunning(), False) + def test_createChildAlgorithm_creates_new_algorithm_that_is_set_as_child(self): parent_alg = AlgorithmManager.createUnmanaged('Load') child_alg = parent_alg.createChildAlgorithm('Rebin') diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/PythonAlgorithmTraitsTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/PythonAlgorithmTraitsTest.py index 4a134254f3df..9e349e538b0c 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/PythonAlgorithmTraitsTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/PythonAlgorithmTraitsTest.py @@ -4,6 +4,8 @@ import unittest import testhelpers +import types + from mantid.kernel import Direction from mantid.api import (PythonAlgorithm, AlgorithmProxy, Algorithm, IAlgorithm, AlgorithmManager, AlgorithmFactory) @@ -25,12 +27,41 @@ def version(self): def category(self): return "BestAlgorithms" + def isRunning(self): + return True + def PyInit(self): pass def PyExec(self): pass +class TestPyAlgIsRunningReturnsNonBool(PythonAlgorithm): + + def isRunning(self): + return 1 + + def PyInit(self): + pass + + def PyExec(self): + pass + +class CancellableAlg(PythonAlgorithm): + + is_running = True + + def PyInit(self): + pass + + def PyExec(self): + pass + + def isRunning(self): + return self.is_running + + def cancel(self): + self.is_running = False ############################################################################### @@ -43,6 +74,8 @@ def setUp(self): self.__class__._registered = True AlgorithmFactory.subscribe(TestPyAlgDefaultAttrs) AlgorithmFactory.subscribe(TestPyAlgOverriddenAttrs) + AlgorithmFactory.subscribe(TestPyAlgIsRunningReturnsNonBool) + AlgorithmFactory.subscribe(CancellableAlg) def test_managed_alg_is_descendent_of_AlgorithmProxy(self): alg = AlgorithmManager.create("TestPyAlgDefaultAttrs") @@ -63,6 +96,8 @@ def test_alg_with_default_attrs(self): self.assertEquals(alg.name(), "TestPyAlgDefaultAttrs") self.assertEquals(alg.version(), 1) self.assertEquals(alg.category(), "PythonAlgorithms") + self.assertEquals(alg.isRunning(), False) + testhelpers.assertRaisesNothing(self, alg.cancel) def test_alg_with_overridden_attrs(self): testhelpers.assertRaisesNothing(self,AlgorithmManager.createUnmanaged, "TestPyAlgOverriddenAttrs") @@ -71,5 +106,16 @@ def test_alg_with_overridden_attrs(self): self.assertEquals(alg.version(), 2) self.assertEquals(alg.category(), "BestAlgorithms") + def test_alg_can_be_cancelled(self): + alg = AlgorithmManager.createUnmanaged("CancellableAlg") + self.assertTrue(alg.isRunning()) + alg.cancel() + self.assertTrue(not alg.isRunning()) + + # --------------------------- Failure cases -------------------------------------------- + def test_isRunning_returning_non_bool_raises_error(self): + alg = AlgorithmManager.createUnmanaged("TestPyAlgIsRunningReturnsNonBool") + self.assertRaises(RuntimeError, alg.isRunning) + if __name__ == '__main__': unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/GetEiT0atSNSTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/GetEiT0atSNSTest.py index a186eec6f676..0f622dd90880 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/GetEiT0atSNSTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/GetEiT0atSNSTest.py @@ -18,7 +18,7 @@ def testGETS(self): try: res=GetEiT0atSNS(w,0.1) except Exception as e: - s="Could not get Ei, and this is not a white beam run\nNo peak found for the monitor1" + s="Could not get Ei, and this is not a white beam run\nNo peak found for the monitor with spectra num: 2" self.assertEquals(find(e.message,s),0) DeleteWorkspace(w) diff --git a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp index 584dc88b7a0c..0275d3f4ba3d 100644 --- a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp +++ b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp @@ -151,7 +151,7 @@ DataObjects::Workspace2D_sptr PoldiAutoCorrelationCore::calculate(DataObjects::W std::vector qValues(dCount); PARALLEL_FOR_NO_WSP_CHECK() - for(int i = 0; i < static_cast(dCount); --i) { + for(int i = 0; i < static_cast(dCount); ++i) { qValues[dCount - i - 1] = (2.0 * M_PI / dValues[i]); } diff --git a/Code/Mantid/Framework/SINQ/src/SINQHMListener.cpp b/Code/Mantid/Framework/SINQ/src/SINQHMListener.cpp index 72a2aa3ec5b6..830745408ead 100644 --- a/Code/Mantid/Framework/SINQ/src/SINQHMListener.cpp +++ b/Code/Mantid/Framework/SINQ/src/SINQHMListener.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsAbsoluteUnitsReductionWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsAbsoluteUnitsReductionWorkflow.xml new file mode 100644 index 000000000000..3af1358267da --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsAbsoluteUnitsReductionWorkflow.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsConvertToEnergyTransferWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsConvertToEnergyTransferWorkflow.xml new file mode 100644 index 000000000000..bfaaa8eaea64 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsConvertToEnergyTransferWorkflow.xml @@ -0,0 +1 @@ +7V1bk6JIsP41EzH70AbI/XGnL7Mde3p3YrrP7tmnE7SiTYwNBupc9tdvIpVYRaVXoIDq8cFQRNAvs7LydnlnXb9+/5iFy5eHdBot3o2N6fd31s278dg3DHjOD/yoHJhn8bQ4ZLIDm3garYRD6zRdrOOleHCSJkk0WQvHZulCvNgynEfSgcdJuJCP/h1P1y/sqOkGuw9+i+L5C97HdeBw/slq/QMvMo1m4WaxvtoeYh+/hnix7f+0bgGbLE3hMvmr1+/X0SLHB/97Acbdnk/LX5lFCfshR77gOsVXvoaLDfuV0s+OkumvWZZ+g3dJmsDBD9H3eP1/8NYYOezdP/DOZK8/RVn8Gq2jLD8jP5assx/c6fnb/PzyM+kLU8Ce3T/N1i/pPE3CxW15dPsD85P2/mt2aJVusgk7K/AZj4TZPMLTONCBIaMUfkX2A07KokW4jr+KNwgZX83L88qvfkpjuPXYYFzsOubIcwx8mG5xAcbStuONrGBse5Zp+mMPfxhevvjR7Io87So38QxjNN7dxGCUxHVjuyPX8Jyx6/umNzZs8SYFCtJNgM5h/v/xtGV+wurAH/UYNuyujuEd/M0O48dLz/fsgj33YmKy9UifDy+Kf4jvOKLvDm3XCL1e2OIQVgsQ1/oeAts+hq/LnDuNv9Psy2oZAudVl9LqJVzmL1+/z3PpN5ot0m+TlzBbj6bhOnwOV/nqmsWLxXW6SPPlANe+g8f1NRxfrbP0S8R9UtC9/AQFE/7IKFtHDJd9S0TmfPyC54zGdrB7FHRCXE13tGM8eLBbfuNEI1LuhZOKNjtGrSSORgdJYB0iwUO4+qIHARxjxMPvMCGB+I+DAISpMtCZ9KBB/5ilm2WczPUAHq4tIC/KbtXAU9tzCfx9so4AzXU0hVNuYAOdrAGg3edw9K8wCafx5lUP2oyDw4vC8inaWARtnAZowzhjz2bwfvkSvxvDRYzbX4a8D1TkUGUfsAPrVMibWA7s7hzk9zN+QTzeP76z7s6BO5rEqzhNZLhn24dqBq8InyrcVuAQcHstMThbXhzaf6SHrIPJIlyt4okCAyGZ3gG1tpe8yBhgsPK2wHY117AETgWVKagcqA9gE8bLRXGV09h2maWTaAW/osq119e5mFC9ZdrOoS3THpNi2WxJRuB1OYT/AT/BWXyLnLrlwpKHGzVsV9H8FU7aWbXtsPWW3RSwtcmucaIjoRNRIRIgWjyn3wT48wPwQb4WYnD9XOhnaF60XGSaW+ZBPdb2ceNuyjY2DxvHW1/a2LgLK0qqBmqp7fmH5R+lIwXsNk1v2iZlIJ+1EM+TfdtlVS7D3apsfM9G/upEuskG8HUWgeX1CHbvIvorPzy9hJP7tZHbljni+LjKyJZLKvs+A6fxjfw83/RwtE/kJtEVrYqVZbN1lcvmqxmTzCfz7gp+//r/c1jrC2G4RpqscWvO30/D1Qs4NkqQa0po+5CEtkxSQrOtnOdrNGxrUUC2YjXhawarwNdbXlfB17K1ejNffY5ew+Vg5bHpH3EHWK5Sy0q2XTVhXCI2uIVaAd+i5/iyCGwXhupFEDOtVBANW9RVQFzbNm0J5b22aTOYU2qGMsxla/Am/goZG9oKY9CeVQpjMhDapo9LlZ3HMOS5tvhrKriWCnTqsMPh/+hGFsiG3GM6+/QS396vbmJYqfHzZp0HYXZeofePf366vb85J3LWpDnSgLQ4HKo0QJhwuTtkAgX7StMOIiJueZ1mGQSPf49/h2jaQAG3RQuvAnhg2MfwxkTDxgW1bJh83vC8ztDnjmwJMeQ4pglxygN7pe9DEsVBavgEMTDMWYsYsglzGfMPSjcJfAgbH+b+ttQUdJhop6agGBX0FFU7qiVbNGfHOHurqhDGuDJHvyWbLZ+j5xjEtaZWiwGx+65EQ+1IVV85mIgBF4ylgoObjZqg66NRgXs8xb+paDxlTaojhaxp34OQ3sXEtzaOzooeyI5j4oXS9NwmpIuuURbcogSWVpW9ZtUNAbTlsK4tsylBoQpV3E2F9IJ0OfyEAqmMoSoePPCZdqN92LIKfZ0m+b99SkWn1ECxhwSvmtCjKtE49LKSfb710nlIpikVBbUEXvIUzKlC8sg6+Lk53gokeisBSQr2uuWgJ8M+gDiDkmxZlMKdRHvsASSYqaECE+rdUEFW1HsvghqrSqecXbXt08vyxQ0xYiWmyEG5OqEt7CvDPnwt07Ao1WPfxcCjcdiDdehqtbPabdngEUrOHv8YdsUZVMjzrQpQDSzBNaF2hwOXYa+g+AyvIevn/5vEBSMPUi33IPZ1AHDIpj4CeGsWkSNbRL9F1tPmObqdzeJJHCWT4daoeRAC47tlVGGvyDcKdiIduBHYZWvoLTC64YqeQZWMLhs9WD2/43QICw8WehcK4esxO4YwGodeNnzOrikeaDImERQqGFGBjo06Ux9rYtV7XEhSqDJ3MDFJu7gE7mMCqqr8WI6upQmolAmoqnJTYRyOQ/Xv8Gu0iJI57BR9qBTD7aTObhlApfQhRQVaoBzeLdsqFHOpimodSnmRrzoRwC6l/S3W4e1bYWizkn0pMzSo5rzHxW+Lv2t7wfvK30S1kzqhTfWlqqC6iLdVZFyNbTt9EUTPHBa+llmpnvCxXDzjeq7IiDIfmpW0b/Tp10KQKCUtu6sZuUMk7+rF+UQMlkNMhYsBPvipH8JFPAef380EsMsZ7QOqsL+yD17j6XSr4zbi1PMO2H9V3Anzr61ceGyXezKy1ST5hgLyF7haG65INzHsgSnxY/NYOB4WAxWQZ8u9Vlu1uknafdWekd86SdLG3ri9F8RQaiT64i6SxC0IYk/3bGxUFLBdMaRLHWmr25ZP1JO1Yi280Dni/FZoiLFI1wuEjjdMXihBXNZ+oWHFpyz6VAB4A02uhgs7GM08rJ4ocVwIEB+BvS0PtKdrVyEUlkLnOVV1M94JRscwUSVMuQJpFajqmsOOsk9AVVUwxKPMO60cQJY1FsSrI86GcCHH4LD0hQkVvB5i4wWa9gBh8Yd2HiDksU4Y3JcNjyf4e/fJNFp+CCdf5tCwP5k+bp4HW+wvDqewK8X+dsDYitcnHLCeeZZuR7vwibY3EN8u3RhP93lX/hz6oVd9BZYBoZFivgyuWsQfO0IeKfNqpEe5rm1wcBHzEqTgLhUSpIE0jZ6qHrhCBcmsqkmhLxsfuWS+2opm+Gv5D98Ji52sLmTGOoMWndp4QMEIHHm8FBd9IQ5WH/FC3BUjV+hjatof6svWzBtOl6FWTMHIKlbMAEwgJTUaKDq6kVuyyaTf4BVeo8ECLSaMQHcXNE51afAYe+eQ/580nGLU7D6ZyfvycJyE5sjm1UjRSWhD74COnITYnL9HYzEvExpE/EuZEhlQ0ZtFOoG2+ci+58QV+mWBwkwbIZBTibHDfE9xQiLTKFQEFgLZJCpGUwLq1+ECtq0oCV/PaSrQs9aK5ggy2EvoLRQCKDagKfYx6KFZIJ8ghWG4xilRN8FJgXF6ovLykmbxv+CmvHgsDqVEqopOBHVjPhrRgYhnqKODbFe9nVJf1KEb3YsvKvUtM1NQu2V02VvOi67+C8+3Wb7v/grfyoBs8fzaNbyornNst86n91w9lw6Wq3B1FX0F8nWlkbQ9AAWak/MGDLpNS1XbF1RtxqoV14uQmkJsmU1EhPDWvIcs95mXpuZtQaUhG5uuqKHg6LxSdZSjF5jHJjRJ80aebwe2C8vHcQKrMuH9stGJst2jVbV7Bfmq0q6wvN3Ee2vbfwqSiMVstgqbQxXCEZHTlnUPLSM06HrUlGOxXPTCbICCPVXMbcJQrI69jElsC1ZXAu0A7J7LrBhq0q06WIkJCuFisoH7RHfwxMftBiq8gwBcs7J0RnXRsUjdQ3CxMJCaF96yNs82zrssfdVi6wwCMXtWdHAFhlgqQsRJoak38f3mSSEHJ4oEFw2G+lp2JVW/kjiO3ltBYWlr8B4x0/xnFHSnq6gbck40jd3OAc7F/tYyHX7PXseyRz6XmFFJy8A2D4JvYCyWG7bkTofGNUT6zPNTOvscJjmnAZg9cd800L4XrCdeyotksKC+grCtVNRwmsSEcY4Kt2dpPcOigZhGbVeKWAgLtj0a6DqorvSLiBJeVSd2U9+h42i1iMCqGnNb6kYcsA9xshluZaGL7SuweNMTiyYIkdzaYOZTJtzuxxW47DVOwrwIvydNSSG7Auv0duNVxdxPYl471R6iIqIxs7Me2gMYXKREG8dGioJI2UfbFkTKzy7qYkCiKzrIe2YfPbhKSIFCSCBFYTYqIYXsHNMvfArli7xnRvSO+ZY3cjGj1BsbslauKphKDH7VRJVEXU6UN+pUSdnt+EaGlpTruyMl/pRprgPSM12xtSMa1ehnB6FAeGC60DiJea9vc3stoz/CAijYUnUaXYDeHeQX5hptKm3NVD4gtb9pq6XTsSO3ECoEqkhxSaOClvJWaehrq7QXLTkf2yFjNII1vWluycmmDOs4ZryHHwlnQvtG2Nfy8PIvwx3NYEI2KLe1VUI846OOrHGlT1lbAR9igm7Pl12DErDu4qJWz6FwBjjYiHAGXr4QCeyKB5K5fQgf8rwl3sTBtpd42UKoSJc9WzDgTMmyBUhxn+YEg2zMadEfz3dFnhBLMMGK7qohoUmMGh5288cjUENX3q7CB8RA1p6b0yq9d8XSV6FlEtNYdWtN74udycS8QscS895k310lsa3sMtt0GQpk0L1Fee/ablftUMuEUd51/ec5bup+55IE0GOZb3dTaclHpFVBrQqVgNg4q1OTFjVLZ/YgkYdXSsVcTth6FeYvE/P+3o5Nc4profakjAtdC6I3D6zgZi0IYuqgXgVfviP2vBDjcp4h6reyN729ei9i/N0bdZ/TGRuqRtOYxPC7bXj6rCKBnhQIuFARvd+J5kFy6GFzjgoeoSOtFsjuAIJFl3Evemeb3S5OB1bxzq0OWFyXHYkFYiTbG5XPWGAicnhdB8RFChEEx0UThbXwaUwhOmVQ2SCbf5e2g0DFwqOgZDnVVnd6CyylvqjzzxGD4XTZWUnHp7K6OmIunC7AEh0YFYoCbSe7lQ5acadUNWIBWpdq3LWCzDKsnWR1OrayOnj79LkXnmBcTk16gitxwMA6Yjg6YoAdU5Ma9wsTA8o0USOooU4KdztL1s96n7+sNOCqbns8odqzoxGdlf7jcoeVjoYjwxjaE2ZYGCfPruhkPrIVVOsLYd6K2CBRYTE3MZBMr8iAB+0l+X7L1aCz2VWfd9MbgOGhxvNETSyr73k6mRD1J8H11rdKFUsVaCsBVjZUHlJIYUkz83EZTe676tbRRIcmcWp1NapfGTGrcMy9SYyBY6CPNQB9f/ElICr23lcKumw2fozWt/GghyjzWKNbGStdqQ5kbW2UxES4+2QS59rebRJl8x8fNzlwg50pIea9VSoBYYa4wNWEhgKZi0KtYEvzJU1igpwe+yTV9qdY0Up2ybqxqL52Si0XblfADiAWpSrbjRrpqZIUtaNXGpGiY3Ejm53XL3n3vA9x8udstoKfpKnSApP2xL1UZR4gMY/pIf0Kg7EBhk3enkEb1NHFjO0isexODcza9tAj5+kpM+WJ8Uma4IoLs5OpVCYxH0ibWC41dYrBrQRaeaO7i7PVmnlD8pjBd20Cu5YYQii5Gre+Sr9YHDIqOEfYim46mAvzbX86ukU3kbgi6gqbi1IsTTborHSfMVI3lWI5JuY59byDDNW2pDHSozTqRhiOiZFPV7w0/BSFX7QRhia41ITyRVEYmq5z1KfWnjCUPcVXT/9G2TmjtPuNPnTzEJKExHQC07XFnYiY39Ie+Nq2Lid3FmVq7JiY9rSdy/9zm0diMAmshBiyrZYPT/xJix0tVHnbxsTEqK6n+SvBvVQ4uhJI5zmcNcK9441ANrqLGO1TFiarWZRtB7VwTaHfQ3r1Od3sem6Gg529P0XBs8U6dGp6mtgihf0AwU0q6k+NJFaCyqVpvnXJkPx6KDo3qlgOxNAuncoJLNMfWVw9AdbIlSk5DjnESH1BAUQcdGVwqmzXaonB4W2WpnCTnVMo59eHdBrlZ/wH \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsDiagnoseWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsDiagnoseWorkflow.xml new file mode 100644 index 000000000000..598335474418 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsDiagnoseWorkflow.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsPreprocessDataWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsPreprocessDataWorkflow.xml new file mode 100644 index 000000000000..beec00f41151 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsPreprocessDataWorkflow.xml @@ -0,0 +1 @@ +7Vvfc9o4EP5rmOk9hLEtfuXxoEnLzLXNXDrX69ONagvw1FiMLBK4v75rs7JlyxATO9i5HA8MrGwhffvttyvJ9Mhsvfsg6Gb1iXss6DmWt+uR9z3HmVgWvMeGfcGwFL53MNlo2Poei3ImyXkg/U3e6PIwZK7M2RY8yHe2oUtmGO5dGpjWb74nVzg4Z5TZPzJ/uVI/Y4+uDy2R3Ks+PLag20BeJSZoi5vXVPWVTJPcADSCc+gm/rTezVgQw6OmfsDi9khrOkjBQhzI6RvI4YYHGmxxjJ+5WPfiWZEd7ZHp1/2GGfOIVhSs5P16t4xd2F8E/NFdUSH7HnP9yOch3Lnwg2DGAy6Se8gieYE9koL/ZFqLlbzSFoUu4qPPBaf3wIRkSJfEhHP7wPiaSbGHS7B1SEh/eOg/eWEHyCz7Gpn1qDkUTSvNl8pGkVbL9HcyZOEDglsO9NAA+hsXP6MNdQHeFO1393S9AZQdC8DJzH/RkHr+dv3bOZ6gkv6gETQWPXELr9nswp4YDBBExL4EetsuwX7YAPYTA3sDRxZ6vwvBH+GbG9Ao8l1Age18+TdYrP4Qv32HbzZ+vmPCh6GwGLsYM8BG7LXL46/x9WmbeYN3C55RXXogNzggFvzgjzeZYZoYoCHG2wdNOuqQiG8FMEqnnKRiyfAqDPf4t046TbCASv8hL311XKBcm/NByu87wV0WRcyDKzSzFiGvlfZDe5ITIOwTgwBaLhcFthq8rvWhiW3boVCF2shjndoKtha4jU4tJFEa+BGb7j/x0Jexmlem8OYQDSaDZ7OYwxdmMJmcSqHEue5f6y+Tz4q7jfO5vHZB2GdbkUz6tcI+sk/CTqy+1qhaLwL7wID9OMlPa4mmJJmu1NcSLZFyIVd8yUMalGXTFRf+vzyUkE+bkSB0fAsSZJaXx0PgpFOUpF/eKflq6DkFT5lL2qt4cGFYseoM41T88nn2CTdUQVlB2pHkOzZg/vrl9k8aLtmXxSKCAVbPABFMSf4Tg92F0jFdnarVqkPyqbZE9KHazF2CWq3ngMEolzmsCUpHHSfgJsMzuX6u5OSYnhH/FNePLqi0FFCJ+8i2l1X95FYAi8Z3qQs23A9lpPV8Fxu0Ok0ld6SLSvaZCw89Zg5Nh1bNx2beD6Hculrz0L6KNsxtKdDI1KPRCpaOByItwJnK683sIPXJGEMkXbVNniq+LKyDc4E3yN+FVKoVd13PMc1sZKgI60bGccyMg+XvPJRJ4vkDpthWMJTw3yB7CeDHs5Da/Mz2TPP5A6sBnf1OS1kIg+64Yz7CAP6znnFIAdPueIacVx/UX5VULRHO34EtFgwF/XlSy5R6mBVE6wUD1ptNFQzE3G98s05HZeqe0wnm0cacbu6Fzhfalv78fn7fI7etnijWUt1CLUiGWIJpKjsaAvkMXR01sPdGzC1PzHD3UIBLsYWT2w5kN7VSqJXdinUG4qxwt0almawDi2Fi7sXVOWNRu6RV6/JE1CqdsZytYghg7kCxropVRrVsqZPKSrr/bHXjzLBmYTfpF2VmZMqM7dhlOqPO2WuBbS5xPvPOJe9nkVglqByJE3AvQWLzSQRkbkrbeegBcVrfSombG5f08TjeSzkm6YPiUWKJpMMeijM4T9LxR2q5zVxYfofnzl5U1LtbzJZGUFKYXCCClLr9v6hIi8EOLirQS00tKgZ1V5KXemrlbBeiOOVCKckRlwglc6n2ZkMJ83L3QmmAT4g1FkrmCvLNOr0k+Dqin+OGnW6uSOehC8/Oh3LK6Fo9NQUzhG2WFo/La1WXwzFWaeoB48JpeUk1iTC/+I7A4LxjutfzAPK5IaeIaDyS3Hy6g6/ZvygOMZP924Tc/AI= \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsProcessDetectorVanadiumWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsProcessDetectorVanadiumWorkflow.xml new file mode 100644 index 000000000000..acc21b754c9c --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsProcessDetectorVanadiumWorkflow.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsReductionWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsReductionWorkflow.xml new file mode 100644 index 000000000000..75f4e54c4631 --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsReductionWorkflow.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsRemapWorkflow.xml b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsRemapWorkflow.xml new file mode 100644 index 000000000000..52448c7d20cf --- /dev/null +++ b/Code/Mantid/Framework/WorkflowAlgorithms/doc/diagrams/DgsRemapWorkflow.xml @@ -0,0 +1 @@ +3ZrPcuI4EIefhqqdw6RsDGzmOCGQnUNmUzWHbE5Tii2MKsZySSIh8/RpiZYtsMjGAcy/A9gt2bS+bn6tBjrRcLa4EaSY3vKEZp1ukCw60XWn270MAnjWhtc1QypYsjSFaJizhMoVk+I8U6xYNcY8z2msVmwTnq3erCAprRl+xSSrW+9ZoqboXHdQ2f+hLJ3atwkH35YjUr3aeyR0QuaZ+mpMMKaHZ8TeyywzGgEawTncRh/NFkOaaTx26UsW4w2jpZOC5ujI+xegE88km6OPHb2iaEE60dWPvJgrGHVM91w8yYLEtLY2OSWFPpwtUh3Wi0nGX+IpEeoiIYo8EgmDVxOWZUOecWGuicbwGA7BLpXgT9QZCcyjHLHE0V13fbjkZyoUxRQyJlzvDeUzqsQrTMHRbh/zCfMrRETBSxXWMETb1AmpvY5gdqXlrSvAcICM/byjGu/RgsZzRf8tCi4ZvIqEigZwpYLn3+GRsO311tiG/TpbO8dlO9gB216N7S2RT07yjpmQ8H7jJrlLYyYZz+t8J+bRMt/IckK+XauNDt9LD15r2wYvRnJFKtY40jz5LgR/gbM4I1KyGCjQBVP/gUXnqD5+gOPgoo9nd1QwcAVyHqzaloNbejpO0afmCntSuyABmUYXJE1nMGlUma5o9mj80YwZqLm5TTKGWBqXNoVE8rkAkXM1Ej5oKcVZmGr6vd8Nm6AZUex5tYRsEwSsNp8OgiG2hyA4SP8nJB8hjip5FMT/9qrKNSw+VlzIBlpSCB5TCa6sS8lwqMW6ZSkJ18pg5CuDPqneRRm8PFOo/QDTBaH2LKw2oOJ+04F6I/i8OL9UbZWq3QmeH9b1ZG1VAULrboX1AXq5Eytmnv3FR+obFjO3vmEo2q9vYb0F/MlPYmfXcBvngW4/2wegXm8EnUblbqkTNDmvzjvqYQ+BgjOw/NvovMN6e9hQbcrM1llrc36nWW7EZMfdC+4KVtIek+8Aab9tE3miQcD97pEEYesmck9BaAgVS6YLFZP9AEzrbeJ+mDZDZMXUZYS5eABG9a7PqW/L7+rO7Lvm9Yrn3WLvreJtaAg3Ui5tfwGabmAmszyFQ0g6+uV8wuBtIPcVBhvytr6zM9pRim2lvVtriaeIHaxrKXOgrW+jPwG12jlMuWB/eK4+2B76SB9Mtb0/ER4t6UZtuBXI42gJPb8NnqZOeKi2tS+D0+q3czPm/McgGr0B \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsAbsoluteUnitsReduction.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsAbsoluteUnitsReduction.cpp index 5f1a1dd63877..c4b986eb299f 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsAbsoluteUnitsReduction.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsAbsoluteUnitsReduction.cpp @@ -1,8 +1,58 @@ /*WIKI* This algorithm is responsible for taking an absolute units sample and -converting it to an integrated value for that sample. A corresponding detector -vanadium can be used in conjunction with the data reduction. +converting it to an integrated value (one value for entire workspace) for that +sample. A corresponding detector vanadium can be used in conjunction with the +data reduction. The diagram below shows the workflow. The +AbsUnitsIncidentEnergy parameter needs to be passed via a property manager +since the absolute units sample may have been measured at an energy different +from the sample of interest. Parameters in italics are controlled by the +[[InstrumentParameterFile | instrument parameter file (IPF)]] unless provided +to the algorithm via a property manager. The mappings are given below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping +|- +| VanadiumMass || vanadium-mass +|- +| AbsUnitsMinimumEnergy || monovan-integr-min +|- +| AbsUnitsMaximumEnergy || monovan-integr-max +|} + +The last two parameters are used to create a single bin for the ''Rebin'' +algorithm. The dashed oval parameter, VanadiumRmm, is taken from the atomic +information for the molecular mass of Vanadium. The open circle represents +detector diagnostic parameters and they are detailed in the table below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| HighCounts || diag_huge || HighThreshold +|- +| LowCounts || diag_tiny || LowThreshold +|- +| AbsUnitsLowOutlier || monovan_lo_bound || LowOutlier +|- +| AbsUnitsHighOutlier || monovan_hi_bound || HighOutlier +|- +| AbsUnitsMedianTestLow || monovan_lo_frac || LowThresholdFraction +|- +| AbsUnitsMedianTestHigh || monovan_hi_frac || HighThresholdFraction +|- +| AbsUnitsErrorBarCriterion || diag_samp_sig || SignificanceTest +|} + +If a detector vanadium is used, the processed sample workspace is multiplied +by a factor containing the sample mass (SampleMass), sample molecular mass +(SampleRmm) and the cross-section (Scattering XSec) given by: +\frac{(\sigma^{V}_{incoherent}+\sigma^{V}_{coherent})\times10^{3}}{4\pi} +with the cross-section units of millibarns/steradian. + +=== Workflow === +[[File:DgsAbsoluteUnitsReductionWorkflow.png]] *WIKI*/ diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp index 4706ef2d8c07..3ed127c1d8f5 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp @@ -1,7 +1,35 @@ /*WIKI* This algorithm is responsible for making the conversion from time-of-flight to -energy transfer for direct geometry spectrometers. +energy transfer for direct geometry spectrometers. The diagram below shows the +workflow for the algorithm. The SNS instruments have a log called EnergyRequest +which allows the IncidentEnergyGuess parameter to be left blank. Also, SNS +instruments need to pass a monitor workspace to ''GetEi'' since they are +separate from the sample workspace. Parameters in italics are controlled by the +[[InstrumentParameterFile|instrument parameter file (IPF)]] unless provided to +the algorithm via a property manager. The mappings are given below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping +|- +| TibTofRangeStart || bkgd-range-min +|- +| TibTofRangeEnd || bkgd-range-max +|} + +Parameters in italics with dashed perimeters are only controllable by the IPF +name given. All underlined parameters are fixed and not controllable. +The EnergyTransferRange parameter takes the canonical Mantid notation of +(start, step, stop). However, it can be left blank and the following values +will be used +(-0.5E^{Guess}_{i}, 0.01E^{Guess}_{i}, 0.99E^{Guess}_{i}). + +The use of the SofPhiEIsDistribution parameter in the last Rebin call is used +to set the ''Rebin'' algorithm parameter PreserveEvents. + +=== Workflow === +[[File:DgsConvertToEnergyTransferWorkflow.png]] *WIKI*/ diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsDiagnose.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsDiagnose.cpp index 45c329463ac8..47393b4519f4 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsDiagnose.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsDiagnose.cpp @@ -1,7 +1,88 @@ /*WIKI* This algorithm is responsible for setting up the necessary workspaces to -hand off to the DetectorDiagnostic algorithm. +hand off to the [[DetectorDiagnostic]] algorithm. The diagram below shows the +manipulations done by this algorithm. Workspaces that have dashed lines are +optional. Parameters in italics are retrieved from the +[[InstrumentParameterFile|instrument parameter file (IPF)]] unless they are +provided to the algorithm via a property manager. The mappings for these +parameters are shown below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| RejectZeroBackground || diag_samp_zero || - +|- +| BackgroundCheck || check_background || - +|- +| PsdBleed || diag_bleed_test || - +|- +| BackgroundTofStart || bkgd-range-min || - +|- +| BackgroundTofEnd || bkgd-range-max || - +|- +| DetVanRatioVariation || diag_variation || DetVanRatioVariation +|} + +The open circles represent groups of parameters. They are detailed in the tables +below. All parameters given here act like italicized parameters. + +====Detectors Outside Limits Parameters==== +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| HighCounts || diag_huge || HighThreshold +|- +| LowCounts || diag_tiny || LowThreshold +|- +|} + +====Median Detector Test Parameters==== +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| HighOutlier || diag_van_out_hi || HighOutlier +|- +| LowOutlier || diag_van_out_lo || LowOutlier +|- +| MedianTestHigh || diag_van_hi || HighThresholdFraction +|- +| MedianTestLow || diag_van_lo || LowThresholdFraction +|- +| ErrorBarCriterion || diag_van_sig || SignificanceTest +|- +| MeanTestLevelsUp || diag_van_levels || LevelsUp +|- +| MedianTestCorrectForSolidAngle || diag_correct_solid_angle || CorrectForSolidAngle +|} + +====Sample Background Parameters==== +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| SamBkgMedianTestHigh || diag_samp_hi || SampleBkgHighAcceptanceFactor +|- +| SamBkgMedianTestLow || diag_samp_lo || SampleBkgLowAcceptanceFactor +|- +| SamBkgErrorBarCriterion || diag_samp_sig || SampleBkgSignificanceTest +|} + +====PsdBleed Parameters==== +{| class="wikitable" +|- +! Parameter !! IPF Mapping !! [[DetectorDiagnostic]] Mapping +|- +| MaxFramerate || diag_bleed_maxrate || MaxTubeFramerate +|- +| IgnoredPixels || diag_bleed_pixels || NIgnoredCentralPixels +|} + +=== Workflow === +[[File:DgsDiagnoseWorkflow.png]] *WIKI*/ @@ -124,7 +205,7 @@ namespace Mantid reductionManager, "diag_samp_zero", detVanWS); const bool createPsdBleed = getBoolPropOrParam("PsdBleed", reductionManager, "diag_bleed_test", detVanWS); - const bool vanSA = getBoolPropOrParam("MediantestCorectForSolidAngle", + const bool vanSA = getBoolPropOrParam("MedianTestCorrectForSolidAngle", reductionManager, "diag_correct_solid_angle", detVanWS); // Numeric properties diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsPreprocessData.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsPreprocessData.cpp index 2d282a8ad18f..e79ab8dee766 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsPreprocessData.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsPreprocessData.cpp @@ -1,7 +1,30 @@ /*WIKI* This algorithm is responsible for normalising data via a given incident beam -parameter. For SNS, monitor workspaces need to be passed. +parameter. This parameter, IncidentBeamNormalisation, is controlled from the +reduction property manager. It can have the values ''None'', ''ByCurrent'' or +''ByMonitor''. For SNS, monitor workspaces need to be passed. Parameters in +italics are controlled by the +[[InstrumentParameterFile | instrument parameter file (IPF)]] unless provided to +the algorithm via a property manager. The mappings are given below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping +|- +| MonitorIntRangeLow || norm-mon1-min +|- +| MonitorIntRangeHigh || norm-mon1-max +|} + +Parameters in italics with dashed perimeters are only controllable by the IPF +name given. All underlined parameters are fixed via other input method. If +normalisation is performed, a sample log called +DirectInelasticReductionNormalisedBy is added to the resulting workspace with +the normalisation procedure used. + +=== Workflow === +[[File:DgsPreprocessDataWorkflow.png]] *WIKI*/ diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsProcessDetectorVanadium.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsProcessDetectorVanadium.cpp index de7149c3d4b8..246a2d6c8221 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsProcessDetectorVanadium.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsProcessDetectorVanadium.cpp @@ -2,7 +2,29 @@ This algorithm is responsible for processing the detector vanadium in the form required for the sample data normalisation in the convert to energy transfer -process. +process. Parameters in italics are controlled by the +[[InstrumentParameterFile|instrument parameter file (IPF)]] unless provided +to the algorithm via a property manager. The mappings are given below. + +{| class="wikitable" +|- +! Parameter !! IPF Mapping +|- +| DetVanIntRangeLow || wb-integr-min +|- +| DetVanIntRangeHigh || wb-integr-max +|} + +Parameters in italics with dashed perimeters are only controllable by the IPF +name given. All underlined parameters are fixed and not controllable. +If the input detector vanadium is in TOF units and that is the +requested units for integration, the ''ConvertUnits'' algorithm does not run. +The range parameters feeding into ''Rebin'' are used to make a single bin. +The resulting integrated vanadium workspace can be saved to a file using the +reduction property manager with the boolean property SaveProcessedDetVan. + +=== Workflow === +[[File:DgsProcessDetectorVanadiumWorkflow.png]] *WIKI*/ diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsReduction.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsReduction.cpp index 9b3aca8056ef..8e99b232e9c3 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsReduction.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsReduction.cpp @@ -4,6 +4,14 @@ This is the top-level workflow algorithm for direct geometry spectrometer data reduction. This algorithm is responsible for gathering the necessary parameters and generating calls to other workflow or standard algorithms. +=== Workflow === +Parameters for the child algorithms are not shown due to sheer number. They +will be detailed in the child algorithm diagrams. Items in parallelograms are +output workspaces from their respective algorithms. Not all output workspaces +are subsequently used by other algorithms. + +[[File:DgsReductionWorkflow.png]] + *WIKI*/ #include "MantidWorkflowAlgorithms/DgsReduction.h" diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsRemap.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsRemap.cpp index 6c710973446b..847e21819651 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsRemap.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsRemap.cpp @@ -3,6 +3,9 @@ This algorithm is responsible for masking and grouping the given input workspace. One can use the ExecuteOppositeOrder to do grouping first then masking. +=== Workflow === +[[File:DgsRemapWorkflow.png]] + *WIKI*/ #include "MantidWorkflowAlgorithms/DgsRemap.h" diff --git a/Code/Mantid/MantidPlot/src/Folder.cpp b/Code/Mantid/MantidPlot/src/Folder.cpp index 234ea01c07f7..2277f07d4fd4 100644 --- a/Code/Mantid/MantidPlot/src/Folder.cpp +++ b/Code/Mantid/MantidPlot/src/Folder.cpp @@ -324,12 +324,20 @@ viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ); QPixmap pix; if (item->rtti() == FolderListItem::RTTI) +{ pix = getQPixmap("folder_closed_xpm"); -else - pix = *item->pixmap (0); +} +else if ( const QPixmap* p = item->pixmap(0) ) +{ + pix = *p; +} Q3IconDrag *drag = new Q3IconDrag(viewport()); -drag->setPixmap(pix, QPoint(pix.width()/2, pix.height()/2 ) ); + +if ( ! pix.isNull() ) +{ + drag->setPixmap(pix, QPoint(pix.width()/2, pix.height()/2 ) ); +} QList lst; for (item = firstChild(); item; item = item->itemBelow()) diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowMaskTab.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowMaskTab.cpp index c989f75a4c42..143fdd02f79c 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowMaskTab.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowMaskTab.cpp @@ -906,21 +906,23 @@ void InstrumentWindowMaskTab::saveMaskingToTableWorkspace(bool invertMask) alg->setProperty("Xmax", xmax); alg->execute(); - if (!alg->isExecuted()) - { - throw std::runtime_error("Algorithm ExtractMaskToTable fails to execute. "); - } - - // Mantid::API::MatrixWorkspace_sptr outputWS - Mantid::API::ITableWorkspace_sptr outputWS = - boost::dynamic_pointer_cast( - Mantid::API::AnalysisDataService::Instance().retrieve( outputWorkspaceName )); - - outputWS->setTitle("MaskBinTable"); - // Restore the previous state enableApplyButtons(); QApplication::restoreOverrideCursor(); + + if ( alg->isExecuted() ) + { + // Mantid::API::MatrixWorkspace_sptr outputWS + Mantid::API::ITableWorkspace_sptr outputWS = + boost::dynamic_pointer_cast( + Mantid::API::AnalysisDataService::Instance().retrieve( outputWorkspaceName )); + + outputWS->setTitle("MaskBinTable"); + } + else + { + QMessageBox::critical(this,"MantidPlot - Error","Algorithm ExtractMaskToTable fails to execute. "); + } } diff --git a/Code/Mantid/MantidPlot/src/Mantid/PeakPickerTool.cpp b/Code/Mantid/MantidPlot/src/Mantid/PeakPickerTool.cpp index fcea10336ed9..f1949d58746a 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/PeakPickerTool.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/PeakPickerTool.cpp @@ -88,9 +88,8 @@ m_width_set(true),m_width(0),m_addingPeak(false),m_resetting(false) this,SLOT(removePlot(MantidQt::MantidWidgets::PropertyHandler*))); connect(m_fitPropertyBrowser,SIGNAL(removeFitCurves()),this,SLOT(removeFitCurves())); - // When fit browser destroyed, disable oneself in the parent graph - connect(m_fitPropertyBrowser, SIGNAL( destroyed() ), graph, SLOT( disableTools() ), - Qt::QueuedConnection); + // When fit browser destroyed, disable oneself in the parent graph + connect(m_fitPropertyBrowser, SIGNAL(destroyed()), graph, SLOT(disableTools())); //Show the fitPropertyBrowser if it isn't already. if (showFitPropertyBrowser) m_fitPropertyBrowser->show(); diff --git a/Code/Mantid/MantidPlot/src/qti.sip b/Code/Mantid/MantidPlot/src/qti.sip index 07d91ef44f25..60d3d797028b 100644 --- a/Code/Mantid/MantidPlot/src/qti.sip +++ b/Code/Mantid/MantidPlot/src/qti.sip @@ -487,7 +487,7 @@ private: ImageMarker(const ImageMarker&); }; -class LegendWidget : QObject // : QWidget /PyName=Legend/ +class LegendWidget: QWidget { %TypeHeaderCode #include "src/LegendWidget.h" diff --git a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h index 2ccd8c95df27..f40e2a317e68 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h +++ b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.h @@ -49,7 +49,13 @@ namespace MantidQt private slots: /// When the "browse" button is clicked open a file browser. - void onBrowse(); + void workspaceSelected(const QString& wsName); + /// Set the "FileName" property when a file is selected from the file browser. + void fileSelected(); + + protected: + /// Overridden to enable dataselector validators + void accept(); protected: /// The form generated by QT Designer. diff --git a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.ui b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.ui index 6d74fca8aced..ae1921184f11 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.ui +++ b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/CatalogPublishDialog.ui @@ -7,8 +7,8 @@ 0 0 - 526 - 281 + 503 + 269 @@ -165,8 +165,8 @@ 0 0 - 506 - 197 + 483 + 185 @@ -181,34 +181,24 @@ QLayout::SetDefaultConstraint - + Name in catalog: - - - - Input workspace: - - - - + - - - - + Investigation number: - + @@ -218,37 +208,7 @@ - - - - Browse - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - - File name: - - - - + Description: @@ -258,9 +218,35 @@ - + + + + + + + + 0 + 0 + + + + false + + + + + + + + + false + + + + + @@ -321,11 +307,11 @@ - MantidQt::MantidWidgets::WorkspaceSelector - QComboBox -
MantidQtMantidWidgets/WorkspaceSelector.h
+ MantidQt::MantidWidgets::DataSelector + QWidget +
MantidQtMantidWidgets/DataSelector.h
- \ No newline at end of file + diff --git a/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp b/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp index 4fcfaf06ef3f..e9fd1946aaa8 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp +++ b/Code/Mantid/MantidQt/CustomDialogs/src/CatalogPublishDialog.cpp @@ -7,6 +7,7 @@ #include "MantidKernel/ConfigService.h" #include "MantidKernel/FacilityInfo.h" #include "MantidQtAPI/AlgorithmInputHistory.h" +#include "MantidQtMantidWidgets/DataSelector.h" #include @@ -28,25 +29,18 @@ namespace MantidQt m_uiForm.setupUi(this); this->setWindowTitle(m_algName); - tie(m_uiForm.fileNameTxt,"FileName"); - tie(m_uiForm.inputWorkspaceCb,"InputWorkspace"); tie(m_uiForm.nameInCatalogTxt,"NameInCatalog"); tie(m_uiForm.investigationNumberCb,"InvestigationNumber"); tie(m_uiForm.descriptionInput,"DataFileDescription"); - // Allows the combo box to show workspaces when they are loaded into Mantid. - m_uiForm.inputWorkspaceCb->setValidatingAlgorithm(m_algName); - - // This allows the user NOT to select a workspace if there are any loaded into Mantid. - m_uiForm.inputWorkspaceCb->insertItem("", 0); - - // Open a browsing dialog when the browse button is pressed. - connect(m_uiForm.browseBtn,SIGNAL(clicked()),this,SLOT(onBrowse())); - // Assign the buttons with the inherited methods. connect(m_uiForm.runBtn,SIGNAL(clicked()),this,SLOT(accept())); connect(m_uiForm.cancelBtn,SIGNAL(clicked()),this,SLOT(reject())); connect(m_uiForm.helpBtn,SIGNAL(clicked()),this,SLOT(helpClicked())); + // When the user selects a workspace, we want to be ready to publish it. + connect(m_uiForm.dataSelector,SIGNAL(dataReady(const QString&)),this,SLOT(workspaceSelected(const QString&))); + // When a file is chosen to be published, set the related "FileName" property of the algorithm. + connect(m_uiForm.dataSelector,SIGNAL(filesFound()),this,SLOT(fileSelected())); // Populate "investigationNumberCb" with the investigation IDs that the user can publish to. populateUserInvestigations(); @@ -90,21 +84,51 @@ namespace MantidQt } /** - * When the "browse" button is clicked open a file browser. + * Obtain the name of the workspace selected, and set it to the algorithm's property. + * @param wsName :: The name of the workspace to publish. + */ + void CatalogPublishDialog::workspaceSelected(const QString& wsName) + { + // Prevents both a file and workspace being published at same time. + storePropertyValue("FileName", ""); + setPropertyValue("FileName", true); + // Set the workspace property to the one the user has selected to publish. + storePropertyValue("InputWorkspace", wsName); + setPropertyValue("InputWorkspace", true); + } + + /** + * Set the "FileName" property when a file is selected from the file browser. */ - void CatalogPublishDialog::onBrowse() + void CatalogPublishDialog::fileSelected() { - if( !m_uiForm.fileNameTxt->text().isEmpty() ) + // Reset workspace property as the input is a file. This prevents both being selected. + storePropertyValue("InputWorkspace", ""); + setPropertyValue("InputWorkspace", true); + // Set the FileName property to the path that appears in the input field on the dialog. + storePropertyValue("FileName", m_uiForm.dataSelector->getFullFilePath()); + setPropertyValue("FileName", true); + } + + /** + * Overridden to enable dataselector validators. + */ + void CatalogPublishDialog::accept() + { + if (!m_uiForm.dataSelector->isValid()) { - QString lastdir = QFileInfo(m_uiForm.fileNameTxt->text()).absoluteDir().path(); - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory(lastdir); + if (m_uiForm.dataSelector->getFullFilePath().isEmpty()) + { + QMessageBox::critical(this,"Error in catalog publishing.","No file specified."); + } + else + { + QMessageBox::critical(this,"Error in catalog publishing.",m_uiForm.dataSelector->getProblem()); + } } - - QString filepath = this->openFileDialog("FileName"); //name of algorithm property. - if( !filepath.isEmpty() ) + else { - m_uiForm.fileNameTxt->clear(); - m_uiForm.fileNameTxt->setText(filepath.trimmed()); + AlgorithmDialog::accept(); } } } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt index 0443c274ff00..a631d991ab71 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt +++ b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt @@ -18,10 +18,11 @@ set ( SRC_FILES src/IndirectBayesTab.cpp src/IndirectDataAnalysis.cpp src/IndirectDiffractionReduction.cpp - src/IndirectLoadAscii.cpp - src/IndirectLoadAsciiTab.cpp - src/IndirectMolDyn.cpp - src/IndirectNeutron.cpp + src/IndirectLoadAscii.cpp + src/IndirectLoadAsciiTab.cpp + src/IndirectMolDyn.cpp + src/IndirectMoments.cpp + src/IndirectNeutron.cpp src/JumpFit.cpp src/MSDFit.cpp src/MantidEV.cpp @@ -73,10 +74,11 @@ set ( INC_FILES inc/MantidQtCustomInterfaces/IndirectBayesTab.h inc/MantidQtCustomInterfaces/IndirectDataAnalysis.h inc/MantidQtCustomInterfaces/IndirectDiffractionReduction.h - inc/MantidQtCustomInterfaces/IndirectLoadAscii.h - inc/MantidQtCustomInterfaces/IndirectLoadAsciiTab.h - inc/MantidQtCustomInterfaces/IndirectMolDyn.h - inc/MantidQtCustomInterfaces/IndirectNeutron.h + inc/MantidQtCustomInterfaces/IndirectLoadAscii.h + inc/MantidQtCustomInterfaces/IndirectLoadAsciiTab.h + inc/MantidQtCustomInterfaces/IndirectMolDyn.h + inc/MantidQtCustomInterfaces/IndirectMoments.h + inc/MantidQtCustomInterfaces/IndirectNeutron.h inc/MantidQtCustomInterfaces/JumpFit.h inc/MantidQtCustomInterfaces/MSDFit.h inc/MantidQtCustomInterfaces/MantidEV.h @@ -129,6 +131,7 @@ set ( MOC_FILES inc/MantidQtCustomInterfaces/Background.h inc/MantidQtCustomInterfaces/IndirectLoadAsciiTab.h inc/MantidQtCustomInterfaces/IndirectNeutron.h inc/MantidQtCustomInterfaces/IndirectMolDyn.h + inc/MantidQtCustomInterfaces/IndirectMoments.h inc/MantidQtCustomInterfaces/JumpFit.h inc/MantidQtCustomInterfaces/MSDFit.h inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -173,6 +176,7 @@ set ( UI_FILES inc/MantidQtCustomInterfaces/ConvertToEnergy.ui set( TEST_FILES CreateMDWorkspaceAlgDialogTest.h EventNexusFileMementoTest.h WorkspaceMementoTest.h + MuonAnalysisHelperTest.h WorkspaceInADSTest.h RawFileMementoTest.h IO_MuonGroupingTest.h diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/C2ETab.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/C2ETab.h index 1395a433ef95..eed11a106418 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/C2ETab.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/C2ETab.h @@ -1,8 +1,40 @@ #ifndef MANTID_CUSTOMINTERFACES_C2ETAB_H_ #define MANTID_CUSTOMINTERFACES_C2ETAB_H_ +#include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/AnalysisDataService.h" #include "MantidKernel/System.h" +#include "MantidQtAPI/MantidQwtMatrixWorkspaceData.h" #include "MantidQtCustomInterfaces/ConvertToEnergy.h" +#include "MantidQtMantidWidgets/RangeSelector.h" + +#include +#include +#include +#include +#include + +#include +#include + + +// Suppress a warning coming out of code that isn't ours +#if defined(__INTEL_COMPILER) + #pragma warning disable 1125 +#elif defined(__GNUC__) + #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6 ) + #pragma GCC diagnostic push + #endif + #pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif +#include "DoubleEditorFactory.h" +#if defined(__INTEL_COMPILER) + #pragma warning enable 1125 +#elif defined(__GNUC__) + #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6 ) + #pragma GCC diagnostic pop + #endif +#endif namespace MantidQt { @@ -46,9 +78,40 @@ namespace CustomInterfaces void setupTab(); void validateTab(); + protected: + // Run the load algorithm with the given file name and output name + bool loadFile(const QString& filename, const QString& outputName); + /// Function to plot a workspace to the miniplot using a workspace name + void plotMiniPlot(const QString& workspace, size_t index); + /// Function to plot a workspace to the miniplot using a workspace pointer + void plotMiniPlot(const Mantid::API::MatrixWorkspace_const_sptr & workspace, size_t wsIndex); + /// Function to get the range of the curve displayed on the mini plot + std::pair getCurveRange(); + /// Function to set the range limits of the plot + void setPlotRange(QtProperty* min, QtProperty* max, const std::pair& bounds); + /// Function to set the range selector on the mini plot + void setMiniPlotGuides(QtProperty* lower, QtProperty* upper, const std::pair& bounds); + + /// Plot of the input + QwtPlot* m_plot; + /// Curve on the plot + QwtPlotCurve* m_curve; + /// Range selector widget for mini plot + MantidQt::MantidWidgets::RangeSelector* m_rangeSelector; + /// Tree of the properties + QtTreePropertyBrowser* m_propTree; + /// Internal list of the properties + QMap m_properties; + /// Double manager to create properties + QtDoublePropertyManager* m_dblManager; + /// Double editor facotry for the properties browser + DoubleEditorFactory* m_dblEdFac; signals: - void runAsPythonScript(const QString & code, bool no_output); + /// Send signal to parent window to show a message box to user + void showMessageBox(const QString& message); + /// Run a python script + void runAsPythonScript(const QString & code, bool no_output); private: /// Overidden by child class. @@ -60,6 +123,7 @@ namespace CustomInterfaces protected: Ui::ConvertToEnergy m_uiForm; + }; } // namespace CustomInterfaces } // namespace Mantid diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ConvertToEnergy.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ConvertToEnergy.ui index e0c781f789c4..a80676518c4b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ConvertToEnergy.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ConvertToEnergy.ui @@ -2783,6 +2783,191 @@ Later steps in the process (saving, renaming) will not be done.
+ + + Moments + + + + + + Input + + + + + + + + + 0 + 0 + + + + Plot Input + + + + _sqw + + + + + _sqw.nxs + + + + false + + + + + + + + + Scale By: + + + + + + + false + + + + 0 + 0 + + + + + 50 + 16777215 + + + + + + + + <html><head/><body style=" color:#aa0000;"></body></html> + + + Qt::RichText + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Output Options + + + + + + + + Verbose + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Plot + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save + + + + + + + + + + Diagnose Detectors @@ -3265,6 +3450,11 @@ Later steps in the process (saving, renaming) will not be done.
QWidget
MantidQtMantidWidgets/DataSelector.h
+ + MantidQt::MantidWidgets::DataSelector + QWidget +
MantidQtMantidWidgets/DataSelector.h
+
tabWidget diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect.h index 5a590e68fed2..925c535aff7c 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect.h @@ -98,6 +98,8 @@ namespace MantidQt void pbRunEditing(); //< Called when a user starts to type / edit the runs to load. void pbRunFinding(); //< Called when the FileFinder starts finding the files. void pbRunFinished(); //< Called when the FileFinder has finished finding the files. + /// Slot showing a message box to the user + void showMessageBox(const QString& message); void analyserSelected(int index); ///< set up cbReflection based on Analyser selection void reflectionSelected(int index); ///< set up parameter file values based on reflection @@ -185,6 +187,7 @@ namespace MantidQt QtGroupPropertyManager* m_sltGrpMng; C2ETab* m_tab_trans; + C2ETab* m_tab_moments; }; } } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectBayesTab.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectBayesTab.h index e6e549753f52..91e2dd4b5a97 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectBayesTab.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectBayesTab.h @@ -123,8 +123,6 @@ namespace MantidQt void updateUpperGuide(QtProperty* lower, QtProperty* upper, double value); /// Function to get the range of the curve displayed on the mini plot std::pair getCurveRange(); - /// Function to check if the file name provided is available - bool checkFileLoaded(const QString& filename, const QString& filepath); /// Plot of the input QwtPlot* m_plot; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectMoments.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectMoments.h new file mode 100644 index 000000000000..6955860092c1 --- /dev/null +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectMoments.h @@ -0,0 +1,63 @@ +#ifndef MANTID_CUSTOMINTERFACES_INDIRECTMOMENTS_H_ +#define MANTID_CUSTOMINTERFACES_INDIRECTMOMENTS_H_ + +#include "MantidKernel/System.h" +#include "MantidQtCustomInterfaces/C2ETab.h" + +namespace MantidQt +{ +namespace CustomInterfaces +{ + /** IndirectMoments : TODO: DESCRIPTION + + + @author Samuel Jackson + @date 13/08/2013 + + Copyright © 2013 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 IndirectMoments : public C2ETab + { + Q_OBJECT + + public: + IndirectMoments(Ui::ConvertToEnergy& uiForm, QWidget * parent = 0); + virtual ~IndirectMoments(); + + virtual void setup(); + virtual void run(); + virtual bool validate(); + + protected slots: + //Handle when a file/workspace is ready for plotting + void handleSampleInputReady(const QString&); + /// Slot for when the min range on the range selector changes + void minValueChanged(double min); + /// Slot for when the min range on the range selector changes + void maxValueChanged(double max); + /// Slot to update the guides when the range properties change + void updateProperties(QtProperty* prop, double val); + + }; +} // namespace CustomInterfaces +} // namespace Mantid + +#endif /* MANTID_CUSTOMINTERFACES_INDIRECTMOMENTS_H_ */ \ No newline at end of file diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h index 74a92dba9832..ea24d832e61b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h @@ -43,6 +43,7 @@ namespace Muon std::string mainFieldDirection; double timeZero; double firstGoodData; + std::string label; }; struct GroupResult { @@ -311,29 +312,15 @@ private slots: /// Calculate number of detectors from string of type 1-3, 5, 10-15 int numOfDetectors(const std::string& str) const; - void changeCurrentRun(std::string& workspaceGroupName); - /// is string a number? bool isNumber(const std::string& s) const; /// Clear tables and front combo box void clearTablesAndCombo(); - /// Sums a given list of workspaces - Workspace_sptr sumWorkspaces(const std::vector& workspaces) const; - /// Deletes a workspace _or_ a workspace group with the given name, if one exists void deleteWorkspaceIfExists(const std::string& wsName); - /// Get group workspace name - QString getGroupName(); - - /// Get a name for the ranged workspace. - std::string getRangedName(); - - /// Check if grouping in table is consistent with data file - std::string isGroupingAndDataConsistent(); - ///Return true if data are loaded bool areDataLoaded(); @@ -416,9 +403,6 @@ private slots: /// tell which group is in which row std::vector m_groupToRow; - /// - void checkIf_ID_dublicatesInTable(const int row); - /// Return the group-number for the group in a row. /// Return -1 if invalid group in row int getGroupNumberFromRow(int row); @@ -508,6 +492,9 @@ private slots: /// When data loaded set various buttons etc to active void nowDataAvailable(); + /// Updates m_currentGroup given the new loaded label + void updateCurrentGroup(const std::string& newGroupName); + /// handles option tab work MantidQt::CustomInterfaces::Muon::MuonAnalysisOptionTab* m_optionTab; /// handles fit data work @@ -521,6 +508,9 @@ private slots: /// First Good Data time as loaded from Data file double m_dataFirstGoodData; + /// The group we should add new plot workspaces to + WorkspaceGroup_sptr m_currentGroup; + /// Default widget values static const QString TIME_ZERO_DEFAULT; static const QString FIRST_GOOD_BIN_DEFAULT; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysisHelper.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysisHelper.h index a444e3b19dbf..83dd2ffa8731 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysisHelper.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysisHelper.h @@ -1,6 +1,7 @@ #ifndef MANTID_CUSTOMINTERFACES_MUONANALYSISHELPER_H_ #define MANTID_CUSTOMINTERFACES_MUONANALYSISHELPER_H_ +#include "MantidQtCustomInterfaces/DllConfig.h" #include "MantidKernel/System.h" #include "MantidAPI/MatrixWorkspace.h" @@ -20,26 +21,38 @@ using namespace Mantid::API; using namespace Mantid::Kernel; /// Sets double validator for specified field -DLLExport void setDoubleValidator(QLineEdit* field, bool allowEmpty = false); +MANTIDQT_CUSTOMINTERFACES_DLL void setDoubleValidator(QLineEdit* field, bool allowEmpty = false); /// Returns a first period MatrixWorkspace in a run workspace -DLLExport MatrixWorkspace_sptr firstPeriod(Workspace_sptr ws); +MANTIDQT_CUSTOMINTERFACES_DLL MatrixWorkspace_sptr firstPeriod(Workspace_sptr ws); /// Validates the field and returns the value -DLLExport double getValidatedDouble(QLineEdit* field, const QString& defaultValue, +MANTIDQT_CUSTOMINTERFACES_DLL double getValidatedDouble(QLineEdit* field, const QString& defaultValue, const QString& valueDescr, Logger& log); /// Returns a number of periods in a run workspace -DLLExport size_t numPeriods(Workspace_sptr ws); +MANTIDQT_CUSTOMINTERFACES_DLL size_t numPeriods(Workspace_sptr ws); /// Print various information about the run -DLLExport void printRunInfo(MatrixWorkspace_sptr runWs, std::ostringstream& out); +MANTIDQT_CUSTOMINTERFACES_DLL void printRunInfo(MatrixWorkspace_sptr runWs, std::ostringstream& out); + +/// Get a run label for the workspace +MANTIDQT_CUSTOMINTERFACES_DLL std::string getRunLabel(const Workspace_sptr& ws); + +/// Get a run label for a list of workspaces +MANTIDQT_CUSTOMINTERFACES_DLL std::string getRunLabel(std::vector wsList); + +/// Sums a list of workspaces together +MANTIDQT_CUSTOMINTERFACES_DLL Workspace_sptr sumWorkspaces(const std::vector& workspaces); + +/// Compares two workspaces by run numbers +MANTIDQT_CUSTOMINTERFACES_DLL bool compareByRunNumber(Workspace_sptr ws1, Workspace_sptr ws2); /** * A class which deals with auto-saving the widget values. Widgets are registered and then on any * change, their value is stored using QSettings. */ -class Q_DECL_EXPORT WidgetAutoSaver : QObject +class MANTIDQT_CUSTOMINTERFACES_DLL WidgetAutoSaver : QObject { Q_OBJECT @@ -93,7 +106,7 @@ private slots: }; /// Validator which accepts valid doubles OR empty strings -class Q_DECL_EXPORT DoubleOrEmptyValidator : public QDoubleValidator +class MANTIDQT_CUSTOMINTERFACES_DLL DoubleOrEmptyValidator : public QDoubleValidator { Q_OBJECT diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/C2ETab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/C2ETab.cpp index a19076aa7a40..089b7254c221 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/C2ETab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/C2ETab.cpp @@ -9,7 +9,9 @@ namespace CustomInterfaces /** Constructor */ C2ETab::C2ETab(Ui::ConvertToEnergy& uiForm, QWidget * parent) : QWidget(parent), - m_uiForm(uiForm) + m_plot(new QwtPlot(parent)), m_curve(new QwtPlotCurve()), m_rangeSelector(new MantidWidgets::RangeSelector(m_plot)), + m_propTree(new QtTreePropertyBrowser()), m_properties(), m_dblManager(new QtDoublePropertyManager()), + m_dblEdFac(new DoubleEditorFactory()), m_uiForm(uiForm) { } @@ -38,6 +40,133 @@ namespace CustomInterfaces validate(); } + /** + * Run the load algorithm with the supplied filename + * + * @param filename :: The name of the workspace + * @return If the algorithm was successful + */ + bool C2ETab::loadFile(const QString& filename, const QString& outputName) + { + using namespace Mantid::API; + + Algorithm_sptr load = AlgorithmManager::Instance().createUnmanaged("Load", -1); + load->initialize(); + load->setProperty("Filename", filename.toStdString()); + load->setProperty("OutputWorkspace", outputName.toStdString()); + load->execute(); + + //if reloading fails we're out of options + if(!load->isExecuted()) + { + return false; + } + + return true; + } + + /** + * Plot a workspace to the miniplot given a workspace name and + * a specturm index. + * + * This method uses the analysis data service to retrieve the workspace. + * + * @param workspace :: The name of the workspace + * @param index :: The spectrum index of the workspace + */ + void C2ETab::plotMiniPlot(const QString& workspace, size_t index) + { + using namespace Mantid::API; + auto ws = AnalysisDataService::Instance().retrieveWS(workspace.toStdString()); + plotMiniPlot(ws, index); + } + + /** + * Gets the range of the curve plotted in the mini plot + * + * @return A pair containing the maximum and minimum points of the curve + */ + std::pair C2ETab::getCurveRange() + { + size_t npts = m_curve->data().size(); + + if( npts < 2 ) + throw std::invalid_argument("Too few points on data curve to determine range."); + + return std::make_pair(m_curve->data().x(0), m_curve->data().x(npts-1)); + } + + /** + * Plot a workspace to the miniplot given a workspace pointer and + * a specturm index. + * + * @param workspace :: Pointer to the workspace + * @param wsIndex :: The spectrum index of the workspace + */ + void C2ETab::plotMiniPlot(const Mantid::API::MatrixWorkspace_const_sptr & workspace, size_t wsIndex) + { + using Mantid::MantidVec; + + //check if we can plot + if( wsIndex >= workspace->getNumberHistograms() || workspace->readX(0).size() < 2 ) + { + return; + } + + MantidQwtMatrixWorkspaceData wsData(workspace, static_cast(wsIndex), false); + + if ( m_curve != NULL ) + { + m_curve->attach(0); + delete m_curve; + m_curve = NULL; + } + + size_t nhist = workspace->getNumberHistograms(); + if ( wsIndex >= nhist ) + { + emit showMessageBox("Error: Workspace index out of range."); + } + else + { + m_curve = new QwtPlotCurve(); + m_curve->setData(wsData); + m_curve->attach(m_plot); + + m_plot->replot(); + } + } + + /** + * Sets the edge bounds of plot to prevent the user inputting invalid values + * + * @param min :: The lower bound property in the property browser + * @param max :: The upper bound property in the property browser + * @param bounds :: The upper and lower bounds to be set + */ + void C2ETab::setPlotRange(QtProperty* min, QtProperty* max, const std::pair& bounds) + { + m_dblManager->setMinimum(min, bounds.first); + m_dblManager->setMaximum(min, bounds.second); + m_dblManager->setMinimum(max, bounds.first); + m_dblManager->setMaximum(max, bounds.second); + m_rangeSelector->setRange(bounds.first, bounds.second); + } + + /** + * Set the position of the guides on the mini plot + * + * @param lower :: The lower bound property in the property browser + * @param upper :: The upper bound property in the property browser + * @param bounds :: The upper and lower bounds to be set + */ + void C2ETab::setMiniPlotGuides(QtProperty* lower, QtProperty* upper, const std::pair& bounds) + { + m_dblManager->setValue(lower, bounds.first); + m_dblManager->setValue(upper, bounds.second); + m_rangeSelector->setMinimum(bounds.first); + m_rangeSelector->setMaximum(bounds.second); + } } // namespace CustomInterfaces } // namespace Mantid diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ConvertToEnergy.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ConvertToEnergy.cpp index e447aaeaa3c1..fa3061f06a54 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ConvertToEnergy.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ConvertToEnergy.cpp @@ -283,6 +283,7 @@ void ConvertToEnergy::changeInterface(DeltaEMode desired) case Direct: m_uiForm.tabWidget->removeTab(m_uiForm.tabWidget->indexOf(m_uiForm.tabCalibration)); m_uiForm.tabWidget->removeTab(m_uiForm.tabWidget->indexOf(m_uiForm.tabSofQW)); + m_uiForm.tabWidget->removeTab(m_uiForm.tabWidget->indexOf(m_uiForm.tabMoments)); m_uiForm.tabWidget->removeTab(m_uiForm.tabWidget->indexOf(m_uiForm.tabTimeSlice)); m_uiForm.tabWidget->removeTab(m_uiForm.tabWidget->indexOf(m_uiForm.tabTransmission)); m_uiForm.tabWidget->addTab(m_uiForm.tabDiagnoseDetectors, "Diagnose Detectors"); @@ -304,6 +305,7 @@ void ConvertToEnergy::changeInterface(DeltaEMode desired) m_uiForm.tabWidget->addTab(m_uiForm.tabTimeSlice, "Diagnostics"); m_uiForm.tabWidget->addTab(m_uiForm.tabTransmission, "Transmission"); m_uiForm.tabWidget->addTab(m_uiForm.tabSofQW, "S(Q, w)"); + m_uiForm.tabWidget->addTab(m_uiForm.tabMoments, "Moments"); if ( m_indirectInstruments == NULL ) { m_indirectInstruments = new Indirect(qobject_cast(this->parent()), m_uiForm); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Fury.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Fury.cpp index ff963584c1d0..da658e84b5b2 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Fury.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Fury.cpp @@ -65,12 +65,6 @@ namespace IDA "from IndirectDataAnalysis import fury\n"; QString wsName = uiForm().fury_dsInput->getCurrentDataName(); - //in case the user removed the workspace somehow, attempt to reload workspace - if(!Mantid::API::AnalysisDataService::Instance().doesExist(wsName.toStdString())) - { - QString fileName = uiForm().fury_dsInput->getFullFilePath(); - pyInput += wsName + " = LoadNexus('"+fileName+"')\n"; - } pyInput += "samples = [r'" + wsName + "']\n" "resolution = r'" + uiForm().fury_resFile->getFirstFilename() + "'\n" diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp index ed66d67620bc..b6f43f1e033e 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp @@ -1,5 +1,6 @@ #include "MantidQtCustomInterfaces/Indirect.h" #include "MantidQtCustomInterfaces/Transmission.h" +#include "MantidQtCustomInterfaces/IndirectMoments.h" #include "MantidQtCustomInterfaces/UserInputValidator.h" #include "MantidQtCustomInterfaces/Background.h" @@ -56,7 +57,9 @@ Indirect::Indirect(QWidget *parent, Ui::ConvertToEnergy & uiForm) : m_calCalCurve(NULL), m_calResCurve(NULL), // Null pointers - Diagnostics Tab m_sltPlot(NULL), m_sltR1(NULL), m_sltR2(NULL), m_sltDataCurve(NULL), - m_tab_trans(new Transmission(m_uiForm,this)) + // Additional tab interfaces + m_tab_trans(new Transmission(m_uiForm,this)), + m_tab_moments(new IndirectMoments(m_uiForm,this)) { // Constructor } @@ -112,8 +115,12 @@ void Indirect::initLayout() connect(m_uiForm.slice_pbPlotRaw, SIGNAL(clicked()), this, SLOT(slicePlotRaw())); connect(m_uiForm.slice_ckUseCalib, SIGNAL(toggled(bool)), this, SLOT(sliceCalib(bool))); - // "Transmission" tab + // additional tabs connect(m_tab_trans, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); + connect(m_tab_moments, SIGNAL(runAsPythonScript(const QString&, bool)), this, SIGNAL(runAsPythonScript(const QString&, bool))); + + connect(m_tab_trans, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); + connect(m_tab_moments, SIGNAL(showMessageBox(const QString&)), this, SLOT(showMessageBox(const QString&))); // create validators m_valInt = new QIntValidator(this); @@ -187,6 +194,8 @@ void Indirect::helpClicked() url += "SofQW"; else if (tabName == "Transmission") url += "Transmission"; + else if (tabName == "Moments") + url += "Moments"; QDesktopServices::openUrl(QUrl(url)); } /** @@ -217,6 +226,10 @@ void Indirect::runClicked() { m_tab_trans->runTab(); } + else if(tabName == "Moments") + { + m_tab_moments->runTab(); + } } void Indirect::runConvertToEnergy() @@ -959,6 +972,9 @@ void Indirect::loadSettings() m_uiForm.ind_calibFile->readSettings(settings.group()); m_uiForm.ind_mapFile->readSettings(settings.group()); m_uiForm.slice_calibFile->readSettings(settings.group()); + m_uiForm.moment_dsInput->readSettings(settings.group()); + m_uiForm.transInputFile->readSettings(settings.group()); + m_uiForm.transCanFile->readSettings(settings.group()); m_uiForm.sqw_dsSampleInput->readSettings(settings.group()); settings.endGroup(); } @@ -1769,19 +1785,18 @@ void Indirect::sOfQwClicked() QString rebinString = m_uiForm.sqw_leQLow->text()+","+m_uiForm.sqw_leQWidth->text()+","+m_uiForm.sqw_leQHigh->text(); QString pyInput = "from mantid.simpleapi import *\n"; - switch(m_uiForm.sqw_dsSampleInput->getCurrentView()) + if(m_uiForm.sqw_dsSampleInput->isFileSelectorVisible()) + { + //load the file + pyInput += "filename = r'" + m_uiForm.sqw_dsSampleInput->getFullFilePath() + "'\n" + "(dir, file) = os.path.split(filename)\n" + "(sqwInput, ext) = os.path.splitext(file)\n" + "LoadNexus(Filename=filename, OutputWorkspace=sqwInput)\n"; + } + else { - case 0: - //load the file - pyInput += "filename = r'" + m_uiForm.sqw_dsSampleInput->getFullFilePath() + "'\n" - "(dir, file) = os.path.split(filename)\n" - "(sqwInput, ext) = os.path.splitext(file)\n" - "LoadNexus(Filename=filename, OutputWorkspace=sqwInput)\n"; - break; - case 1: - //get the workspace - pyInput += "sqwInput = '" + m_uiForm.sqw_dsSampleInput->getCurrentDataName() + "'\n"; - break; + //get the workspace + pyInput += "sqwInput = '" + m_uiForm.sqw_dsSampleInput->getCurrentDataName() + "'\n"; } // Create output name before rebinning @@ -1862,19 +1877,18 @@ void Indirect::sOfQwPlotInput() if (m_uiForm.sqw_dsSampleInput->isValid()) { - switch(m_uiForm.sqw_dsSampleInput->getCurrentView()) + if(m_uiForm.sqw_dsSampleInput->isFileSelectorVisible()) { - case 0: - //load the file - pyInput += "filename = r'" + m_uiForm.sqw_dsSampleInput->getFullFilePath() + "'\n" - "(dir, file) = os.path.split(filename)\n" - "(sqwInput, ext) = os.path.splitext(file)\n" - "LoadNexus(Filename=filename, OutputWorkspace=sqwInput)\n"; - break; - case 1: - //get the workspace - pyInput += "sqwInput = '" + m_uiForm.sqw_dsSampleInput->getCurrentDataName() + "'\n"; - break; + //load the file + pyInput += "filename = r'" + m_uiForm.sqw_dsSampleInput->getFullFilePath() + "'\n" + "(dir, file) = os.path.split(filename)\n" + "(sqwInput, ext) = os.path.splitext(file)\n" + "LoadNexus(Filename=filename, OutputWorkspace=sqwInput)\n"; + } + else + { + //get the workspace + pyInput += "sqwInput = '" + m_uiForm.sqw_dsSampleInput->getCurrentDataName() + "'\n"; } pyInput += "ConvertSpectrumAxis(InputWorkspace=sqwInput, OutputWorkspace=sqwInput[:-4]+'_rqw', Target='ElasticQ', EMode='Indirect')\n" @@ -2046,6 +2060,16 @@ void Indirect::sliceUpdateRS(QtProperty* prop, double val) else if ( prop == m_sltProp["R2E"] ) m_sltR2->setMaximum(val); } +/** + * Slot to wrap the protected showInformationBox method defined + * in UserSubWindow and provide access to composed tabs. + * + * @param message :: The message to display in the message box + */ +void Indirect::showMessageBox(const QString& message) +{ + showInformationBox(message); +} void Indirect::setPlotRange(MantidWidgets::RangeSelector* rangeSelector, QtDoublePropertyManager* dblManager, const std::pair props, const std::pair& bounds) @@ -2056,5 +2080,3 @@ void Indirect::setPlotRange(MantidWidgets::RangeSelector* rangeSelector, QtDoubl dblManager->setMaximum(props.second, bounds.second); rangeSelector->setRange(bounds.first, bounds.second); } - - diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectBayesTab.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectBayesTab.cpp index 73ae6711acd8..6c49acd4d300 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectBayesTab.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectBayesTab.cpp @@ -240,38 +240,5 @@ namespace MantidQt m_rangeSelector->setMaximum(value); } } - - /** - * Checks if a file is present in the ADS and if not attempts to load it. - * - * @param filename :: name of the file that should be loaded - * @param filepath :: path to file - */ - bool IndirectBayesTab::checkFileLoaded(const QString& filename, const QString& filepath) - { - if(filename.isEmpty()) - { - emit showMessageBox("Please correct the following:\n Could not find the file called \"" + filename + "\""); - return false; - } - else if(!Mantid::API::AnalysisDataService::Instance().doesExist(filename.toStdString())) - { - //attempt reload the file if it's not there - Mantid::API::Algorithm_sptr load = Mantid::API::AlgorithmManager::Instance().createUnmanaged("Load", -1); - load->initialize(); - load->setProperty("Filename", filepath.toStdString()); - load->setProperty("OutputWorkspace", filename.toStdString()); - load->execute(); - - //if reloading fails we're out of options - if(!load->isExecuted()) - { - emit showMessageBox("Please correct the following:\n Workspace "+filename+" missing form analysis data service"); - return false; - } - } - - return true; - } } } // namespace MantidQt diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectMoments.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectMoments.cpp new file mode 100644 index 000000000000..dbbe3642f1ab --- /dev/null +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectMoments.cpp @@ -0,0 +1,187 @@ +#include "MantidQtCustomInterfaces/IndirectMoments.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" + +#include +#include + +namespace MantidQt +{ +namespace CustomInterfaces +{ + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + IndirectMoments::IndirectMoments(Ui::ConvertToEnergy& uiForm, QWidget * parent) : C2ETab(uiForm, parent) + { + const unsigned int NUM_DECIMALS = 6; + + m_propTree->setFactoryForManager(m_dblManager, m_dblEdFac); + m_rangeSelector->setInfoOnly(false); + + // initilise plot + m_plot->setCanvasBackground(Qt::white); + m_plot->setAxisFont(QwtPlot::xBottom, parent->font()); + m_plot->setAxisFont(QwtPlot::yLeft, parent->font()); + + //add the plot to the ui form + m_uiForm.moment_plotSpace->addWidget(m_plot); + //add the properties browser to the ui form + m_uiForm.moment_treeSpace->addWidget(m_propTree); + m_properties["EMin"] = m_dblManager->addProperty("EMin"); + m_properties["EMax"] = m_dblManager->addProperty("EMax"); + + m_propTree->addProperty(m_properties["EMin"]); + m_propTree->addProperty(m_properties["EMax"]); + + m_dblManager->setDecimals(m_properties["EMin"], NUM_DECIMALS); + m_dblManager->setDecimals(m_properties["EMax"], NUM_DECIMALS); + + m_uiForm.moment_leScale->setValidator(new QDoubleValidator()); + + connect(m_uiForm.moment_dsInput, SIGNAL(dataReady(const QString&)), this, SLOT(handleSampleInputReady(const QString&))); + connect(m_uiForm.moment_ckScale, SIGNAL(toggled(bool)), m_uiForm.moment_leScale, SLOT(setEnabled(bool))); + connect(m_uiForm.moment_ckScale, SIGNAL(toggled(bool)), m_uiForm.moment_validScale, SLOT(setVisible(bool))); + + connect(m_rangeSelector, SIGNAL(minValueChanged(double)), this, SLOT(minValueChanged(double))); + connect(m_rangeSelector, SIGNAL(maxValueChanged(double)), this, SLOT(maxValueChanged(double))); + connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updateProperties(QtProperty*, double))); + + m_uiForm.moment_validScale->setStyleSheet("QLabel { color : #aa0000; }"); + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + IndirectMoments::~IndirectMoments() + { + + } + + void IndirectMoments::setup() {} + + void IndirectMoments::run() + { + using namespace Mantid::API; + QString workspaceName = m_uiForm.moment_dsInput->getCurrentDataName(); + QString outputName = workspaceName.left(workspaceName.length()-4); + QString scaleString = m_uiForm.moment_leScale->text(); + double scale = 1.0; + double eMin = m_dblManager->value(m_properties["EMin"]); + double eMax = m_dblManager->value(m_properties["EMax"]); + + bool plot = m_uiForm.moment_ckPlot->isChecked(); + bool verbose = m_uiForm.moment_ckVerbose->isChecked(); + bool save = m_uiForm.moment_ckSave->isChecked(); + + if (!scaleString.isEmpty()) + { + scale = scaleString.toDouble(); + } + + Algorithm_sptr momentsAlg = AlgorithmManager::Instance().createUnmanaged("SofQWMoments", -1); + momentsAlg->initialize(); + momentsAlg->setProperty("Sample", workspaceName.toStdString()); + momentsAlg->setProperty("Scale", scale); + momentsAlg->setProperty("EnergyMin", eMin); + momentsAlg->setProperty("EnergyMax", eMax); + momentsAlg->setProperty("Plot", plot); + momentsAlg->setProperty("Verbose", verbose); + momentsAlg->setProperty("Save", save); + momentsAlg->setProperty("OutputWorkspace", outputName.toStdString() + "_Moments"); + try + { + momentsAlg->execute(); + } + catch(const std::runtime_error& e) + { + QString msg(e.what()); + emit showMessageBox("Error running Moments. " + msg + ".\nSee results log for details."); + } + } + + bool IndirectMoments::validate() + { + using namespace Mantid::API; + UserInputValidator uiv; + + uiv.checkDataSelectorIsValid("Sample input", m_uiForm.moment_dsInput); + + if (m_uiForm.moment_ckScale->isChecked()) + { + uiv.checkFieldIsValid("A valid scale must be supplied.\n", m_uiForm.moment_leScale, m_uiForm.moment_validScale); + } + + QString msg = uiv.generateErrorMessage(); + if (!msg.isEmpty()) + { + emit showMessageBox(msg); + return false; + } + + return true; + } + + void IndirectMoments::handleSampleInputReady(const QString& filename) + { + plotMiniPlot(filename, 0); + std::pair range = getCurveRange(); + setMiniPlotGuides(m_properties["EMin"], m_properties["EMax"], range); + setPlotRange(m_properties["EMin"], m_properties["EMax"], range); + } + + /** + * Updates the property manager when the lower guide is moved on the mini plot + * + * @param min :: The new value of the lower guide + */ + void IndirectMoments::minValueChanged(double min) + { + m_dblManager->setValue(m_properties["EMin"], min); + } + + /** + * Updates the property manager when the upper guide is moved on the mini plot + * + * @param max :: The new value of the upper guide + */ + void IndirectMoments::maxValueChanged(double max) + { + m_dblManager->setValue(m_properties["EMax"], max); + } + + /** + * Handles when properties in the property manager are updated. + * + * @param prop :: The property being updated + * @param val :: The new value for the property + */ + void IndirectMoments::updateProperties(QtProperty* prop, double val) + { + if(prop == m_properties["EMin"]) + { + double emax = m_dblManager->value(m_properties["EMax"]); + if(val > emax) + { + m_dblManager->setValue(prop, emax); + } + else + { + m_rangeSelector->setMinimum(val); + } + } + else if (prop == m_properties["EMax"]) + { + double emin = m_dblManager->value(m_properties["EMin"]); + if(emin > val) + { + m_dblManager->setValue(prop, emin); + } + else + { + m_rangeSelector->setMaximum(val); + } + } + } +} // namespace CustomInterfaces +} // namespace Mantid diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/JumpFit.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/JumpFit.cpp index 222d7d5e2f25..5edf78dca6c6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/JumpFit.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/JumpFit.cpp @@ -1,6 +1,7 @@ #include "MantidAPI/Run.h" #include "MantidAPI/TextAxis.h" #include "MantidQtCustomInterfaces/JumpFit.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" #include #include @@ -43,15 +44,21 @@ namespace MantidQt */ bool JumpFit::validate() { - //check that the sample file is loaded - QString sampleName = m_uiForm.dsSample->getCurrentDataName(); - QString samplePath = m_uiForm.dsSample->getFullFilePath(); + UserInputValidator uiv; + uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample); //this workspace doesn't have any valid widths - if(spectraList.size() == 0) return false; + if(spectraList.size() == 0) + { + uiv.addErrorMessage("Input workspace doesn't appear to contain any width data."); + } - //can't get hold of a pointer to the workspace - if(!checkFileLoaded(sampleName, samplePath)) return false; + QString errors = uiv.generateErrorMessage(); + if (!errors.isEmpty()) + { + emit showMessageBox(errors); + return false; + } return true; } @@ -223,7 +230,7 @@ namespace MantidQt if(!sampleName.isEmpty() && spectraList.size() > 0) { - if(checkFileLoaded(sampleName, samplePath)) + if(validate()) { plotMiniPlot(sampleName, spectraList[text.toStdString()]); } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index 0680f841b329..ab11387b12fb 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -368,28 +368,26 @@ void MuonAnalysis::plotItem(ItemType itemType, int tableRow, PlotType plotType) try { - // Name of the group currently used to store plot workspaces. Depends on loaded data. - const std::string groupName = getGroupName().toStdString(); - // Create workspace and a raw (unbinned) version of it MatrixWorkspace_sptr ws = createAnalysisWorkspace(itemType, tableRow, plotType); MatrixWorkspace_sptr wsRaw = createAnalysisWorkspace(itemType, tableRow, plotType, true); // Find names for new workspaces - const std::string wsName = getNewAnalysisWSName(groupName, itemType, tableRow, plotType); + const std::string wsName = getNewAnalysisWSName(m_currentGroup->getName(), itemType, tableRow, + plotType); const std::string wsRawName = wsName + "_Raw"; + // Make sure they are in the current group + if ( ! m_currentGroup->contains(wsName) ) + { + m_currentGroup->addWorkspace(ws); + m_currentGroup->addWorkspace(wsRaw); + } + // Make sure they end up in the ADS ads.addOrReplace(wsName, ws); ads.addOrReplace(wsRawName, wsRaw); - // Make sure they are in the right group - if ( ! ads.retrieveWS(groupName)->contains(wsName) ) - { - ads.addToGroup(groupName, wsName); - ads.addToGroup(groupName, wsRawName); - } - QString wsNameQ = QString::fromStdString(wsName); // Plot the workspace @@ -1399,11 +1397,32 @@ boost::shared_ptr MuonAnalysis::load(const QStringList& files) const result->mainFieldDirection = "longitudinal"; } - // Acquire a single loaded worksace to work with. If multiple loaded - sum them to get one if ( loadedWorkspaces.size() == 1 ) - result->loadedWorkspace = loadedWorkspaces.front(); + { + + // If single workspace loaded - use it + Workspace_sptr ws = loadedWorkspaces.front(); + result->loadedWorkspace = ws; + + result->label = getRunLabel(ws); + } else - result->loadedWorkspace = sumWorkspaces(loadedWorkspaces); + { + // If multiple workspaces loaded - sum them to get the one to work with + try + { + result->loadedWorkspace = sumWorkspaces(loadedWorkspaces); + } + catch(std::exception& e) + { + std::ostringstream error; + error << "Unable to sum workspaces together: " << e.what() << "\n"; + error << "Make sure they have equal dimensions and number of periods."; + throw std::runtime_error(error.str()); + } + + result->label = getRunLabel(loadedWorkspaces); + } return result; } @@ -1589,28 +1608,25 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) std::ostringstream infoStr; - // Populate run information with the run number - QString run(getGroupName()); - if (m_previousFilenames.size() > 1) - infoStr << "Runs: "; - else - infoStr << "Run: "; + std::string label = loadResult->label; // Remove instrument and leading zeros - // TODO: this should be moved to a separate method - int zeroCount(0); - for (int i=0; i 1) + infoStr << "Runs: "; + else + infoStr << "Run: "; + + infoStr << label; // Add other information about the run printRunInfo(matrix_workspace, infoStr); @@ -1639,44 +1655,13 @@ void MuonAnalysis::inputFileChanged(const QStringList& files) // Make the options available nowDataAvailable(); - // Create a group for new data, if it doesn't exist - const std::string groupName = getGroupName().toStdString(); - if ( ! AnalysisDataService::Instance().doesExist(groupName) ) - { - AnalysisDataService::Instance().add( groupName, boost::make_shared() ); - } + // Use label as a name for the group we will place plots to + updateCurrentGroup(loadResult->label); if(m_uiForm.frontPlotButton->isEnabled()) plotSelectedItem(); } -/** - * Sums a given list of workspaces - * @param workspaces :: List of workspaces - * @return Result workspace - */ -Workspace_sptr MuonAnalysis::sumWorkspaces(const std::vector& workspaces) const -{ - if (workspaces.size() < 1) - throw std::invalid_argument("Couldn't sum an empty list of workspaces"); - - ScopedWorkspace accumulatorEntry(workspaces.front()); - - for ( auto it = (workspaces.begin() + 1); it != workspaces.end(); ++it ) - { - ScopedWorkspace wsEntry(*it); - - IAlgorithm_sptr alg = AlgorithmManager::Instance().create("Plus"); - alg->setPropertyValue("LHSWorkspace", accumulatorEntry.name()); - alg->setPropertyValue("RHSWorkspace", wsEntry.name()); - alg->setPropertyValue("OutputWorkspace", accumulatorEntry.name()); - if (!alg->execute()) - throw std::runtime_error("Error in adding range together."); - } - - return accumulatorEntry.retrieve(); -} - /** * Deletes a workspace _or_ a workspace group with the given name, if one exists * @param wsName :: Name of the workspace to delete @@ -1692,71 +1677,6 @@ void MuonAnalysis::deleteWorkspaceIfExists(const std::string &wsName) } } -/** -* Get the group name for the workspace. -* -* @return wsGroupName :: The name of the group workspace. -*/ -QString MuonAnalysis::getGroupName() -{ - std::string workspaceGroupName(""); - - // Decide on name for workspaceGroup - if (m_previousFilenames.size() == 1) - { - Poco::File l_path( m_previousFilenames[0].toStdString() ); - workspaceGroupName = Poco::Path(l_path.path()).getFileName(); - changeCurrentRun(workspaceGroupName); - } - else - { - workspaceGroupName = getRangedName(); - } - - std::size_t extPos = workspaceGroupName.find("."); - if ( extPos!=std::string::npos) - workspaceGroupName = workspaceGroupName.substr(0,extPos); - - QString wsGroupName(workspaceGroupName.c_str()); - wsGroupName = wsGroupName.toUpper(); - return wsGroupName; -} - -/** -* Get ranged name. -* -* @return rangedName :: The name to be used to identify the workspace. -*/ -std::string MuonAnalysis::getRangedName() -{ - QString filePath(""); - QString firstFile(m_previousFilenames[0]); - QString lastFile(m_previousFilenames[m_previousFilenames.size()-1]); - - QString firstRun(""); - QString lastRun(""); - int runSize(-1); - - separateMuonFile(filePath, firstFile, firstRun, runSize); - - separateMuonFile(filePath, lastFile, lastRun, runSize); - - for (int i=0; i(rangeSize); } -/** -* Change the workspace group name to the instrument and run number if load current run was pressed. -* -* @param workspaceGroupName :: The name of the group that needs to be changed or is already in correct format. -*/ -void MuonAnalysis::changeCurrentRun(std::string & workspaceGroupName) -{ - QString tempGroupName(QString::fromStdString(workspaceGroupName) ); - - if ( (tempGroupName.contains("auto") ) || (tempGroupName.contains("argus0000000") ) ) - { - Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name); - MatrixWorkspace_sptr matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr); - if(!matrix_workspace) // Data collected in periods. - { - // Get run number from first period data. - workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1"); - matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr); - if(!matrix_workspace) - { - QMessageBox::information(this, "Mantid - Muon Analysis", "Mantid expected period data but no periods were found.\n" - "Default plot name will be used insead of run number."); - return; - } - } - const Run& runDetails = matrix_workspace->run(); - - std::string runNumber = runDetails.getProperty("run_number")->value(); - QString instname = m_uiForm.instrSelector->currentText().toUpper(); - - size_t zeroPadding(8); - - if (instname == "ARGUS") - zeroPadding = 7; - - for (size_t i=runNumber.size(); igetCustomFinishTime(); } -/** -* Check if grouping in table is consistent with data file -* -* @return empty string if OK otherwise a complaint -*/ -std::string MuonAnalysis::isGroupingAndDataConsistent() -{ - std::string complaint = "Grouping inconsistent with data file. Plotting disabled.\n"; - - // should probably farm the getting of matrix workspace out into separate method or store - // as attribute assigned in inputFileChanged - Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name); - WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast(workspace_ptr); - MatrixWorkspace_sptr matrix_workspace; - if (wsPeriods) - { - Workspace_sptr workspace_ptr1 = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1"); - matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr1); - } - else - { - matrix_workspace = boost::dynamic_pointer_cast(workspace_ptr); - } - - int nDet = static_cast(matrix_workspace->getNumberHistograms()); - - complaint += "Number of spectra in data = " + boost::lexical_cast(nDet) + ". "; - - int numG = numGroups(); - bool returnComplaint = false; - for (int iG = 0; iG < numG; iG++) - { - typedef Poco::StringTokenizer tokenizer; - tokenizer values(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString(), ",", tokenizer::TOK_TRIM); - - for (int i = 0; i < static_cast(values.count()); i++) - { - std::size_t found= values[i].find("-"); - if (found!=std::string::npos) - { - tokenizer aPart(values[i], "-", tokenizer::TOK_TRIM); - - int rightInt; - std::stringstream rightRead(aPart[1]); - rightRead >> rightInt; - - if ( rightInt > nDet ) - { - complaint += " Group-table row " + boost::lexical_cast(m_groupToRow[iG]+1) + " refers to spectrum " - + boost::lexical_cast(rightInt) + "."; - returnComplaint = true; - break; - } - } - else - { - if ( (boost::lexical_cast(values[i].c_str()) > nDet) || (boost::lexical_cast(values[i].c_str()) < 1) ) - { - complaint += " Group-table row " + boost::lexical_cast(m_groupToRow[iG]+1) + " refers to spectrum " - + values[i] + "."; - returnComplaint = true; - break; - } - } - } - } - if ( returnComplaint ) - return complaint; - else - return std::string(""); -} - - -/** -* Check if dublicate ID between different rows -* FIXME: this function doesn't seem to be used anywhere -*/ -void MuonAnalysis::checkIf_ID_dublicatesInTable(const int row) -{ - QTableWidgetItem *item = m_uiForm.groupTable->item(row,1); - - // row of IDs to compare against - std::vector idsNew = Strings::parseRange(item->text().toStdString()); - - int numG = numGroups(); - int rowInFocus = getGroupNumberFromRow(row); - for (int iG = 0; iG < numG; iG++) - { - if (iG != rowInFocus) - { - std::vector ids = Strings::parseRange(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString()); - - for (unsigned int i = 0; i < ids.size(); i++) - { - for (unsigned int j = 0; j < idsNew.size(); j++) - { - if ( ids[i] == idsNew[j] ) - { - item->setText(QString("Dublicate ID: " + item->text())); - return; - } - } - } - } - } -} - - /** * Load auto saved values */ @@ -2792,7 +2559,7 @@ void MuonAnalysis::changeRun(int amountToChange) if (currentFile.contains("auto") || currentFile.contains("argus0000000")) { separateMuonFile(filePath, currentFile, run, runSize); - currentFile = filePath + getGroupName() + ".nxs"; + currentFile = filePath + QString::fromStdString(m_currentGroup->getName()) + ".nxs"; } separateMuonFile(filePath, currentFile, run, runSize); @@ -3553,6 +3320,33 @@ void MuonAnalysis::nowDataAvailable() m_uiForm.guessAlphaButton->setEnabled(true); } +/** + * Updates the m_currentGroup given the name of the new group we want to store plot workspace to. + * @param newGroupName :: Name of the group m_currentGroup should have + */ +void MuonAnalysis::updateCurrentGroup(const std::string& newGroupName) +{ + if ( AnalysisDataService::Instance().doesExist(newGroupName) ) + { + auto existingGroup = AnalysisDataService::Instance().retrieveWS(newGroupName); + + if (existingGroup) + { + m_currentGroup = existingGroup; + return; + } + else + { + g_log.warning() << "Workspace with name '" << newGroupName << "' "; + g_log.warning() << "was replaced with the group used by MuonAnalysis." << "\n"; + } + } + + m_currentGroup = boost::make_shared(); + AnalysisDataService::Instance().addOrReplace(newGroupName, m_currentGroup); +} + + void MuonAnalysis::openDirectoryDialog() { MantidQt::API::ManageUserDirectories *ad = new MantidQt::API::ManageUserDirectories(this); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisHelper.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisHelper.cpp index 18487fc9dc71..8413cb6e0076 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisHelper.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysisHelper.cpp @@ -1,8 +1,13 @@ #include "MantidQtCustomInterfaces/MuonAnalysisHelper.h" +#include "MantidKernel/InstrumentInfo.h" #include "MantidKernel/EmptyValues.h" + #include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/ScopedWorkspace.h" #include "MantidAPI/WorkspaceGroup.h" + #include #include #include @@ -17,8 +22,8 @@ namespace CustomInterfaces namespace MuonAnalysisHelper { -using namespace Mantid::API; using namespace Mantid::Kernel; +using namespace Mantid::API; /** * Sets double validator for specified field. @@ -348,6 +353,98 @@ void WidgetAutoSaver::endGroup() } /** + * Get a run label for the workspace. + * E.g. for MUSR data of run 15189 it will look like MUSR00015189. + * @param ws :: Workspace to get label for. + * @return + */ +std::string getRunLabel(const Workspace_sptr& ws) +{ + MatrixWorkspace_const_sptr firstPrd = firstPeriod(ws); + + int runNumber = firstPrd->getRunNumber(); + std::string instrName = firstPrd->getInstrument()->getName(); + + int zeroPadding = ConfigService::Instance().getInstrument(instrName).zeroPadding(runNumber); + + std::ostringstream label; + label << instrName; + label << std::setw(zeroPadding) << std::setfill('0') << std::right << runNumber; + return label.str(); +} + +/** + * Get a run label for a list of workspaces. + * E.g. for MUSR data of runs 15189, 15190, 15191 it will look like MUSR00015189-91. + * @param wsList + * @return + */ +std::string getRunLabel(std::vector wsList) +{ + if (wsList.empty()) + throw std::invalid_argument("Unable to run on an empty list"); + + // Sort by run numbers, in case of non-sequential list of runs + std::sort(wsList.begin(), wsList.end(), compareByRunNumber); + + // Get string representation of the first and last run numbers + auto firstRun = boost::lexical_cast(firstPeriod(wsList.front())->getRunNumber()); + auto lastRun = boost::lexical_cast(firstPeriod(wsList.back())->getRunNumber()); + + // Remove the common part of the first and last run, so we get e.g. "12345-56" instead of "12345-12356" + for (size_t i = 0; i < firstRun.size() && i < lastRun.size(); ++i) + { + if (firstRun[i] != lastRun[i]) + { + lastRun.erase(0,i); + break; + } + } + + std::ostringstream label; + label << getRunLabel(wsList.front()); + label << '-' << lastRun; + return label.str(); +} + +/** + * Sums a given list of workspaces + * @param workspaces :: List of workspaces + * @return Result workspace + */ +Workspace_sptr sumWorkspaces(const std::vector& workspaces) +{ + if (workspaces.size() < 1) + throw std::invalid_argument("Couldn't sum an empty list of workspaces"); + + ScopedWorkspace firstEntry(workspaces.front()); + ScopedWorkspace accumulatorEntry; + + // Create accumulator workspace, by cloning the first one from the list + IAlgorithm_sptr cloneAlg = AlgorithmManager::Instance().create("CloneWorkspace"); + cloneAlg->setLogging(false); + cloneAlg->setRethrows(true); + cloneAlg->setPropertyValue("InputWorkspace", firstEntry.name()); + cloneAlg->setPropertyValue("OutputWorkspace", accumulatorEntry.name()); + cloneAlg->execute(); + + for ( auto it = (workspaces.begin() + 1); it != workspaces.end(); ++it ) + { + ScopedWorkspace wsEntry(*it); + + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("Plus"); + alg->setLogging(false); + alg->setRethrows(true); + alg->setPropertyValue("LHSWorkspace", accumulatorEntry.name()); + alg->setPropertyValue("RHSWorkspace", wsEntry.name()); + alg->setPropertyValue("OutputWorkspace", accumulatorEntry.name()); + alg->execute(); + } + + return accumulatorEntry.retrieve(); +} + +/* * Validates and returns a double value. If it is not invalid, the widget is set to default value, * appropriate warning is printed and default value is returned. * @param field :: Field to get value from @@ -381,6 +478,16 @@ double getValidatedDouble(QLineEdit* field, const QString& defaultValue, return value; } +/** + * @param ws1 :: First workspace to compare + * @param ws2 :: Second workspace to compare + * @return True if ws1 < ws2, false otherwise + */ +bool compareByRunNumber(Workspace_sptr ws1, Workspace_sptr ws2) +{ + return firstPeriod(ws1)->getRunNumber() < firstPeriod(ws2)->getRunNumber(); +} + } // namespace MuonAnalysisHelper } // namespace CustomInterfaces } // namespace Mantid diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Quasi.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Quasi.cpp index 48feee3739df..f8384fb0cec5 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Quasi.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Quasi.cpp @@ -1,4 +1,5 @@ #include "MantidQtCustomInterfaces/Quasi.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" namespace MantidQt { @@ -67,32 +68,27 @@ namespace MantidQt */ bool Quasi::validate() { - //check that the sample file exists - QString sampleName = m_uiForm.dsSample->getCurrentDataName(); - QString samplePath = m_uiForm.dsSample->getFullFilePath(); - - if(!checkFileLoaded(sampleName, samplePath)) return false; - - //check that the resolution file exists - QString resName = m_uiForm.dsResolution->getCurrentDataName(); - QString resPath = m_uiForm.dsResolution->getFullFilePath(); - - if(!checkFileLoaded(resName, resPath)) return false; - + UserInputValidator uiv; + uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample); + uiv.checkDataSelectorIsValid("Resolution", m_uiForm.dsResolution); + //check that the ResNorm file is valid if we are using it if(m_uiForm.chkUseResNorm->isChecked()) { - QString resNormFile = m_uiForm.dsResNorm->getCurrentDataName(); - QString resNormPath = m_uiForm.dsResNorm->getFullFilePath(); - - if(!checkFileLoaded(resNormFile, resNormPath)) return false; + uiv.checkDataSelectorIsValid("ResNorm", m_uiForm.dsResNorm); } //check fixed width file exists if(m_uiForm.chkFixWidth->isChecked() && !m_uiForm.mwFixWidthDat->isValid()) { - emit showMessageBox("Please correct the following:\n Could not find the specified Fixed Width file"); + uiv.checkMWRunFilesIsValid("Width", m_uiForm.mwFixWidthDat); + } + + QString errors = uiv.generateErrorMessage(); + if (!errors.isEmpty()) + { + emit showMessageBox(errors); return false; } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ResNorm.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ResNorm.cpp index 81fd95db93f1..5ab1d38bd4f2 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ResNorm.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ResNorm.cpp @@ -1,4 +1,5 @@ #include "MantidQtCustomInterfaces/ResNorm.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" namespace MantidQt { @@ -40,17 +41,16 @@ namespace MantidQt */ bool ResNorm::validate() { - //check that the sample file exists - QString sampleName = m_uiForm.dsVanadium->getCurrentDataName(); - QString samplePath = m_uiForm.dsVanadium->getFullFilePath(); + UserInputValidator uiv; + uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsVanadium); + uiv.checkDataSelectorIsValid("Resolution", m_uiForm.dsResolution); - if(!checkFileLoaded(sampleName, samplePath)) return false; - - //check that the resolution file exists - QString resName = m_uiForm.dsResolution->getCurrentDataName(); - QString resPath = m_uiForm.dsResolution->getFullFilePath(); - - if(!checkFileLoaded(resName, resPath)) return false; + QString errors = uiv.generateErrorMessage(); + if (!errors.isEmpty()) + { + emit showMessageBox(errors); + return false; + } return true; } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Stretch.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Stretch.cpp index 45bbaafadfc8..e75822650e92 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Stretch.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Stretch.cpp @@ -1,4 +1,5 @@ #include "MantidQtCustomInterfaces/Stretch.h" +#include "MantidQtCustomInterfaces/UserInputValidator.h" namespace MantidQt { @@ -54,17 +55,16 @@ namespace MantidQt */ bool Stretch::validate() { - //check that the sample file exists - QString sampleName = m_uiForm.dsSample->getCurrentDataName(); - QString samplePath = m_uiForm.dsSample->getFullFilePath(); - - if(!checkFileLoaded(sampleName, samplePath)) return false; - - //check that the resolution file exists - QString resName = m_uiForm.dsResolution->getCurrentDataName(); - QString resPath = m_uiForm.dsResolution->getFullFilePath(); - - if(!checkFileLoaded(resName, resPath)) return false; + UserInputValidator uiv; + uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample); + uiv.checkDataSelectorIsValid("Resolution", m_uiForm.dsResolution); + + QString errors = uiv.generateErrorMessage(); + if (!errors.isEmpty()) + { + emit showMessageBox(errors); + return false; + } return true; } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/UserInputValidator.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/UserInputValidator.cpp index 8d879aef003a..c57252ae5c47 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/UserInputValidator.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/UserInputValidator.cpp @@ -103,7 +103,7 @@ namespace MantidQt } /** - * Check that the given MWRunFiles widget has valid files. + * Check that the given DataSelector widget has valid files. * * @param name :: the "name" of the widget so as to be recognised by the user. * @param widget :: the widget to check @@ -112,15 +112,7 @@ namespace MantidQt { if( ! widget->isValid() ) { - switch(widget->getCurrentView()) - { - case 0: - m_errorMessages.append(name + " file error: file could not be found"); - break; - case 1: - m_errorMessages.append(name + " workspace error: workspace could not be found"); - break; - } + m_errorMessages.append(name + " error: " + widget->getProblem()); } } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt index 1371bf3af916..12ac3d146062 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt @@ -3,6 +3,11 @@ if ( CXXTEST_FOUND ) include_directories( ../../../Framework/TestHelpers/inc ../../../Framework/DataObjects/inc ) + set ( TESTHELPER_SRCS ../../../Framework/TestHelpers/src/ComponentCreationHelper.cpp + ../../../Framework/TestHelpers/src/WorkspaceCreationHelper.cpp + ../../../Framework/TestHelpers/src/ScopedFileHelper.cpp + ) + if ( GMOCK_FOUND AND GTEST_FOUND ) cxxtest_add_test ( CustomInterfacesTest ${TEST_FILES} ${GMOCK_TEST_FILES} ) target_link_libraries( CustomInterfacesTest CustomInterfaces DataObjects ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} ) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/MuonAnalysisHelperTest.h b/Code/Mantid/MantidQt/CustomInterfaces/test/MuonAnalysisHelperTest.h new file mode 100644 index 000000000000..1d2223158319 --- /dev/null +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/MuonAnalysisHelperTest.h @@ -0,0 +1,121 @@ +#ifndef MANTID_CUSTOMINTERFACES_MUONANALYSISHELPERTEST_H_ +#define MANTID_CUSTOMINTERFACES_MUONANALYSISHELPERTEST_H_ + +#include + +#include "MantidQtCustomInterfaces/MuonAnalysisHelper.h" +#include "MantidAPI/WorkspaceFactory.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidGeometry/Instrument.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" + +#include + +using namespace MantidQt::CustomInterfaces::MuonAnalysisHelper; + +using namespace Mantid; +using namespace Mantid::API; + +class MuonAnalysisHelperTest : 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 MuonAnalysisHelperTest *createSuite() { return new MuonAnalysisHelperTest(); } + static void destroySuite( MuonAnalysisHelperTest *suite ) { delete suite; } + + MuonAnalysisHelperTest() + { + FrameworkManager::Instance(); // So that framework is initialized + } + + void test_getRunLabel_singleWs() + { + std::string label = getRunLabel(createWs("MUSR", 15189)); + TS_ASSERT_EQUALS(label, "MUSR00015189"); + } + + void test_getRunLabel_argus() + { + std::string label = getRunLabel(createWs("ARGUS", 26577)); + TS_ASSERT_EQUALS(label, "ARGUS0026577"); + } + + void test_getRunLabel_singleWs_tooBigRunNumber() + { + std::string label = getRunLabel(createWs("EMU", 999999999)); + TS_ASSERT_EQUALS(label, "EMU999999999"); + } + + void test_getRunLabel_wsList() + { + std::vector list; + + for (int i = 15189; i <= 15199; ++i) + { + list.push_back(createWs("MUSR", i)); + } + + std::string label = getRunLabel(list); + TS_ASSERT_EQUALS(label, "MUSR00015189-99"); + } + + void test_getRunLabel_wsList_wrongOrder() + { + std::vector runNumbers = boost::assign::list_of(10)(3)(5)(1)(6); + std::vector list; + + for (auto it = runNumbers.begin(); it != runNumbers.end(); ++it) + { + list.push_back(createWs("EMU", *it)); + } + + std::string label = getRunLabel(list); + TS_ASSERT_EQUALS(label, "EMU00000001-10"); + } + + void test_sumWorkspaces() + { + MatrixWorkspace_sptr ws1 = WorkspaceCreationHelper::Create2DWorkspace123(1, 3); + MatrixWorkspace_sptr ws2 = WorkspaceCreationHelper::Create2DWorkspace123(1, 3); + MatrixWorkspace_sptr ws3 = WorkspaceCreationHelper::Create2DWorkspace123(1, 3); + + std::vector wsList = boost::assign::list_of(ws1)(ws2)(ws3); + + auto result = boost::dynamic_pointer_cast(sumWorkspaces(wsList)); + + TS_ASSERT(result); + if (!result) + return; // Nothing to check + + TS_ASSERT_EQUALS(result->getNumberHistograms(), 1); + TS_ASSERT_EQUALS(result->blocksize(), 3); + + TS_ASSERT_EQUALS(result->readY(0)[0], 6); + TS_ASSERT_EQUALS(result->readY(0)[1], 6); + TS_ASSERT_EQUALS(result->readY(0)[2], 6); + + // Original workspaces shouldn't be touched + TS_ASSERT_EQUALS(ws1->readY(0)[0], 2); + TS_ASSERT_EQUALS(ws3->readY(0)[2], 2); + } + +private: + + // Creates a single-point workspace with instrument and runNumber set + Workspace_sptr createWs(const std::string& instrName, int runNumber) + { + Geometry::Instrument_const_sptr instr = boost::make_shared(instrName); + + MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); + ws->setInstrument(instr); + + ws->mutableRun().addProperty("run_number", runNumber); + + return ws; + } + +}; + + +#endif /* MANTID_CUSTOMINTERFACES_MUONANALYSISHELPERTEST_H_ */ diff --git a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt index 08cb74567e17..4356dca0154b 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt +++ b/Code/Mantid/MantidQt/MantidWidgets/CMakeLists.txt @@ -5,6 +5,8 @@ set ( SRC_FILES src/CheckboxHeader.cpp src/DataSelector.cpp src/DiagResults.cpp + src/FilenameDialogEditor.cpp + src/FormulaDialogEditor.cpp src/FindDialog.cpp src/FindReplaceDialog.cpp src/FitPropertyBrowser.cpp @@ -26,7 +28,10 @@ set ( SRC_FILES src/SelectFunctionDialog.cpp src/SelectWorkspacesDialog.cpp src/SequentialFitDialog.cpp + src/StringDialogEditor.cpp + src/StringEditorFactory.cpp src/UserFunctionDialog.cpp + src/WorkspaceEditorFactory.cpp src/WorkspaceSelector.cpp src/pythonCalc.cpp ) @@ -37,6 +42,8 @@ set ( MOC_FILES inc/MantidQtMantidWidgets/CheckboxHeader.h inc/MantidQtMantidWidgets/DataSelector.h inc/MantidQtMantidWidgets/DiagResults.h + inc/MantidQtMantidWidgets/FilenameDialogEditor.h + inc/MantidQtMantidWidgets/FormulaDialogEditor.h inc/MantidQtMantidWidgets/FindReplaceDialog.h inc/MantidQtMantidWidgets/FindDialog.h inc/MantidQtMantidWidgets/FitPropertyBrowser.h @@ -60,7 +67,10 @@ set ( MOC_FILES inc/MantidQtMantidWidgets/SelectFunctionDialog.h inc/MantidQtMantidWidgets/SelectWorkspacesDialog.h inc/MantidQtMantidWidgets/SequentialFitDialog.h + inc/MantidQtMantidWidgets/StringDialogEditor.h + inc/MantidQtMantidWidgets/StringEditorFactory.h inc/MantidQtMantidWidgets/UserFunctionDialog.h + inc/MantidQtMantidWidgets/WorkspaceEditorFactory.h inc/MantidQtMantidWidgets/WorkspaceSelector.h ) @@ -105,7 +115,7 @@ add_definitions ( -DQSCINTILLA_DLL ) # Will only have an effect on Windows ( # For Windows: -add_definitions ( -DIN_MANTIDQT_MANTIDWIDGETS ) +add_definitions ( -DIN_MANTIDQT_MANTIDWIDGETS -DQT_QTPROPERTYBROWSER_IMPORT ) # Use a precompiled header where they are supported enable_precompiled_headers( inc/MantidQtMantidWidgets/PrecompiledHeader.h ALL_SRC ) add_library ( MantidWidgets ${ALL_SRC} ${INC_FILES} ${UI_HDRS} ) diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataSelector.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataSelector.h index 1ac3e9c7c6e4..6e9769d42056 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataSelector.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataSelector.h @@ -57,13 +57,17 @@ namespace MantidQt virtual ~DataSelector(); /// Get the current file path in the MWRunFiles widget - QString getFullFilePath(); + QString getFullFilePath() const; /// Get the currently available file or workspace name - QString getCurrentDataName(); - /// Get whether file or workspace input is currently being shown - int getCurrentView() const; + QString getCurrentDataName() const; + /// Get whether the file selector is currently being shown + bool isFileSelectorVisible() const; + /// Get whether the workspace selector is currently being shown + bool isWorkspaceSelectorVisible() const; /// Checks if widget is in a valid state - bool isValid() const; + bool isValid(); + /// Get file problem, empty string means no error. + QString getProblem() const; /// Check if the widget is set to automatically attempt to load files bool willAutoLoad(); /// Set the widget to automatically attempt to load files diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FilenameDialogEditor.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FilenameDialogEditor.h new file mode 100644 index 000000000000..bbc58a5303a5 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FilenameDialogEditor.h @@ -0,0 +1,44 @@ +#ifndef MANTIDQT_MANTIDWIDGETS_FILENAMEDIALOGEDITFACTORY_H +#define MANTIDQT_MANTIDWIDGETS_FILENAMEDIALOGEDITFACTORY_H + +#include "MantidQtMantidWidgets/StringDialogEditor.h" + +namespace MantidQt +{ +namespace MantidWidgets +{ + +/** + * A stringDialogEditor for editing file names. + */ +class FilenameDialogEditor: public StringDialogEditor +{ + Q_OBJECT +public: + FilenameDialogEditor(QtProperty *property, QWidget *parent) + :StringDialogEditor(property,parent){} +protected slots: + void runDialog(); +}; + +/** + * The factory for the FilenameDialogEditor. + */ +class FilenameDialogEditorFactory: public StringDialogEditorFactory +{ + Q_OBJECT +public: + FilenameDialogEditorFactory(QObject* parent):StringDialogEditorFactory(parent){} +protected: + using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning + QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent) + { + (void) manager; //Avoid unused warning + return new FilenameDialogEditor(property,parent); + } +}; + +} +} + +#endif // MANTIDQT_MANTIDWIDGETS_FILENAMEDIALOGEDITFACTORY_H \ No newline at end of file diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h index f7808c930056..b22ca81cc849 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FitPropertyBrowser.h @@ -26,6 +26,8 @@ class QtIntPropertyManager; class QtBoolPropertyManager; class QtStringPropertyManager; class QtEnumPropertyManager; +class ParameterPropertyManager; + class QtProperty; class QtBrowserItem; @@ -272,6 +274,8 @@ private slots: void boolChanged(QtProperty* prop); void intChanged(QtProperty* prop); virtual void doubleChanged(QtProperty* prop); + /// Called when one of the parameter values gets changed + void parameterChanged(QtProperty* prop); void stringChanged(QtProperty* prop); void filenameChanged(QtProperty* prop); void columnChanged(QtProperty* prop); @@ -360,6 +364,7 @@ private slots: QtGroupPropertyManager *m_vectorManager; QtIntPropertyManager *m_vectorSizeManager; QtDoublePropertyManager *m_vectorDoubleManager; + ParameterPropertyManager *m_parameterManager; QtProperty *m_workspace; QtProperty *m_workspaceIndex; @@ -377,6 +382,7 @@ private slots: QtProperty *m_xColumn; QtProperty *m_yColumn; QtProperty *m_errColumn; + QtProperty *m_showParamErrors; QList m_minimizerProperties; /// A copy of the edited function diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FormulaDialogEditor.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FormulaDialogEditor.h new file mode 100644 index 000000000000..55effc50985e --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FormulaDialogEditor.h @@ -0,0 +1,43 @@ +#ifndef MANTIDQT_MANTIDWIDGETS_FORMULADIALOGEDIT_H +#define MANTIDQT_MANTIDWIDGETS_FORMULADIALOGEDIT_H + +#include "MantidQtMantidWidgets/StringDialogEditor.h" + +namespace MantidQt +{ +namespace MantidWidgets +{ + +/** + * A stringDialogEditor for editing UserFunction. + */ +class FormulaDialogEditor: public StringDialogEditor +{ + Q_OBJECT +public: + FormulaDialogEditor(QtProperty *property, QWidget *parent) + :StringDialogEditor(property,parent){} +protected slots: + void runDialog(); +}; + +/** + * The factory for the FormulaDialogEditor. + */ +class FormulaDialogEditorFactory: public StringDialogEditorFactory +{ + Q_OBJECT +public: + FormulaDialogEditorFactory(QObject* parent):StringDialogEditorFactory(parent){} +protected: + using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning + QWidget *createEditor(QtStringPropertyManager *, QtProperty *property,QWidget *parent) + { + return new FormulaDialogEditor(property,parent); + } +}; + +} +} + +#endif // MANTIDQT_MANTIDWIDGETS_FORMULADIALOGEDIT_H diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h index b01a431dd39c..ce9a6447bc33 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h @@ -216,8 +216,12 @@ protected slots: QtStringPropertyManager *m_tieManager; /// Manager for parameter constraint properties QtStringPropertyManager *m_constraintManager; + /// Manager for file name attributes + QtStringPropertyManager *m_filenameManager; /// Manager for Formula attributes QtStringPropertyManager *m_formulaManager; + /// Manager for Workspace attributes + QtStringPropertyManager *m_workspaceManager; /// Manager for vector attribute properties QtGroupPropertyManager *m_attributeVectorManager; /// Manager for vector attribute member properties diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/PropertyHandler.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/PropertyHandler.h index 494be7231c31..6efc72d474c7 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/PropertyHandler.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/PropertyHandler.h @@ -64,6 +64,9 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS PropertyHandler:public QObject, public M QString functionPrefix()const; + /// High level structure representation of the string + QString functionStructure() const; + // Return composite function boost::shared_ptr cfun()const{return m_cf;} // Return peak function @@ -127,11 +130,15 @@ class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS PropertyHandler:public QObject, public M /// Set function vector attribute value void setVectorAttribute(QtProperty* prop); - /** - * Update the parameter properties - */ + /// Sync all parameter values with the manager void updateParameters(); + /// Set all parameter error values in the manager + void updateErrors(); + + /// Clear all parameter error values in the manager + void clearErrors(); + // Get property for function parameter parName QtProperty* getParameterProperty(const QString& parName)const; @@ -188,6 +195,9 @@ protected slots: // void plotRemoved(); + /// Run when function structure is changed, i.e. children function added/removed + void onFunctionStructChanged(); + protected: void initAttributes(); @@ -214,6 +224,18 @@ protected slots: //mutable FunctionCurve* m_curve;//< the curve to plot the handled function mutable bool m_hasPlot; + /// Sync function parameter value with the manager + void updateParameter(QtProperty* prop); + + /// Set function parameter error in the manager + void updateError(QtProperty* prop); + + /// Clear function parameter error in the manager + void clearError(QtProperty* prop); + + /// Applies given function to all the parameter properties recursively + void applyToAllParameters(void (PropertyHandler::*func)(QtProperty*)); + friend class CreateAttributeProperty; }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/SequentialFitDialog.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/SequentialFitDialog.ui index 9be27de7c522..2b0b0bd0716e 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/SequentialFitDialog.ui +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/SequentialFitDialog.ui @@ -128,6 +128,23 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + @@ -139,7 +156,27 @@ - + + + false + + + Output Composite Members + + + + + + + false + + + Convolve Members + + + + + Qt::Horizontal diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringDialogEditor.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringDialogEditor.h new file mode 100644 index 000000000000..6baccc78ab71 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringDialogEditor.h @@ -0,0 +1,46 @@ +#ifndef STRINGDIALOGEDITORFACTORY_H +#define STRINGDIALOGEDITORFACTORY_H + +#include "qtpropertymanager.h" + +class QLineEdit; + +/** + * An abstract editor factory to be used with QtPropertyBrowser. Implementations need to + * implement QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent) + * method which creates a specific editor. The underlying type of the edited property must be string. + */ +class StringDialogEditorFactory : public QtAbstractEditorFactory +{ + Q_OBJECT +public: + StringDialogEditorFactory(QObject *parent = 0): QtAbstractEditorFactory(parent){} +protected: + void connectPropertyManager(QtStringPropertyManager *manager); + void disconnectPropertyManager(QtStringPropertyManager *manager); +}; + +/** + * Partially implemented string editor. It has a QLineEdit for manual editing and a button [...] next to it + * to call a dialog for more complex editing. Clicking the button calls virtual runDialog() method. + * Concrete classes must implement it. + */ +class StringDialogEditor: public QWidget +{ + Q_OBJECT +public: + StringDialogEditor(QtProperty *property, QWidget *parent); + ~StringDialogEditor(); +protected slots: + /// Implementations must open a dialog to edit the editor's text. If editing is successful + /// setText() and updateProperty() methods must be called. + virtual void runDialog() = 0; + void updateProperty(); + void setText(const QString& txt); + QString getText()const; +private: + QLineEdit* m_lineEdit; + QtProperty* m_property; +}; + +#endif // STRINGDIALOGEDITORFACTORY_H diff --git a/Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringEditorFactory.h similarity index 62% rename from Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.h rename to Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringEditorFactory.h index d323a42f27bd..bd8440bc9fef 100644 --- a/Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/StringEditorFactory.h @@ -4,18 +4,19 @@ #include "qtpropertymanager.h" #include -class QT_QTPROPERTYBROWSER_EXPORT StringEditorFactory : public QtAbstractEditorFactory +class StringEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: StringEditorFactory(QObject *parent = 0): QtAbstractEditorFactory(parent){} protected: - void connectPropertyManager(QtStringPropertyManager *manager); + using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning + void connectPropertyManager(QtStringPropertyManager *){} QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent); - void disconnectPropertyManager(QtStringPropertyManager *manager); + void disconnectPropertyManager(QtStringPropertyManager *){} }; -class QT_QTPROPERTYBROWSER_EXPORT StringEditor: public QLineEdit +class StringEditor: public QLineEdit { Q_OBJECT public: diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/WorkspaceEditorFactory.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/WorkspaceEditorFactory.h new file mode 100644 index 000000000000..c8149af175b2 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/WorkspaceEditorFactory.h @@ -0,0 +1,38 @@ +#ifndef STRINGEDITORFACTORY_H +#define STRINGEDITORFACTORY_H + +#include "qtpropertymanager.h" +#include "MantidQtMantidWidgets/WorkspaceSelector.h" + +namespace MantidQt +{ +namespace MantidWidgets +{ + +class WorkspaceEditorFactory : public QtAbstractEditorFactory +{ + Q_OBJECT +public: + WorkspaceEditorFactory(QObject *parent = 0): QtAbstractEditorFactory(parent){} +protected: + using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning + void connectPropertyManager(QtStringPropertyManager *){} + QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent); + void disconnectPropertyManager(QtStringPropertyManager *){} +}; + +class WorkspaceEditor: public WorkspaceSelector +{ + Q_OBJECT +public: + WorkspaceEditor(QtProperty *property, QWidget *parent); +protected slots: + void updateProperty(const QString& text); +private: + QtProperty* m_property; +}; + +} +} + +#endif // STRINGEDITORFACTORY_H diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/DataSelector.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/DataSelector.cpp index c75598f00ec2..85b1a95b8b33 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/DataSelector.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/DataSelector.cpp @@ -57,15 +57,24 @@ namespace MantidQt } /** - * Get whether file or workspace input is currently being shown. + * Get if the file selector is currently being shown. * - * Returns 0 for file view and 1 for workspace view + * @return :: true if it is visible, otherwise false + */ + bool DataSelector::isFileSelectorVisible() const + { + int index = m_uiForm.stackedDataSelect->currentIndex(); + return ( index == 0 ); + } + + /** + * Get if the workspace selector is currently being shown. * - * @return :: index of the visible view + * @return :: true if it is visible, otherwise false */ - int DataSelector::getCurrentView() const + bool DataSelector::isWorkspaceSelectorVisible() const { - return m_uiForm.stackedDataSelect->currentIndex(); + return !isFileSelectorVisible(); } /** @@ -76,25 +85,73 @@ namespace MantidQt * * @return :: If the data selector is valid */ - bool DataSelector::isValid() const + bool DataSelector::isValid() { + using namespace Mantid::API; + bool isValid = false; - switch(getCurrentView()) + if(isFileSelectorVisible()) { - case 0: - // file view is visible - isValid = m_uiForm.rfFileInput->isValid(); - break; - case 1: - // workspace view is visible - isValid = m_uiForm.wsWorkspaceInput->isValid(); - break; + isValid = m_uiForm.rfFileInput->isValid(); + + //check to make sure the user hasn't deleted the auto-loaded file + //since choosing it. + if(isValid && m_autoLoad) + { + const QString wsName = getCurrentDataName(); + + if(!AnalysisDataService::Instance().doesExist(wsName.toStdString())) + { + //attempt to reload if we can + //don't use algorithm runner because we need to know instantly. + const QString filepath = m_uiForm.rfFileInput->getFirstFilename(); + const Algorithm_sptr loadAlg = AlgorithmManager::Instance().createUnmanaged("Load"); + loadAlg->initialize(); + loadAlg->setProperty("Filename", filepath.toStdString()); + loadAlg->setProperty("OutputWorkspace", wsName.toStdString()); + loadAlg->execute(); + + isValid = AnalysisDataService::Instance().doesExist(wsName.toStdString()); + + if(!isValid) + { + m_uiForm.rfFileInput->setFileProblem("The specified workspace is missing from the analysis data service"); + } + } + } + } + else + { + isValid = m_uiForm.wsWorkspaceInput->isValid(); } return isValid; } + /** + * Return the error. + * @returns A string explaining the error. + */ + QString DataSelector::getProblem() const + { + using namespace Mantid::API; + + QString problem = ""; + const QString wsName = getCurrentDataName(); + + if(isFileSelectorVisible()) + { + problem = m_uiForm.rfFileInput->getFileProblem(); + } + else + { + problem = "A valid workspace has not been selected"; + } + + return problem; + } + /** * Attempt to load a file if the widget is set to attempt auto-loading * @@ -187,7 +244,7 @@ namespace MantidQt * * @return The full file path */ - QString DataSelector::getFullFilePath() + QString DataSelector::getFullFilePath() const { return m_uiForm.rfFileInput->getFirstFilename(); } @@ -202,7 +259,7 @@ namespace MantidQt * * @return The name of the current data item */ - QString DataSelector::getCurrentDataName() + QString DataSelector::getCurrentDataName() const { QString filename(""); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/FilenameDialogEditor.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/FilenameDialogEditor.cpp new file mode 100644 index 000000000000..cdc2d36e8282 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/src/FilenameDialogEditor.cpp @@ -0,0 +1,27 @@ +#include "MantidQtMantidWidgets/FilenameDialogEditor.h" + +#include +#include + +namespace MantidQt +{ +namespace MantidWidgets +{ + +/** + * Open a file dialog to choose a file. Update the property if a file was selected. + */ +void FilenameDialogEditor::runDialog() +{ + QSettings settings; + QString dir = settings.value("Mantid/FitBrowser/ResolutionDir").toString(); + QString StringDialog = QFileDialog::getOpenFileName(this, tr("Open File"),dir); + if (!StringDialog.isEmpty()) + { + setText(StringDialog); + updateProperty(); + } +} + +} +} diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/FitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/FitPropertyBrowser.cpp index 5fa4d943b82f..6e48c5865d0c 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/FitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/FitPropertyBrowser.cpp @@ -25,10 +25,14 @@ #include "MantidAPI/CostFunctionFactory.h" #include "MantidAPI/ICostFunction.h" -#include "MantidQtMantidWidgets/UserFunctionDialog.h" +#include "MantidQtMantidWidgets/FilenameDialogEditor.h" +#include "MantidQtMantidWidgets/FormulaDialogEditor.h" +#include "MantidQtMantidWidgets/StringEditorFactory.h" #include "qttreepropertybrowser.h" #include "qtpropertymanager.h" +#include "ParameterPropertyManager.h" + // Suppress a warning coming out of code that isn't ours #if defined(__INTEL_COMPILER) #pragma warning disable 1125 @@ -39,8 +43,6 @@ #pragma GCC diagnostic ignored "-Woverloaded-virtual" #endif #include "qteditorfactory.h" -#include "StringEditorFactory.h" -#include "StringDialogEditorFactory.h" #include "DoubleEditorFactory.h" #if defined(__INTEL_COMPILER) #pragma warning enable 1125 @@ -78,38 +80,6 @@ namespace MantidWidgets { -class FormulaDialogEditor: public StringDialogEditor -{ -public: - FormulaDialogEditor(QtProperty *property, QWidget *parent) - :StringDialogEditor(property,parent){} -protected slots: - void runDialog() - { - MantidQt::MantidWidgets::UserFunctionDialog *dlg = new MantidQt::MantidWidgets::UserFunctionDialog((QWidget*)parent(),getText()); - if (dlg->exec() == QDialog::Accepted) - { - setText(dlg->getFormula()); - updateProperty(); - }; - } -}; - - -class FormulaDialogEditorFactory: public StringDialogEditorFactory -{ -public: - FormulaDialogEditorFactory(QObject* parent):StringDialogEditorFactory(parent){} -protected: - using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning - QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent) - { - (void) manager; //Avoid unused warning - return new FormulaDialogEditor(property,parent); - } -}; - - /** * Constructor * @param parent :: The parent widget - must be an ApplicationWindow @@ -185,6 +155,7 @@ m_mantidui(mantidui) m_vectorManager = new QtGroupPropertyManager(w); m_vectorSizeManager = new QtIntPropertyManager(w); m_vectorDoubleManager = new QtDoublePropertyManager(w); + m_parameterManager = new ParameterPropertyManager(w); } @@ -242,6 +213,11 @@ void FitPropertyBrowser::init() QVariant(false)).toBool(); m_boolManager->setValue(m_convolveMembers, convolveCompositeItems); + m_showParamErrors = m_boolManager->addProperty("Show Parameter Errors"); + bool showParamErrors = settings.value(m_showParamErrors->propertyName(), false).toBool(); + m_boolManager->setValue(m_showParamErrors, showParamErrors); + m_parameterManager->setErrorsEnabled(showParamErrors); + m_xColumn = m_columnManager->addProperty("XColumn"); m_yColumn = m_columnManager->addProperty("YColumn"); m_errColumn = m_columnManager->addProperty("ErrColumn"); @@ -259,6 +235,7 @@ void FitPropertyBrowser::init() settingsGroup->addSubProperty(m_plotDiff); settingsGroup->addSubProperty(m_plotCompositeMembers); settingsGroup->addSubProperty(m_convolveMembers); + settingsGroup->addSubProperty(m_showParamErrors); /* Create editors and assign them to the managers */ createEditors(w); @@ -298,6 +275,7 @@ void FitPropertyBrowser::initLayout(QWidget *w) connect(m_formulaManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(stringChanged(QtProperty*))); connect(m_columnManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(columnChanged(QtProperty*))); connect(m_vectorDoubleManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(vectorDoubleChanged(QtProperty*))); + connect(m_parameterManager,SIGNAL(propertyChanged(QtProperty*)), this, SLOT(parameterChanged(QtProperty*))); QVBoxLayout* layout = new QVBoxLayout(w); QGridLayout* buttonsLayout = new QGridLayout(); @@ -433,7 +411,7 @@ void FitPropertyBrowser::createEditors(QWidget *w) QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w); DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w); StringEditorFactory* stringEditFactory = new StringEditorFactory(w); - StringDialogEditorFactory* stringDialogEditFactory = new StringDialogEditorFactory(w); + FilenameDialogEditorFactory* filenameDialogEditorFactory = new FilenameDialogEditorFactory(w); FormulaDialogEditorFactory* formulaDialogEditFactory = new FormulaDialogEditorFactory(w); m_browser = new QtTreePropertyBrowser(); @@ -442,11 +420,12 @@ void FitPropertyBrowser::createEditors(QWidget *w) m_browser->setFactoryForManager(m_intManager, spinBoxFactory); m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory); m_browser->setFactoryForManager(m_stringManager, stringEditFactory); - m_browser->setFactoryForManager(m_filenameManager, stringDialogEditFactory); + m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory); m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory); m_browser->setFactoryForManager(m_columnManager, comboBoxFactory); m_browser->setFactoryForManager(m_vectorSizeManager, spinBoxFactory); m_browser->setFactoryForManager(m_vectorDoubleManager, doubleEditorFactory); + m_browser->setFactoryForManager(m_parameterManager, new ParameterEditorFactory(w)); } @@ -1221,11 +1200,19 @@ void FitPropertyBrowser::boolChanged(QtProperty* prop) { if ( ! m_changeSlotsEnabled ) return; - if ( prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData ) + if ( prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData + || prop == m_showParamErrors ) { + bool val = m_boolManager->value(prop); + QSettings settings; settings.beginGroup("Mantid/FitBrowser"); - settings.setValue(prop->propertyName(), m_boolManager->value(prop)); + settings.setValue(prop->propertyName(), val); + + if ( m_showParamErrors ) + { + m_parameterManager->setErrorsEnabled(val); + } } else {// it could be an attribute @@ -1304,10 +1291,6 @@ void FitPropertyBrowser::doubleChanged(QtProperty* prop) emit xRangeChanged(startX(), endX()); return; } - else if(getHandler()->setParameter(prop)) - { - return; - } else {// check if it is a constraint PropertyHandler* h = getHandler()->findHandler(prop); @@ -1333,6 +1316,19 @@ void FitPropertyBrowser::doubleChanged(QtProperty* prop) } } } + +/** + * Called when one of the parameter values gets changed. This could be caused either by user setting + * the value or programmatically. + * @param prop :: Parameter property which value got changed + */ +void FitPropertyBrowser::parameterChanged(QtProperty* prop) +{ + if ( ! m_changeSlotsEnabled ) return; + + getHandler()->setParameter(prop); +} + /** Called when a string property changed * @param prop :: A pointer to the property */ @@ -1820,7 +1816,8 @@ void FitPropertyBrowser::vectorDoubleChanged(QtProperty *prop) h->setVectorAttribute(prop); } -/** Update the function parameter properties. +/** + * Update the function parameter properties */ void FitPropertyBrowser::updateParameters() { @@ -1863,14 +1860,19 @@ void FitPropertyBrowser::getFitResults() try { std::string name; - double value; - row >> name >> value; + double value, error; + row >> name >> value >> error; + // In case of a single function Fit doesn't create a CompositeFunction if (count() == 1) { name.insert(0,"f0."); } - compositeFunction()->setParameter(name,value); + + size_t paramIndex = compositeFunction()->parameterIndex(name); + + compositeFunction()->setParameter(paramIndex,value); + compositeFunction()->setError(paramIndex, error); } catch(...) { @@ -1879,6 +1881,7 @@ void FitPropertyBrowser::getFitResults() } while(row.next()); updateParameters(); + getHandler()->updateErrors(); } } @@ -1894,6 +1897,7 @@ void FitPropertyBrowser::undoFit() compositeFunction()->setParameter(i,m_initialParameters[i]); } updateParameters(); + getHandler()->clearErrors(); } disableUndo(); } diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/FormulaDialogEditor.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/FormulaDialogEditor.cpp new file mode 100644 index 000000000000..171de1eb57a3 --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/src/FormulaDialogEditor.cpp @@ -0,0 +1,26 @@ +#include "MantidQtMantidWidgets/FormulaDialogEditor.h" +#include "MantidQtMantidWidgets/UserFunctionDialog.h" + +#include +#include + +namespace MantidQt +{ +namespace MantidWidgets +{ + +/** + * Open a UserFunctionDialog. Update the property if a file was selected. + */ +void FormulaDialogEditor::runDialog() +{ + MantidQt::MantidWidgets::UserFunctionDialog *dlg = new MantidQt::MantidWidgets::UserFunctionDialog((QWidget*)parent(),getText()); + if (dlg->exec() == QDialog::Accepted) + { + setText(dlg->getFormula()); + updateProperty(); + } +} + +} +} diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp index a741f24bde5c..bdb4481dc5b2 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp @@ -23,6 +23,9 @@ #include "MantidAPI/ICostFunction.h" #include "MantidQtMantidWidgets/UserFunctionDialog.h" +#include "MantidQtMantidWidgets/FilenameDialogEditor.h" +#include "MantidQtMantidWidgets/FormulaDialogEditor.h" +#include "MantidQtMantidWidgets/WorkspaceEditorFactory.h" #include "qttreepropertybrowser.h" #include "qtpropertymanager.h" @@ -36,7 +39,6 @@ #pragma GCC diagnostic ignored "-Woverloaded-virtual" #endif #include "qteditorfactory.h" -#include "StringDialogEditorFactory.h" #include "DoubleEditorFactory.h" #if defined(__INTEL_COMPILER) #pragma warning enable 1125 @@ -69,41 +71,6 @@ namespace MantidQt namespace MantidWidgets { -namespace -{ - -class FormulaDialogEditor: public StringDialogEditor -{ -public: - FormulaDialogEditor(QtProperty *property, QWidget *parent) - :StringDialogEditor(property,parent){} -protected slots: - void runDialog() - { - MantidQt::MantidWidgets::UserFunctionDialog *dlg = new MantidQt::MantidWidgets::UserFunctionDialog((QWidget*)parent(),getText()); - if (dlg->exec() == QDialog::Accepted) - { - setText(dlg->getFormula()); - updateProperty(); - }; - } -}; - -class FormulaDialogEditorFactory: public StringDialogEditorFactory -{ -public: - FormulaDialogEditorFactory(QObject* parent):StringDialogEditorFactory(parent){} -protected: - using QtAbstractEditorFactoryBase::createEditor; // Avoid Intel compiler warning - QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent) - { - (void) manager; //Avoid unused warning - return new FormulaDialogEditor(property,parent); - } -}; - -} - /** * Constructor * @param parent :: The parent widget. @@ -144,7 +111,9 @@ void FunctionBrowser::createBrowser() m_indexManager = new QtStringPropertyManager(this); m_tieManager = new QtStringPropertyManager(this); m_constraintManager = new QtStringPropertyManager(this); + m_filenameManager = new QtStringPropertyManager(this); m_formulaManager = new QtStringPropertyManager(this); + m_workspaceManager = new QtStringPropertyManager(this); m_attributeVectorManager = new QtGroupPropertyManager(this); m_attributeSizeManager = new QtIntPropertyManager(this); m_attributeVectorDoubleManager = new QtDoublePropertyManager(this); @@ -154,8 +123,9 @@ void FunctionBrowser::createBrowser() DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(this); QtLineEditFactory *lineEditFactory = new QtLineEditFactory(this); QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(this); - //StringDialogEditorFactory* stringDialogEditFactory = new StringDialogEditorFactory(this); + FilenameDialogEditorFactory* filenameDialogEditorFactory = new FilenameDialogEditorFactory(this); FormulaDialogEditorFactory* formulaDialogEditFactory = new FormulaDialogEditorFactory(this); + WorkspaceEditorFactory* workspaceEditorFactory = new WorkspaceEditorFactory(this); m_browser = new QtTreePropertyBrowser(); // assign factories to property managers @@ -167,7 +137,9 @@ void FunctionBrowser::createBrowser() m_browser->setFactoryForManager(m_indexManager, lineEditFactory); m_browser->setFactoryForManager(m_tieManager, lineEditFactory); m_browser->setFactoryForManager(m_constraintManager, lineEditFactory); + m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory); m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory); + m_browser->setFactoryForManager(m_workspaceManager, workspaceEditorFactory); m_browser->setFactoryForManager(m_attributeSizeManager, spinBoxFactory); m_browser->setFactoryForManager(m_attributeVectorDoubleManager, doubleEditorFactory); @@ -180,6 +152,7 @@ void FunctionBrowser::createBrowser() connect(m_attributeIntManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(attributeChanged(QtProperty*))); connect(m_attributeBoolManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(attributeChanged(QtProperty*))); connect(m_formulaManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(attributeChanged(QtProperty*))); + connect(m_filenameManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(attributeChanged(QtProperty*))); connect(m_attributeVectorDoubleManager,SIGNAL(propertyChanged(QtProperty*)),this,SLOT(attributeVectorDoubleChanged(QtProperty*))); } @@ -467,11 +440,21 @@ class CreateAttributePropertyForFunctionBrowser: public Mantid::API::IFunction:: FunctionBrowser::AProperty apply(const std::string& str)const { QtProperty* prop = NULL; - if ( m_attName == "Formula" ) + if (m_attName == "FileName") + { + prop = m_browser->m_filenameManager->addProperty(m_attName); + m_browser->m_filenameManager->setValue(prop, QString::fromStdString(str)); + } + else if ( m_attName == "Formula" ) { prop = m_browser->m_formulaManager->addProperty(m_attName); m_browser->m_formulaManager->setValue(prop, QString::fromStdString(str)); } + else if ( m_attName == "Workspace" ) + { + prop = m_browser->m_workspaceManager->addProperty(m_attName); + m_browser->m_workspaceManager->setValue(prop, QString::fromStdString(str)); + } else { prop = m_browser->m_attributeStringManager->addProperty(m_attName); @@ -546,10 +529,18 @@ class SetAttributeFromProperty: public Mantid::API::IFunction::AttributeVisitor< void apply(std::string& str)const { QString attName = m_prop->propertyName(); - if ( attName == "Formula" ) + if ( attName == "FileName" ) + { + str = m_browser->m_filenameManager->value(m_prop).toStdString(); + } + else if ( attName == "Formula" ) { str = m_browser->m_formulaManager->value(m_prop).toStdString(); } + else if ( attName == "Workspace" ) + { + str = m_browser->m_workspaceManager->value(m_prop).toStdString(); + } else { str = m_browser->m_attributeStringManager->value(m_prop).toStdString(); @@ -747,7 +738,9 @@ bool FunctionBrowser::isStringAttribute(QtProperty* prop) const { return prop && ( dynamic_cast(m_attributeStringManager) == prop->propertyManager() || - dynamic_cast(m_formulaManager) == prop->propertyManager() + dynamic_cast(m_formulaManager) == prop->propertyManager() || + dynamic_cast(m_filenameManager) == prop->propertyManager() || + dynamic_cast(m_workspaceManager) == prop->propertyManager() ); } @@ -1307,7 +1300,15 @@ Mantid::API::IFunction_sptr FunctionBrowser::getFunction(QtProperty* prop, bool SetAttributeFromProperty setter(this,child); Mantid::API::IFunction::Attribute attr = fun->getAttribute(attName); attr.apply(setter); - fun->setAttribute(attName,attr); + try + { + fun->setAttribute(attName,attr); + } + catch(std::exception& expt) + { + QMessageBox::critical(this,"MantidPlot - Error", "Cannot set attribute " + QString::fromStdString(attName) + + " of function " + prop->propertyName() + ":\n\n" + QString::fromStdString(expt.what())); + } } else if (!attributesOnly && isParameter(child)) { diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp index a2f4318128e4..d23ef81271d8 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MuonFitPropertyBrowser.cpp @@ -1,6 +1,7 @@ #include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h" #include "MantidQtMantidWidgets/PropertyHandler.h" #include "MantidAPI/FunctionFactory.h" +#include "MantidQtMantidWidgets/StringEditorFactory.h" // Suppress a warning coming out of code that isn't ours #if defined(__INTEL_COMPILER) @@ -13,7 +14,6 @@ #endif #include "DoubleEditorFactory.h" #include "qteditorfactory.h" -#include "StringDialogEditorFactory.h" #if defined(__INTEL_COMPILER) #pragma warning enable 1125 #elif defined(__GNUC__) @@ -111,12 +111,22 @@ void MuonFitPropertyBrowser::init() // Custom settings that are specific and asked for by the muon scientists. QtProperty* customSettingsGroup = m_groupManager->addProperty("Settings"); + m_rawData = m_boolManager->addProperty("Fit To Raw Data"); bool data = settings.value("Fit To Raw Data",QVariant(false)).toBool(); m_boolManager->setValue(m_rawData,data); + + m_showParamErrors = m_boolManager->addProperty("Show Parameter Errors"); + // XXX: showParamErrors is true by default for Muons + bool showParamErrors = settings.value(m_showParamErrors->propertyName(), true).toBool(); + m_boolManager->setValue(m_showParamErrors, showParamErrors); + m_parameterManager->setErrorsEnabled(showParamErrors); + customSettingsGroup->addSubProperty(m_minimizer); customSettingsGroup->addSubProperty(m_plotDiff); customSettingsGroup->addSubProperty(m_rawData); + customSettingsGroup->addSubProperty(m_showParamErrors); + m_customSettingsGroup = m_browser->addProperty(customSettingsGroup); // Initialise the layout. @@ -167,10 +177,6 @@ void MuonFitPropertyBrowser::doubleChanged(QtProperty* prop) emit xRangeChanged(startX(), endX()); return; } - else if(getHandler()->setParameter(prop)) - { - return; - } else {// check if it is a constraint MantidQt::MantidWidgets::PropertyHandler* h = getHandler()->findHandler(prop); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/PropertyHandler.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/PropertyHandler.cpp index 04e39ce10b9c..8beda4585245 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/PropertyHandler.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/PropertyHandler.cpp @@ -18,6 +18,7 @@ #include "qttreepropertybrowser.h" #include "qtpropertymanager.h" +#include "ParameterPropertyManager.h" #include #include @@ -141,8 +142,9 @@ void PropertyHandler::init() } } - m_browser->m_changeSlotsEnabled = true; + onFunctionStructChanged(); + m_browser->m_changeSlotsEnabled = true; } /** @@ -247,13 +249,11 @@ void PropertyHandler::initParameters() { QString parName = QString::fromStdString(function()->parameterName(i)); if (parName.contains('.')) continue; - QtProperty* prop = m_browser->addDoubleProperty(parName); - QString toolTip = QString::fromStdString(function()->parameterDescription(i)); - if (!toolTip.isEmpty()) - { - prop->setToolTip(toolTip); - } - m_browser->m_doubleManager->setValue(prop,function()->getParameter(i)); + QtProperty* prop = m_browser->addDoubleProperty(parName, m_browser->m_parameterManager); + + m_browser->m_parameterManager->setDescription(prop, function()->parameterDescription(i)); + m_browser->m_parameterManager->setValue(prop,function()->getParameter(i)); + m_item->property()->addSubProperty(prop); m_parameters << prop; // add tie property if this parameter has a tie @@ -479,6 +479,9 @@ PropertyHandler* PropertyHandler::addFunction(const std::string& fnName) } m_browser->setFocus(); m_browser->setCurrentFunction(h); + + onFunctionStructChanged(); + return h; } @@ -505,6 +508,7 @@ void PropertyHandler::removeFunction() } } ph->renameChildren(); + ph->onFunctionStructChanged(); } } @@ -571,6 +575,41 @@ QString PropertyHandler::functionPrefix()const return ""; } +/** + * For non-composite functions is equal to function()->name(). + * @return High-level structure string, e.g. ((Gaussian * Lorentzian) + FlatBackground) + */ +QString PropertyHandler::functionStructure() const +{ + if ( m_cf && (m_cf->name() == "CompositeFunction" || m_cf->name() == "ProductFunction") ) + { + QStringList children; + + for (size_t i = 0; i < m_cf->nFunctions(); ++i) + { + children << getHandler(i)->functionStructure(); + } + + if ( children.empty() ) + { + return QString::fromStdString("Empty " + m_cf->name()); + } + + QChar op('+'); + + if (m_cf->name() == "ProductFunction") + { + op = '*'; + } + + return QString("(%1)").arg(children.join(' ' + op + ' ')); + } + else + { + return QString::fromStdString(function()->name()); + } +} + // Return the parent handler PropertyHandler* PropertyHandler::parentHandler()const { @@ -682,7 +721,7 @@ bool PropertyHandler::setParameter(QtProperty* prop) if (m_parameters.contains(prop)) { std::string parName = prop->propertyName().toStdString(); - double parValue = m_browser->m_doubleManager->value(prop); + double parValue = m_browser->m_parameterManager->value(prop); m_fun->setParameter(parName,parValue); m_browser->sendParameterChanged(m_fun.get()); return true; @@ -920,26 +959,68 @@ void PropertyHandler::setVectorAttribute(QtProperty *prop) } /** -* Update the parameter properties -*/ -void PropertyHandler::updateParameters() + * Applies given function to all the parameter properties recursively, within this context. + * @param func :: Function to apply + */ +void PropertyHandler::applyToAllParameters(void (PropertyHandler::*func)(QtProperty*)) { for(int i=0;ipropertyName().toStdString(); - double parValue = function()->getParameter(parName); - m_browser->m_doubleManager->setValue(prop,parValue); + (this->*(func))(prop); } + if (m_cf) { for(size_t i=0;inFunctions();i++) { - getHandler(i)->updateParameters(); + getHandler(i)->applyToAllParameters(func); } } } +void PropertyHandler::updateParameters() +{ + applyToAllParameters(&PropertyHandler::updateParameter); +} + +void PropertyHandler::updateErrors() +{ + applyToAllParameters(&PropertyHandler::updateError); +} + +void PropertyHandler::clearErrors() +{ + applyToAllParameters(&PropertyHandler::clearError); +} + +/** + * @param prop :: Property of the parameter + */ +void PropertyHandler::updateParameter(QtProperty* prop) +{ + double parValue = function()->getParameter(prop->propertyName().toStdString()); + m_browser->m_parameterManager->setValue(prop, parValue); +} + +/** + * @param prop :: Property of the parameter + */ +void PropertyHandler::updateError(QtProperty* prop) +{ + size_t index = function()->parameterIndex(prop->propertyName().toStdString()); + double error = function()->getError(index); + m_browser->m_parameterManager->setError(prop, error); +} + +/** + * @param prop :: Property of the parameter + */ +void PropertyHandler::clearError(QtProperty* prop) +{ + m_browser->m_parameterManager->clearError(prop); +} + /** * Change the type of the function (replace the function) * @param prop :: The "Type" property with new value @@ -1117,7 +1198,7 @@ void PropertyHandler::fix(const QString& parName) { QtProperty* parProp = getParameterProperty(parName); if (!parProp) return; - QString parValue = QString::number(m_browser->m_doubleManager->value(parProp)); + QString parValue = QString::number(m_browser->m_parameterManager->value(parProp)); try { m_fun->tie(parName.toStdString(),parValue.toStdString()); @@ -1442,6 +1523,17 @@ void PropertyHandler::plotRemoved() m_hasPlot = false; } +void PropertyHandler::onFunctionStructChanged() +{ + // Update structural tooltip of oneself + m_item->property()->setToolTip(functionStructure()); + + // If is handler of child function, make sure ancestors are updated as well + if (PropertyHandler* h = parentHandler()) + { + h->onFunctionStructChanged(); + } +} /** * Remove all plots including children's diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/SequentialFitDialog.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/SequentialFitDialog.cpp index 16bc8d602418..e92884258fa5 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/SequentialFitDialog.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/SequentialFitDialog.cpp @@ -45,6 +45,8 @@ QDialog(fitBrowser),m_fitBrowser(fitBrowser) connect(ui.btnCancel,SIGNAL(clicked()),this,SLOT(reject())); connect(ui.btnHelp,SIGNAL(clicked()),this,SLOT(helpClicked())); connect(ui.ckbLogPlot,SIGNAL(toggled(bool)),this,SLOT(plotAgainstLog(bool))); + connect(ui.ckCreateOutput,SIGNAL(toggled(bool)),ui.ckOutputCompMembers,SLOT(setEnabled(bool))); + connect(ui.ckCreateOutput,SIGNAL(toggled(bool)),ui.ckConvolveMembers,SLOT(setEnabled(bool))); ui.cbLogValue->setEditable(true); ui.ckbLogPlot->setChecked(true); @@ -337,6 +339,8 @@ void SequentialFitDialog::accept() alg->setPropertyValue("OutputWorkspace",m_fitBrowser->outputName()); alg->setPropertyValue("Function",funStr); alg->setProperty("CreateOutput", ui.ckCreateOutput->isChecked()); + alg->setProperty("OutputCompositeMembers", ui.ckOutputCompMembers->isChecked()); + alg->setProperty("ConvolveMembers", ui.ckConvolveMembers->isChecked()); if (ui.ckbLogPlot->isChecked()) { std::string logName = ui.cbLogValue->currentText().toStdString(); diff --git a/Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/StringDialogEditor.cpp similarity index 70% rename from Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.cpp rename to Code/Mantid/MantidQt/MantidWidgets/src/StringDialogEditor.cpp index 241b00cf48e8..e84f62ba4442 100644 --- a/Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/StringDialogEditor.cpp @@ -1,4 +1,4 @@ -#include "StringDialogEditorFactory.h" +#include "MantidQtMantidWidgets/StringDialogEditor.h" #include #include @@ -10,22 +10,25 @@ #include -void StringDialogEditorFactory::connectPropertyManager(QtStringPropertyManager *manager) +/** + * Do nothing to connect a manager. + */ +void StringDialogEditorFactory::connectPropertyManager(QtStringPropertyManager*) { - (void) manager; } -QWidget* StringDialogEditorFactory::createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent) +/** + * Do nothing to disconnect a manager - it was never connected. + */ +void StringDialogEditorFactory::disconnectPropertyManager(QtStringPropertyManager*) { - (void) manager; - return new StringDialogEditor(property,parent); -} - -void StringDialogEditorFactory::disconnectPropertyManager(QtStringPropertyManager *manager) -{ - (void) manager; } +/** + * Constructor. + * @param property :: A property to edit. + * @param parent :: A widget parent for the editor widget. + */ StringDialogEditor::StringDialogEditor(QtProperty *property, QWidget *parent):QWidget(parent),m_property(property) { QHBoxLayout *layout = new QHBoxLayout; @@ -49,23 +52,18 @@ StringDialogEditor::StringDialogEditor(QtProperty *property, QWidget *parent):QW this->setLayout(layout); } -void StringDialogEditor::runDialog() -{ - QSettings settings; - QString dir = settings.value("Mantid/FitBrowser/ResolutionDir").toString(); - QString StringDialog = QFileDialog::getOpenFileName(this, tr("Open File"),dir); - if (!StringDialog.isEmpty()) - { - m_lineEdit->setText(StringDialog); - updateProperty(); - } -} - +/** + * Set the text in the editor. + * @param txt :: A text to set. + */ void StringDialogEditor::setText(const QString& txt) { m_lineEdit->setText(txt); } +/** + * Get the current text inside the editor. + */ QString StringDialogEditor::getText()const { return m_lineEdit->text(); @@ -75,6 +73,9 @@ StringDialogEditor::~StringDialogEditor() { } +/** + * Slot which sets the property with the current text in the editor. + */ void StringDialogEditor::updateProperty() { QtStringPropertyManager* mgr = dynamic_cast(m_property->propertyManager()); diff --git a/Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/StringEditorFactory.cpp similarity index 78% rename from Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.cpp rename to Code/Mantid/MantidQt/MantidWidgets/src/StringEditorFactory.cpp index 48eeb1e8ba76..0669578253ea 100644 --- a/Code/Mantid/QtPropertyBrowser/src/StringEditorFactory.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/StringEditorFactory.cpp @@ -1,18 +1,10 @@ -#include "StringEditorFactory.h" - -void StringEditorFactory::connectPropertyManager(QtStringPropertyManager *) -{ -} +#include "MantidQtMantidWidgets/StringEditorFactory.h" QWidget* StringEditorFactory::createEditor(QtStringPropertyManager *, QtProperty *property,QWidget *parent) { return new StringEditor(property,parent); } -void StringEditorFactory::disconnectPropertyManager(QtStringPropertyManager *) -{ -} - StringEditor::StringEditor(QtProperty *property, QWidget *parent):QLineEdit(parent),m_property(property) { connect(this,SIGNAL(editingFinished()),this,SLOT(updateProperty())); diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/WorkspaceEditorFactory.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/WorkspaceEditorFactory.cpp new file mode 100644 index 000000000000..4b38c967604f --- /dev/null +++ b/Code/Mantid/MantidQt/MantidWidgets/src/WorkspaceEditorFactory.cpp @@ -0,0 +1,32 @@ +#include "MantidQtMantidWidgets/WorkspaceEditorFactory.h" + +namespace MantidQt +{ +namespace MantidWidgets +{ + +QWidget* WorkspaceEditorFactory::createEditor(QtStringPropertyManager *, QtProperty *property,QWidget *parent) +{ + return new WorkspaceEditor(property,parent); +} + +WorkspaceEditor::WorkspaceEditor(QtProperty *property, QWidget *parent):WorkspaceSelector(parent),m_property(property) +{ + this->insertItem("",0); + updateProperty(this->text(0)); + this->setCurrentIndex(0); + connect(this,SIGNAL(currentIndexChanged(const QString&)),this,SLOT(updateProperty(const QString&))); +} + +void WorkspaceEditor::updateProperty(const QString& text) +{ + QtStringPropertyManager* mgr = dynamic_cast(m_property->propertyManager()); + if (mgr) + { + mgr->setValue(m_property,text); + } +} + +} +} + diff --git a/Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp b/Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp index 5e647ba9e205..bc44e1a4c3bf 100644 --- a/Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp +++ b/Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp @@ -1,4 +1,5 @@ #include "MantidAPI/AnalysisDataService.h" +#include "MantidAPI/CoordTransform.h" #include "MantidAPI/IMDEventWorkspace.h" #include "MantidAPI/IMDIterator.h" #include "MantidAPI/MatrixWorkspace.h" diff --git a/Code/Mantid/QtPropertyBrowser/CMakeLists.txt b/Code/Mantid/QtPropertyBrowser/CMakeLists.txt index cd618aeb387e..1602611929ef 100644 --- a/Code/Mantid/QtPropertyBrowser/CMakeLists.txt +++ b/Code/Mantid/QtPropertyBrowser/CMakeLists.txt @@ -20,9 +20,8 @@ set( QTPROPERTYBROWSER_SRCS src/qtbuttonpropertybrowser.cpp src/qtgroupboxpropertybrowser.cpp src/qtpropertybrowserutils.cpp - src/DoubleEditorFactory.cpp - src/StringDialogEditorFactory.cpp - src/StringEditorFactory.cpp + src/DoubleEditorFactory.cpp + src/ParameterPropertyManager.cpp ) # moc'd files will end up in build directory, so add to include path @@ -104,8 +103,7 @@ set ( ) qt4_wrap_cpp ( EXTRA_MOCS src/DoubleEditorFactory.h - src/StringDialogEditorFactory.h - src/StringEditorFactory.h + src/ParameterPropertyManager.h ) set ( diff --git a/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.cpp b/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.cpp index 5d3d17644699..666130ec533e 100644 --- a/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.cpp +++ b/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.cpp @@ -1,5 +1,7 @@ #include "DoubleEditorFactory.h" +#include "ParameterPropertyManager.h" + #include #include @@ -8,27 +10,12 @@ #include #include -void DoubleEditorFactory::connectPropertyManager(QtDoublePropertyManager *manager) -{ - (void) manager; -} - -QWidget* DoubleEditorFactory::createEditor(QtDoublePropertyManager *manager, QtProperty *property,QWidget *parent) -{ - (void) manager; - return new DoubleEditor(property,parent); -} - -void DoubleEditorFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) -{ - (void) manager; -} DoubleEditor::DoubleEditor(QtProperty *property, QWidget *parent) :QLineEdit(parent), m_property(property) { - QtDoublePropertyManager* mgr = dynamic_cast(property->propertyManager()); + auto mgr = dynamic_cast(property->propertyManager()); if (!mgr) { throw std::runtime_error("QtDoublePropertyManager expected as parent of DoubleEditor"); @@ -51,17 +38,48 @@ DoubleEditor::~DoubleEditor() void DoubleEditor::setValue(const double& d) { - double absVal = fabs(d); - char format = absVal > 1e5 || (absVal != 0 && absVal < 1e-5) ? 'e' : 'f'; - setText(QString::number(d,format , m_decimals)); + setText(formatValue(d)); } void DoubleEditor::updateProperty() { - QtDoublePropertyManager* mgr = dynamic_cast(m_property->propertyManager()); + auto mgr = dynamic_cast(m_property->propertyManager()); if (mgr) { mgr->setValue(m_property,text().toDouble()); } } +/** + * @param d :: The value to format + * @return Formatted string representation of the value + */ +QString DoubleEditor::formatValue(const double& d) const +{ + // XXX: this is taken from QtDoublePropertyManager. Ideally, QtDoublePropertyManager should be + // refactored to haves such a method, but it doesn't seem to be a good idea to edit it heavily. + double absVal = fabs(d); + char format = absVal > 1e5 || (absVal != 0 && absVal < 1e-5) ? 'e' : 'f'; + return QString::number(d, format, m_decimals); +} + +void ParameterEditor::updateProperty() +{ + auto mgr = dynamic_cast(m_property->propertyManager()); + if (mgr) + { + // To find out whether the value was really changed, we format it and compare string values. This + // ensures that we don't suffer from double precision loss and consider only real changes in value + + QString prevVal = formatValue(mgr->value(m_property)); + QString newVal = formatValue(text().toDouble()); + + if ( prevVal != newVal ) + { + // As the value was changed, the error becomes invalid, so clear it + mgr->clearError(m_property); + } + } + + DoubleEditor::updateProperty(); +} diff --git a/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.h b/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.h index 95f881e8a38e..a2668dd52916 100644 --- a/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.h +++ b/Code/Mantid/QtPropertyBrowser/src/DoubleEditorFactory.h @@ -2,21 +2,47 @@ #define DOUBLEEDITORFACTORY_H #include "qtpropertymanager.h" +#include "ParameterPropertyManager.h" #include -class QT_QTPROPERTYBROWSER_EXPORT DoubleEditorFactory : public QtAbstractEditorFactory +/** + * Base class for double editor factories + * @param DoubleManagerType :: Double manager class to use + * @param DoubleEditorType :: Double editor class to create + */ +template +class DoubleEditorFactoryBase : public QtAbstractEditorFactory { - Q_OBJECT public: - DoubleEditorFactory(QObject *parent = 0): QtAbstractEditorFactory(parent){} + DoubleEditorFactoryBase(QObject *parent = 0) + : QtAbstractEditorFactory(parent) + {} + protected: - void connectPropertyManager(QtDoublePropertyManager *manager); - QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDoublePropertyManager *manager); + void connectPropertyManager(DoubleManagerType *manager) + { + (void) manager; // Unused + // Do nothing + } + + void disconnectPropertyManager(DoubleManagerType *manager) + { + (void) manager; // Unused + // Do nothing + } + + QWidget *createEditor(DoubleManagerType *manager, QtProperty *property, QWidget *parent) + { + (void) manager; // Unused + + return new DoubleEditorType(property, parent); + } }; +/** + * Editor for double values + */ class QT_QTPROPERTYBROWSER_EXPORT DoubleEditor: public QLineEdit { Q_OBJECT @@ -24,11 +50,48 @@ class QT_QTPROPERTYBROWSER_EXPORT DoubleEditor: public QLineEdit DoubleEditor(QtProperty *property, QWidget *parent); ~DoubleEditor(); void setValue(const double& d); -private slots: - void updateProperty(); -private: +protected slots: + virtual void updateProperty(); +protected: + /// Returns string representation of the value, using the format of the property + QString formatValue(const double& d) const; + QtProperty* m_property; int m_decimals; }; +/** + * Specialized version of double editor for parameters + */ +class QT_QTPROPERTYBROWSER_EXPORT ParameterEditor : public DoubleEditor +{ + Q_OBJECT +public: + ParameterEditor(QtProperty *property, QWidget *parent) : DoubleEditor(property, parent) {} +protected slots: + virtual void updateProperty(); +}; + +/** + * Concrete double editor factory for double properties + */ +class QT_QTPROPERTYBROWSER_EXPORT DoubleEditorFactory : public DoubleEditorFactoryBase +{ + Q_OBJECT +public: + DoubleEditorFactory(QObject* parent = 0) + : DoubleEditorFactoryBase(parent) {} +}; + +/** + * Concrete double editor factory for parameter properties + */ +class QT_QTPROPERTYBROWSER_EXPORT ParameterEditorFactory : public DoubleEditorFactoryBase +{ + Q_OBJECT +public: + ParameterEditorFactory(QObject* parent = 0) + : DoubleEditorFactoryBase(parent) {} +}; + #endif // DOUBLEEDITORFACTORY_H diff --git a/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.cpp b/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.cpp new file mode 100644 index 000000000000..a1db9506baba --- /dev/null +++ b/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.cpp @@ -0,0 +1,148 @@ +#include "ParameterPropertyManager.h" + +#include "qtpropertymanager.h" + +#include +#include + +const QString ParameterPropertyManager::ERROR_TOOLTIP(" (Error)"); + +ParameterPropertyManager::ParameterPropertyManager(QObject *parent) + : QtDoublePropertyManager(parent), + m_errors(), m_errorsEnabled(false) +{} + +/** + * Throws if property error is not set + * @param property :: Property to get error for + * @return Error value of the property + */ +double ParameterPropertyManager::error(const QtProperty* property) const +{ + // Cast for searching purposes + auto prop = const_cast(property); + + if (!m_errors.contains(prop)) + throw std::runtime_error("Parameter doesn't have error value set"); + + return m_errors[prop]; +} + +/** + * @param property :: Parameter property + * @return Parameter description + */ +std::string ParameterPropertyManager::description(const QtProperty* property) const +{ + // Cast for searching purposes + auto prop = const_cast(property); + + if(!m_descriptions.contains(prop)) + throw std::runtime_error("Parameter doesn't have description set"); + + return m_descriptions[prop]; +} + +/** + * @param property :: Property to check + * @return True if error was set for the property, false otherwise + */ +bool ParameterPropertyManager::isErrorSet(const QtProperty* property) const +{ + // Cast for searching purposes + auto prop = const_cast(property); + + return m_errors.contains(prop); +} + +/** + * @param property :: Property to set error for + * @param error :: Error value to set + */ +void ParameterPropertyManager::setError(QtProperty* property, const double& error) +{ + m_errors[property] = error; + emit propertyChanged(property); + updateTooltip(property); +} + +/** + * @param property :: Parameter property to set error for + * @param description :: Description of the parameter + */ +void ParameterPropertyManager::setDescription(QtProperty* property, const std::string& description) +{ + m_descriptions[property] = description; + updateTooltip(property); +} + +/** + * Clears error of the property, if one was set. If error was not set, the function does nothing. + * @param property :: Property to clear error for + */ +void ParameterPropertyManager::clearError(QtProperty* property) +{ + m_errors.remove(property); + emit propertyChanged(property); + updateTooltip(property); +} + +/** + * Sets errors enabled state. Updates all the properties as well to show/hide errors. + * @param enabled :: New errors enabled state + */ +void ParameterPropertyManager::setErrorsEnabled(bool enabled) +{ + m_errorsEnabled = enabled; + + foreach(QtProperty* prop, m_errors.keys()) + { + emit propertyChanged(prop); + updateTooltip(prop); + } +} + +/** + * Adds error parameter value to property display + * @param property :: Property we want to display + * @return Text representation of the property + * @see QtAbstractPropertyManager + */ +QString ParameterPropertyManager::valueText(const QtProperty* property) const +{ + QString originalValueText = QtDoublePropertyManager::valueText(property); + + if (areErrorsEnabled() && isErrorSet(property)) + { + double propError = error(property); + int precision = decimals(property); + + // Format logic taken from QtDoublePropertyManager::valueText + double absVal = fabs(value(property)); + char format = absVal > 1e5 || (absVal != 0 && absVal < 1e-5) ? 'e' : 'f'; + + return originalValueText + QString(" (%1)").arg(propError, 0, format, precision); + } + else + { + // No error set or errors disabled, so don't append error value + return originalValueText; + } +} + +/** + * @param property :: Property to update tooltip for + */ +void ParameterPropertyManager::updateTooltip(QtProperty* property) const +{ + // Description only initially + QString tooltip = QString::fromStdString(description(property)); + + if ( areErrorsEnabled() && isErrorSet(property)) + { + // If error is displayed - add description for it + tooltip += ERROR_TOOLTIP; + } + + property->setToolTip(tooltip); +} diff --git a/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.h b/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.h new file mode 100644 index 000000000000..3bca0b6837e3 --- /dev/null +++ b/Code/Mantid/QtPropertyBrowser/src/ParameterPropertyManager.h @@ -0,0 +1,86 @@ +#ifndef PARAMETERPROPERTYMANAGER_H +#define PARAMETERPROPERTYMANAGER_H + +#include "qtpropertymanager.h" + +#include + +/** ParameterPropertyManager : specialized version of QtDoublePropertyManager for fitting parameters. + + Is capable to store/display parameter errors in addition to 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 QT_QTPROPERTYBROWSER_EXPORT ParameterPropertyManager : public QtDoublePropertyManager +{ + Q_OBJECT + +public: + ParameterPropertyManager(QObject *parent = 0); + + /// Get parameter error + double error(const QtProperty* property) const; + + /// Get parameter description + std::string description(const QtProperty* property) const; + + /// Checks if given property has error value set + bool isErrorSet(const QtProperty* property) const; + + /// Returns errors enabled status + bool areErrorsEnabled() const { return m_errorsEnabled; } + +public Q_SLOTS: + /// Set property error + void setError(QtProperty* property, const double& error); + + /// Set parameter description + void setDescription(QtProperty* property, const std::string& description); + + /// Clears error of the property, if one was set + void clearError(QtProperty* property); + + /// Enabled/disables error display + void setErrorsEnabled(bool enabled); + +protected: + /// Text representation of the property + virtual QString valueText(const QtProperty* property) const; + +private Q_SLOTS: + /// Updates the tooltip of the property + void updateTooltip(QtProperty* property) const; + +private: + /// Text appended to parameter descr. tooltip if error is set + static const QString ERROR_TOOLTIP; + + /// Parameter error values + QMap m_errors; + + /// Parameter descriptions + QMap m_descriptions; + + /// Errors enabled flag. When is false, errors can be set, but will not be displayed + bool m_errorsEnabled; +}; + +#endif // PARAMETERPROPERTYMANAGER_H diff --git a/Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.h b/Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.h deleted file mode 100644 index 35994ba2e9ea..000000000000 --- a/Code/Mantid/QtPropertyBrowser/src/StringDialogEditorFactory.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef STRINGDIALOGEDITORFACTORY_H -#define STRINGDIALOGEDITORFACTORY_H - -#include "qtpropertymanager.h" - -class QLineEdit; - -class QT_QTPROPERTYBROWSER_EXPORT StringDialogEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - StringDialogEditorFactory(QObject *parent = 0): QtAbstractEditorFactory(parent){} -protected: - void connectPropertyManager(QtStringPropertyManager *manager); - QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,QWidget *parent); - void disconnectPropertyManager(QtStringPropertyManager *manager); -}; - -class QT_QTPROPERTYBROWSER_EXPORT StringDialogEditor: public QWidget -{ - Q_OBJECT -public: - StringDialogEditor(QtProperty *property, QWidget *parent); - ~StringDialogEditor(); -protected slots: - virtual void runDialog(); - void updateProperty(); - void setText(const QString& txt); - QString getText()const; -private: - QLineEdit* m_lineEdit; - QtProperty* m_property; -}; - -#endif // STRINGDIALOGEDITORFACTORY_H diff --git a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp index 86a46b811b6d..c53fb787eb34 100644 --- a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp +++ b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp @@ -638,20 +638,33 @@ void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item) { QtProperty *property = m_itemToIndex[item]->property(); + QString toolTip = property->toolTip(); QIcon expandIcon; - if (property->hasValue()) { - QString toolTip = property->toolTip(); + if (property->hasValue()) + { if (toolTip.isEmpty()) toolTip = property->valueText(); + + // If property has value, use custom tooltip for value and default one for name item->setToolTip(1, toolTip); + item->setToolTip(0, property->propertyName()); + item->setIcon(1, property->valueIcon()); item->setText(1, property->valueText()); - } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) { - expandIcon = m_expandIcon; + } + else + { + if(toolTip.isEmpty()) + toolTip = property->propertyName(); + + // If property doesn't have value, use custom tooltip for it + item->setToolTip(0, toolTip); + + if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) + expandIcon = m_expandIcon; } item->setIcon(0, expandIcon); item->setFirstColumnSpanned(!property->hasValue()); - item->setToolTip(0, property->propertyName()); item->setStatusTip(0, property->statusTip()); item->setWhatsThis(0, property->whatsThis()); item->setText(0, property->propertyName()); diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/Common.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/Common.h index 44a080dc5150..6f2c94cef288 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/Common.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/Common.h @@ -38,6 +38,8 @@ std::string makeAxisTitle(Dimension_const_sptr dim); void setAxisLabel(std::string metadataLabel, std::string labelString, vtkFieldData *fieldData); +/// Function to check for special values. +bool isSpecial(double value); } diff --git a/Code/Mantid/Vates/VatesAPI/src/Common.cpp b/Code/Mantid/Vates/VatesAPI/src/Common.cpp index 5bf26a6a1e1c..698610bea2c8 100644 --- a/Code/Mantid/Vates/VatesAPI/src/Common.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/Common.cpp @@ -5,6 +5,8 @@ #include #include +#include + //using namespace Mantid::Geometry; namespace Mantid { @@ -31,6 +33,10 @@ void setAxisLabel(std::string metadataLabel, fieldData->AddArray(axisTitle.GetPointer()); } +bool isSpecial(double value) +{ + return boost::math::isnan(value) || boost::math::isinf(value); +} } // VATES } // Mantid diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToNonOrthogonalDataSet.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToNonOrthogonalDataSet.cpp index d390cdbdde17..49003e749691 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToNonOrthogonalDataSet.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToNonOrthogonalDataSet.cpp @@ -1,4 +1,5 @@ #include "MantidVatesAPI/vtkDataSetToNonOrthogonalDataSet.h" +#include "MantidAPI/CoordTransform.h" #include "MantidAPI/IMDEventWorkspace.h" #include "MantidAPI/IMDHistoWorkspace.h" #include "MantidGeometry/Crystal/UnitCell.h" diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDHexFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDHexFactory.cpp index 558fecfb569c..053782f2d7bc 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDHexFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDHexFactory.cpp @@ -2,8 +2,8 @@ #include "MantidKernel/CPUTimer.h" #include "MantidMDEvents/MDEventFactory.h" #include "MantidVatesAPI/vtkMDHexFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" -#include #include #include #include @@ -100,7 +100,7 @@ namespace Mantid API::IMDNode * box = boxes[i]; Mantid::signal_t signal_normalized= box->getSignalNormalized(); - if (!boost::math::isnan( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) + if (!isSpecial( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) { // Cache the signal and using of it signalArray[i] = float(signal_normalized); diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoHexFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoHexFactory.cpp index 090b80294647..ce9b098f1158 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoHexFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoHexFactory.cpp @@ -2,8 +2,8 @@ #include "MantidKernel/CPUTimer.h" #include "MantidMDEvents/MDHistoWorkspace.h" #include "MantidVatesAPI/vtkMDHistoHexFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" -#include #include "MantidAPI/NullCoordTransform.h" #include "MantidKernel/ReadLock.h" @@ -150,7 +150,7 @@ namespace VATES else signalScalar = m_workspace->getSignalNormalizedAt(x,y,z); - if (boost::math::isnan( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) + if (isSpecial( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) { // out of range voxelShown[index] = false; diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoLineFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoLineFactory.cpp index aaaf4af335a7..d8223d1e008b 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoLineFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoLineFactory.cpp @@ -1,4 +1,5 @@ #include "MantidVatesAPI/vtkMDHistoLineFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" #include "vtkCellArray.h" #include "vtkCellData.h" @@ -6,7 +7,6 @@ #include "vtkSmartPointer.h" #include "vtkLine.h" #include -#include #include "MantidAPI/IMDWorkspace.h" #include "MantidAPI/NullCoordTransform.h" #include "MantidMDEvents/MDHistoWorkspace.h" @@ -105,7 +105,7 @@ namespace Mantid float signalScalar = static_cast(m_workspace->getSignalNormalizedAt(i)); - if (boost::math::isnan( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) + if (isSpecial( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) { //Flagged so that topological and scalar data is not applied. unstructPoint.isSparse = true; diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoQuadFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoQuadFactory.cpp index 8ef755534f7a..2341a57fe072 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoQuadFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDHistoQuadFactory.cpp @@ -3,13 +3,13 @@ #include "MantidMDEvents/MDHistoWorkspace.h" #include "MantidAPI/NullCoordTransform.h" #include "MantidVatesAPI/vtkMDHistoQuadFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkFloatArray.h" #include "vtkQuad.h" #include "vtkSmartPointer.h" -#include #include #include "MantidKernel/ReadLock.h" @@ -118,7 +118,7 @@ namespace Mantid { index = j + nBinsY*i; signalScalar = static_cast(m_workspace->getSignalNormalizedAt(i, j)); - if (boost::math::isnan( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) + if (isSpecial( signalScalar ) || !m_thresholdRange->inRange(signalScalar)) { // out of range voxelShown[index] = false; diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDLineFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDLineFactory.cpp index d7ce64ee734b..6864152a1824 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDLineFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDLineFactory.cpp @@ -1,4 +1,5 @@ #include "MantidVatesAPI/vtkMDLineFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" #include "MantidAPI/IMDWorkspace.h" #include "MantidAPI/IMDEventWorkspace.h" @@ -10,7 +11,6 @@ #include #include #include -#include #include "MantidKernel/ReadLock.h" using namespace Mantid::API; @@ -102,7 +102,7 @@ namespace Mantid progressUpdating.eventRaised(double(iBox)*progressFactor); Mantid::signal_t signal_normalized= it->getNormalizedSignal(); - if (!boost::math::isnan( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) + if (!isSpecial( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) { useBox[iBox] = true; signals->InsertNextValue(static_cast(signal_normalized)); diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkMDQuadFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkMDQuadFactory.cpp index 7b6fb96bdec2..e1721843b398 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkMDQuadFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkMDQuadFactory.cpp @@ -1,4 +1,5 @@ #include "MantidVatesAPI/vtkMDQuadFactory.h" +#include "MantidVatesAPI/Common.h" #include "MantidVatesAPI/ProgressAction.h" #include "MantidAPI/IMDWorkspace.h" #include "MantidAPI/IMDEventWorkspace.h" @@ -10,7 +11,6 @@ #include #include #include -#include #include "MantidKernel/ReadLock.h" using namespace Mantid::API; @@ -98,7 +98,7 @@ namespace Mantid progressUpdating.eventRaised(progressFactor * double(iBox)); Mantid::signal_t signal_normalized= it->getNormalizedSignal(); - if (!boost::math::isnan( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) + if (!isSpecial( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) { useBox[iBox] = true; signals->InsertNextValue(static_cast(signal_normalized)); diff --git a/Code/Mantid/instrument/Facilities.xml b/Code/Mantid/instrument/Facilities.xml index d0732fba0e3d..dc58aba68636 100644 --- a/Code/Mantid/instrument/Facilities.xml +++ b/Code/Mantid/instrument/Facilities.xml @@ -360,6 +360,10 @@ Small Angle Scattering + + Small Angle Scattering + + Neutron Diffraction @@ -367,6 +371,7 @@ Neutron Diffraction Diffuse Scattering + diff --git a/Code/Mantid/instrument/MAPS_Parameters.xml b/Code/Mantid/instrument/MAPS_Parameters.xml index 5636a65062ce..502f8e429e8d 100644 --- a/Code/Mantid/instrument/MAPS_Parameters.xml +++ b/Code/Mantid/instrument/MAPS_Parameters.xml @@ -80,6 +80,13 @@ + + + + diff --git a/Code/Mantid/instrument/MARI_Parameters.xml b/Code/Mantid/instrument/MARI_Parameters.xml index 82bfeca84002..7d7f491cf134 100644 --- a/Code/Mantid/instrument/MARI_Parameters.xml +++ b/Code/Mantid/instrument/MARI_Parameters.xml @@ -78,8 +78,13 @@ - - + + + + diff --git a/Code/Mantid/instrument/POLDI_Parameters_2013.xml b/Code/Mantid/instrument/POLDI_Parameters_2013.xml index d559d8ab9fd7..1e22818a98d8 100644 --- a/Code/Mantid/instrument/POLDI_Parameters_2013.xml +++ b/Code/Mantid/instrument/POLDI_Parameters_2013.xml @@ -1,9 +1,5 @@ - + diff --git a/Code/Mantid/instrument/POWGEN_Definition_2014-02-01.xml b/Code/Mantid/instrument/POWGEN_Definition_2014-02-01.xml index 66ded2efbef0..e32f25078773 100644 --- a/Code/Mantid/instrument/POWGEN_Definition_2014-02-01.xml +++ b/Code/Mantid/instrument/POWGEN_Definition_2014-02-01.xml @@ -1,5 +1,5 @@ - + @@ -27,7 +27,7 @@ - + @@ -401,6 +401,6 @@ - + diff --git a/Code/Mantid/instrument/POWGEN_Definition_2014-03-10.xml b/Code/Mantid/instrument/POWGEN_Definition_2014-03-10.xml new file mode 100644 index 000000000000..ba62f5e8b7e4 --- /dev/null +++ b/Code/Mantid/instrument/POWGEN_Definition_2014-03-10.xml @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Mantid/instrument/USANS_Definition.xml b/Code/Mantid/instrument/USANS_Definition.xml new file mode 100644 index 000000000000..d4cf999c363e --- /dev/null +++ b/Code/Mantid/instrument/USANS_Definition.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Mantid/scripts/Inelastic/DirectEnergyConversion.py b/Code/Mantid/scripts/Inelastic/DirectEnergyConversion.py index 058181c00378..cbdcb7b94fff 100644 --- a/Code/Mantid/scripts/Inelastic/DirectEnergyConversion.py +++ b/Code/Mantid/scripts/Inelastic/DirectEnergyConversion.py @@ -319,10 +319,17 @@ def _do_mono_SNS(self, data_ws, monitor_ws, result_name, ei_guess, InfoFilename = mono_run.replace("_neutron_event.dat", "_runinfo.xml") monitor_ws=LoadPreNexusMonitors(RunInfoFilename=InfoFilename) + argi = {}; + argi['Monitor1Spec']=int(self.ei_mon_spectra[0]); + argi['Monitor2Spec']=int(self.ei_mon_spectra[1]); + argi['EnergyEstimate']=ei_guess; + argi['FixEi'] =self.fix_ei + if hasattr(self, 'ei_mon_peak_search_range'): + argi['PeakSearchRange']=self.ei_mon_peak_search_range; + try: ei_calc,firstmon_peak,firstmon_index,TzeroCalculated = \ - GetEi(InputWorkspace=monitor_ws, Monitor1Spec=int(self.ei_mon_spectra[0]), Monitor2Spec=int(self.ei_mon_spectra[1]), - EnergyEstimate=ei_guess,FixEi=self.fix_ei) + GetEi(InputWorkspace=monitor_ws,**argi) except: self.log("Error in GetEi. Using entered values.") #monitor_ws.getRun()['Ei'] = ei_value diff --git a/Code/Mantid/scripts/Inelastic/IndirectBayes.py b/Code/Mantid/scripts/Inelastic/IndirectBayes.py index 894f7fa35c10..219df5cede34 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectBayes.py +++ b/Code/Mantid/scripts/Inelastic/IndirectBayes.py @@ -96,18 +96,12 @@ def ReadNormFile(readRes,resnormWS,nsam,Verbose): # get norm & scale Xin = mtd[resnormWS+'_Intensity'].readX(0) nrm = len(Xin) # no. points from length of x array if nrm == 0: - error = 'ResNorm file has no Intensity points' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('ResNorm file has no Intensity points') Xin = mtd[resnormWS+'_Stretch'].readX(0) # no. points from length of x array if len(Xin) == 0: - error = 'ResNorm file has no xscale points' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('ResNorm file has no xscale points') if nrm != nsam: # check that no. groups are the same - error = 'ResNorm groups (' +str(nrm) + ') not = Sample (' +str(nsam) +')' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('ResNorm groups (' +str(nrm) + ') not = Sample (' +str(nsam) +')') else: dtn,xsc = GetResNorm(resnormWS,0) else: @@ -137,22 +131,15 @@ def ReadWidthFile(readWidth,widthFile,numSampleGroups,Verbose): handle.close() except Exception, e: - error = 'Failed to read width file' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Failed to read width file') numLines = len(asc) if numLines == 0: - error = 'No groups in width file' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('No groups in width file') if numLines != numSampleGroups: # check that no. groups are the same - error = 'Width groups (' +str(numLines) + ') not = Sample (' +str(numSampleGroups) +')' - logger.notice('ERROR *** ' + error) - sys.exit(error) - + raise ValueError('Width groups (' +str(numLines) + ') not = Sample (' +str(numSampleGroups) +')') else: # no file: just use constant values widthY = np.zeros(numSampleGroups) @@ -223,8 +210,7 @@ def QLRun(program,samWS,resWS,resnormWS,erange,nbins,Fit,wfile,Loop,Verbose,Plot if nres == 1: prog = 'QSe' # res file else: - error = 'Stretched Exp ONLY works with RES file' - sys.exit(error) + raise ValueError('Stretched Exp ONLY works with RES file') if Verbose: logger.notice('Version is ' +prog) @@ -671,22 +657,16 @@ def QuasiPlot(ws_stem,plot_type,res_plot,sequential): def CheckBetSig(nbs): Nsig = int(nbs[1]) if Nsig == 0: - error = 'Number of sigma points is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Number of sigma points is Zero') if Nsig > 200: - error = 'Max number of sigma points is 200' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Max number of sigma points is 200') + Nbet = int(nbs[0]) if Nbet == 0: - error = 'Number of beta points is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Number of beta points is Zero') if Nbet > 200: - error = 'Max number of beta points is 200' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Max number of beta points is 200') + return Nbet,Nsig def QuestRun(samWS,resWS,nbs,erange,nbins,Fit,Loop,Verbose,Plot,Save): @@ -729,9 +709,7 @@ def QuestRun(samWS,resWS,nbs,erange,nbins,Fit,Loop,Verbose,Plot,Save): if nres == 1: prog = 'Qst' # res file else: - error = 'Stretched Exp ONLY works with RES file' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Stretched Exp ONLY works with RES file') if Verbose: logger.notice(' Number of spectra = '+str(nsam)) logger.notice(' Erange : '+str(erange[0])+' to '+str(erange[1])) diff --git a/Code/Mantid/scripts/Inelastic/IndirectCommon.py b/Code/Mantid/scripts/Inelastic/IndirectCommon.py index 3bee75cb16e9..1f966b7bbc52 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectCommon.py +++ b/Code/Mantid/scripts/Inelastic/IndirectCommon.py @@ -77,8 +77,7 @@ def getDefaultWorkingDirectory(): workdir = config['defaultsave.directory'] if not os.path.isdir(workdir): - error = "Default save directory is not a valid path!" - sys.exit(error) + raise IOError("Default save directory is not a valid path!") return workdir @@ -113,12 +112,10 @@ def createQaxis(inputWS): msg = 'Creating Axis based on Detector Q value: ' if not axis.isNumeric(): msg += 'Input workspace must have either spectra or numeric axis.' - logger.notice(msg) - sys.exit(msg) + raise ValueError(msg) if ( axis.getUnit().unitID() != 'MomentumTransfer' ): msg += 'Input must have axis values of Q' - logger.notice(msg) - sys.exit(msg) + raise ValueError(msg) for i in range(0, nHist): result.append(float(axis.label(i))) return result @@ -183,13 +180,9 @@ def CheckAnalysers(in1WS,in2WS,Verbose): a2 = ws2.getInstrument().getStringParameter('analyser')[0] r2 = ws2.getInstrument().getStringParameter('reflection')[0] if a1 != a2: - error = 'Workspace '+in1WS+' and '+in2WS+' have different analysers' - logger.notice('ERROR *** '+error) - sys.exit(error) + raise ValueError('Workspace '+in1WS+' and '+in2WS+' have different analysers') elif r1 != r2: - error = 'Workspace '+in1WS+' and '+in2WS+' have different reflections' - logger.notice('ERROR *** '+error) - sys.exit(error) + raise ValueError('Workspace '+in1WS+' and '+in2WS+' have different reflections') else: if Verbose: logger.notice('Analyser is '+a1+r1) @@ -197,15 +190,11 @@ def CheckAnalysers(in1WS,in2WS,Verbose): def CheckHistZero(inWS): nhist = mtd[inWS].getNumberHistograms() # no. of hist/groups in WS if nhist == 0: - error = 'Workspace '+inWS+' has NO histograms' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Workspace '+inWS+' has NO histograms') Xin = mtd[inWS].readX(0) ntc = len(Xin)-1 # no. points from length of x array if ntc == 0: - error = 'Workspace '+inWS+' has NO points' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Workspace '+inWS+' has NO points') return nhist,ntc def CheckHistSame(in1WS,name1,in2WS,name2): @@ -219,68 +208,38 @@ def CheckHistSame(in1WS,name1,in2WS,name2): e1 = name1+' ('+in1WS+') histograms (' +str(nhist1) + ')' e2 = name2+' ('+in2WS+') histograms (' +str(nhist2) + ')' error = e1 + ' not = ' + e2 - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError(error) elif xlen1 != xlen2: e1 = name1+' ('+in1WS+') array length (' +str(xlen1) + ')' e2 = name2+' ('+in2WS+') array length (' +str(xlen2) + ')' error = e1 + ' not = ' + e2 - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError(error) -def CheckXrange(xrange,type): - if not ( ( len(xrange) == 2 ) or ( len(xrange) == 4 ) ): - error = type + ' - Range must contain either 2 or 4 numbers' - logger.notice(error) - sys.exit(error) - if math.fabs(xrange[0]) < 1e-5: - error = type + ' - input minimum ('+str(xrange[0])+') is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if math.fabs(xrange[1]) < 1e-5: - error = type + ' - input maximum ('+str(xrange[1])+') is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if xrange[1] < xrange[0]: - error = type + ' - input max ('+str(xrange[1])+') < min ('+xrange[0]+')' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if len(xrange) >2: - if math.fabs(xrange[2]) < 1e-5: - error = type + '2 - input minimum ('+str(xrange[2])+') is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if math.fabs(xrange[3]) < 1e-5: - error = type + '2 - input maximum ('+str(xrange[3])+') is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) - if xrange[3] < xrange[2]: - error = type + '2 - input max ('+str(xrange[3])+') < min ('+xrange[2]+')' - logger.notice('ERROR *** ' + error) - sys.exit(error) +def CheckXrange(x_range,type): + if not ( ( len(x_range) == 2 ) or ( len(x_range) == 4 ) ): + raise ValueError(type + ' - Range must contain either 2 or 4 numbers') + + for lower, upper in zip(x_range[::2], x_range[1::2]): + if math.fabs(lower) < 1e-5: + raise ValueError(type + ' - input minimum ('+str(lower)+') is Zero') + if math.fabs(upper) < 1e-5: + raise ValueError(type + ' - input maximum ('+str(upper)+') is Zero') + if upper < lower: + raise ValueError(type + ' - input max ('+str(upper)+') < min ('+lower+')') def CheckElimits(erange,Xin): nx = len(Xin)-1 + if math.fabs(erange[0]) < 1e-5: - error = 'Elimits - input emin ( '+str(erange[0])+' ) is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Elimits - input emin ( '+str(erange[0])+' ) is Zero') if erange[0] < Xin[0]: - error = 'Elimits - input emin ( '+str(erange[0])+' ) < data emin ( '+str(Xin[0])+' )' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Elimits - input emin ( '+str(erange[0])+' ) < data emin ( '+str(Xin[0])+' )') if math.fabs(erange[1]) < 1e-5: - error = 'Elimits - input emax ( '+str(erange[1])+' ) is Zero' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Elimits - input emax ( '+str(erange[1])+' ) is Zero') if erange[1] > Xin[nx]: - error = 'Elimits - input emax ( '+str(erange[1])+' ) > data emax ( '+str(Xin[nx])+' )' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Elimits - input emax ( '+str(erange[1])+' ) > data emax ( '+str(Xin[nx])+' )') if erange[1] < erange[0]: - error = 'Elimits - input emax ( '+str(erange[1])+' ) < emin ( '+erange[0]+' )' - logger.notice('ERROR *** ' + error) - sys.exit(error) + raise ValueError('Elimits - input emax ( '+str(erange[1])+' ) < emin ( '+erange[0]+' )') def plotSpectra(ws, y_axis_title, indicies=[]): """ diff --git a/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py b/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py index a8076d61f174..bfd280c20f8a 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py +++ b/Code/Mantid/scripts/Inelastic/IndirectEnergyConversion.py @@ -390,93 +390,3 @@ def IndirectTrans(inst, sfile,cfile,Verbose=False,Plot=False,Save=False): if Plot: TransPlot(transWS) EndTime('Transmission') - -############################################################################## -# Moments -############################################################################## - -def SqwMoments(samWS,erange,factor,Verbose,Plot,Save): - StartTime('Moments') - workdir = config['defaultsave.directory'] - nq,nw = CheckHistZero(samWS) - if Verbose: - logger.notice('Sample '+samWS+' has '+str(nq)+' Q values & '+str(nw)+' w values') - axis = mtd[samWS].getAxis(1) - Q = [] - e0 = [] - for i in range(0,nq): - Q.append(float(axis.label(i))) - e0.append(0.0) - Xin = mtd[samWS].readX(0) - CheckElimits(erange,Xin) - CropWorkspace(InputWorkspace=samWS, OutputWorkspace=samWS, XMin=erange[0], XMax=erange[1]) - Xin = mtd[samWS].readX(0) - nw = len(Xin)-1 - if Verbose: - logger.notice('Energy range is '+str(Xin[0])+' to '+str(Xin[nw])) - if factor > 0.0: - Scale(InputWorkspace=samWS, OutputWorkspace=samWS, Factor=factor, Operation='Multiply') - if Verbose: - logger.notice('S(q,w) scaled by '+str(factor)) - w = mtd[samWS].readX(0) - yM0 = [] - yM1 = [] - yM2 = [] - yM4 = [] - xdel = [] - for n in range(0,nw): - xdel.append(w[n+1]-w[n]) - xdel.append(w[nw-1]) - for m in range(0,nq): - if Verbose: - logger.notice('Group '+str(m+1)+' at Q = '+str(Q[m])) - S = mtd[samWS].readY(m) - m0 = 0.0 - m1 = 0.0 - m2 = 0.0 - m3 = 0.0 - m4 = 0.0 - for n in range(0,nw): - S0 = S[n]*xdel[n] - m0 += S0 - S1 = Xin[n]*S0 - m1 += S1 - S2 = Xin[n]*S1 - m2 += S2 - S3 = Xin[n]*S2 - m3 += S3 - S4 = Xin[n]*S3 - m4 += S4 - m1 = m1/m0 - m2 = m2/m0 - m3 = m3/m0 - m4 = m4/m0 - text = 'M0 = '+str(m0)+' ; M2 = '+str(m2)+' ; M4 = '+str(m4) - logger.notice(text) - yM0.append(m0) - yM1.append(m1) - yM2.append(m2) - yM4.append(m4) - fname = samWS[:-3] + 'Moments' - CreateWorkspace(OutputWorkspace=fname+'_M0', DataX=Q, DataY=yM0, DataE=e0, - Nspec=1, UnitX='MomentumTransfer') - CreateWorkspace(OutputWorkspace=fname+'_M1', DataX=Q, DataY=yM1, DataE=e0, - Nspec=1, UnitX='MomentumTransfer') - CreateWorkspace(OutputWorkspace=fname+'_M2', DataX=Q, DataY=yM2, DataE=e0, - Nspec=1, UnitX='MomentumTransfer') - CreateWorkspace(OutputWorkspace=fname+'_M4', DataX=Q, DataY=yM4, DataE=e0, - Nspec=1, UnitX='MomentumTransfer') - group = fname+'_M0,'+fname+'_M1,'+fname+'_M2,'+fname+'_M4' - GroupWorkspaces(InputWorkspaces=group,OutputWorkspace=fname) - if Save: - opath = os.path.join(workdir,fname+'.nxs') - SaveNexusProcessed(InputWorkspace=fname, Filename=opath) - if Verbose: - logger.notice('Output file : ' + opath) - if (Plot != 'None'): - SqwMomentsPlot(fname,Plot) - EndTime('Moments') - -def SqwMomentsPlot(inputWS,Plot): - m0_plot=mp.plotSpectrum(inputWS+'_M0',0) - m2_plot=mp.plotSpectrum([inputWS+'_M2',inputWS+'_M4'],0) diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_choose_col.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_choose_col.py new file mode 100644 index 000000000000..0f1d288a15d7 --- /dev/null +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_choose_col.py @@ -0,0 +1,33 @@ +#This is an extension of refl_columns.py as that is a auto-generated script form pyqt and shouldn't be edited +#so this file provides any extra GUI tweaks not easily doable in the designer +#for the time being this also includes non-GUI behaviour +import refl_columns +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class ReflChoose(refl_columns.Ui_ChooseColumnsDialog): + visiblestates = {} + def setupUi(self, Dialog, ColHeaders, table): + super(ReflChoose, self).setupUi(Dialog) + self.visiblestates.clear() + self.listColumns.itemChanged.connect(self.on_listColumns_itemChanged) + self.buttonsColumns.clicked.connect(self.on_buttonsColumns_Clicked) + for key, value in ColHeaders.iteritems(): + header = table.horizontalHeaderItem(key).text() + item = QtGui.QListWidgetItem(header) + if value: + item.setCheckState(2) + else: + item.setCheckState(0) + self.listColumns.insertItem(key, item) + def on_listColumns_itemChanged(self, item): + colno=self.listColumns.row(item) + self.visiblestates[colno] = (item.checkState() > 0) + def on_buttonsColumns_Clicked(self, button): + if self.buttonsColumns.button(QtGui.QDialogButtonBox.RestoreDefaults) == button: + for i in range(self.listColumns.count()): + self.listColumns.item(i).setCheckState(2) \ No newline at end of file diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.py new file mode 100644 index 000000000000..d52fe4ff040a --- /dev/null +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'D:\mantid\windows\Code\Mantid\scripts\Interface\ui\reflectometer/refl_columns.ui' +# +# Created: Wed Mar 19 16:41:17 2014 +# by: PyQt4 UI code generator 4.8.3 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_ChooseColumnsDialog(object): + def setupUi(self, ChooseColumnsDialog): + ChooseColumnsDialog.setObjectName(_fromUtf8("ChooseColumnsDialog")) + ChooseColumnsDialog.resize(307, 300) + ChooseColumnsDialog.setSizeGripEnabled(False) + self.verticalLayout = QtGui.QVBoxLayout(ChooseColumnsDialog) + self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) + self.labelColumns = QtGui.QLabel(ChooseColumnsDialog) + self.labelColumns.setObjectName(_fromUtf8("labelColumns")) + self.verticalLayout.addWidget(self.labelColumns) + self.layoutListButtons = QtGui.QHBoxLayout() + self.layoutListButtons.setObjectName(_fromUtf8("layoutListButtons")) + self.listColumns = QtGui.QListWidget(ChooseColumnsDialog) + self.listColumns.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.listColumns.setSelectionMode(QtGui.QAbstractItemView.NoSelection) + self.listColumns.setObjectName(_fromUtf8("listColumns")) + self.layoutListButtons.addWidget(self.listColumns) + self.buttonsColumns = QtGui.QDialogButtonBox(ChooseColumnsDialog) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.buttonsColumns.sizePolicy().hasHeightForWidth()) + self.buttonsColumns.setSizePolicy(sizePolicy) + self.buttonsColumns.setLayoutDirection(QtCore.Qt.LeftToRight) + self.buttonsColumns.setOrientation(QtCore.Qt.Vertical) + self.buttonsColumns.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.RestoreDefaults) + self.buttonsColumns.setCenterButtons(False) + self.buttonsColumns.setObjectName(_fromUtf8("buttonsColumns")) + self.layoutListButtons.addWidget(self.buttonsColumns) + self.verticalLayout.addLayout(self.layoutListButtons) + + self.retranslateUi(ChooseColumnsDialog) + QtCore.QObject.connect(self.buttonsColumns, QtCore.SIGNAL(_fromUtf8("accepted()")), ChooseColumnsDialog.accept) + QtCore.QObject.connect(self.buttonsColumns, QtCore.SIGNAL(_fromUtf8("rejected()")), ChooseColumnsDialog.reject) + QtCore.QMetaObject.connectSlotsByName(ChooseColumnsDialog) + + def retranslateUi(self, ChooseColumnsDialog): + ChooseColumnsDialog.setWindowTitle(QtGui.QApplication.translate("ChooseColumnsDialog", "Choose Columns...", None, QtGui.QApplication.UnicodeUTF8)) + self.labelColumns.setText(QtGui.QApplication.translate("ChooseColumnsDialog", "Choose columns to display", None, QtGui.QApplication.UnicodeUTF8)) + diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.ui b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.ui new file mode 100644 index 000000000000..2e7ecba48cd7 --- /dev/null +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_columns.ui @@ -0,0 +1,100 @@ + + + ChooseColumnsDialog + + + + 0 + 0 + 307 + 300 + + + + Choose Columns... + + + false + + + + + + Choose columns to display + + + + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + false + + + + + + + + + + + buttonsColumns + accepted() + ChooseColumnsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonsColumns + rejected() + ChooseColumnsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py index 4e872b011b11..8fe380d21fed 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_gui.py @@ -3,14 +3,16 @@ #for the time being this also includes non-GUI behaviour import refl_window import refl_save +import refl_choose_col import csv +import string +import os from PyQt4 import QtCore, QtGui from mantid.simpleapi import * from isis_reflectometry.quick import * from isis_reflectometry import load_live_runs from isis_reflectometry.combineMulti import * from latest_isis_runs import * - from mantid.api import Workspace, WorkspaceGroup try: @@ -89,6 +91,26 @@ def _plot_row(self): plotbutton = self.sender() self._plot(plotbutton) + def on_plotButton_clicked(self): + plotbutton = self.windowRefl.sender() + self.plot(plotbutton) + + def actionCopy_triggered(self): + self.copy_cells() + + def actionCut_triggered(self): + self.copy_cells() + self.clear_cells() + + def actionPaste_triggered(self): + self.paste_cells() + + def actionClear_triggered(self): + self.clear_cells() + + def actionChoose_Columns_triggered(self): + self.chooseColumns() + ''' Event handler for polarisation correction selection. ''' @@ -100,6 +122,9 @@ def _polar_corr_selected(self): logger.notice("Polarisation correction is not supported on " + str(self.current_instrument)) def setup_layout(self): + self.shownCols = {} + self.loading = False + self.clip = QtGui.QApplication.clipboard() self.comboInstrument.addItems(self.instrument_list) current_instrument = config['default.instrument'].upper() if current_instrument in self.instrument_list: @@ -118,6 +143,7 @@ def setup_layout(self): self.comboPolarCorrect.setCurrentIndex(self.comboPolarCorrect.findText('None')) self.current_polarisation_method = self.polarisation_options['None'] self.comboPolarCorrect.setEnabled(self.current_instrument in self.polarisation_instruments) + self.splitterList.setSizes([200, 800]) self.labelStatus = QtGui.QLabel("Ready") self.statusMain.addWidget(self.labelStatus) self._initialise_table() @@ -148,7 +174,10 @@ def _initialise_table(self): return self.current_table = None self.accMethod = None - + + settings = QtCore.QSettings() + settings.beginGroup("Mantid/ISISReflGui/Columns") + for column in range(self.tableMain.columnCount()): for row in range(self.tableMain.rowCount()): if (column == 0) or (column == 5) or (column == 10): @@ -193,6 +222,14 @@ def _initialise_table(self): item = QtGui.QTableWidgetItem() item.setText('') self.tableMain.setItem(row, column, item) + vis_state = settings.value(str(column), True, type=bool) + self.shownCols[column] = vis_state + if vis_state: + self.tableMain.showColumn(column) + else: + self.tableMain.hideColumn(column) + settings.endGroup() + del settings self.tableMain.resizeColumnsToContents() self.modFlag = False @@ -219,6 +256,11 @@ def _connect_slots(self): self.actionProcess.triggered.connect(self._process) self.actionTransfer.triggered.connect(self._transfer) self.tableMain.cellChanged.connect(self._table_modified) + self.actionClear.triggered.connect(self.actionClear_triggered) + self.actionPaste.triggered.connect(self.actionPaste_triggered) + self.actionCut.triggered.connect(self.actionCut_triggered) + self.actionCopy.triggered.connect(self.actionCopy_triggered) + self.actionChoose_Columns.triggered.connect(self.actionChoose_Columns_triggered) def _populate_runs_list(self): # Clear existing @@ -245,6 +287,7 @@ def _populate_runs_list(self): self.statusMain.clearMessage() for run in runs: self.listMain.addItem(run) + self.splitterList.setSizes([self.listMain.sizeHintForColumn(0), (1000 - self.listMain.sizeHintForColumn(0))]) except Exception as ex: logger.notice("Could not list archive runs") logger.notice(str(ex)) @@ -292,6 +335,107 @@ def _create_workspace_display_name(self, candidate): todisplay = groupGet(mtd[candidate], "samp", "run_number") return todisplay + def clear_cells(self): + cells = self.tableMain.selectedItems() + for cell in cells: + column = cell.column() + if column < 17: + cell.setText('') + + def copy_cells(self): + cells = self.tableMain.selectedItems() + if not cells: + print 'nothing to copy' + return + #first discover the size of the selection and initialise a list + mincol = cells[0].column() + if mincol == 17 or mincol == 18: + return + logger.error("Cannot copy, all cells out of range") + maxrow = -1 + maxcol = -1 + minrow = cells[0].row() + for cell in reversed(range(len(cells))): + col = cells[cell].column() + if col < 17: + maxcol = col + maxrow = cells[cell].row() + break + colsize = maxcol - mincol + 1 + rowsize = maxrow - minrow + 1 + selection = [['' for x in range(colsize)] for y in range(rowsize)] + #now fill that list + for cell in cells: + row = cell.row() + col = cell.column() + if col < 17: + selection[row - minrow][col - mincol] = str(cell.text()) + tocopy = '' + for y in range(rowsize): + for x in range(colsize): + if x > 0: + tocopy += '\t' + tocopy += selection[y][x] + if y < (rowsize - 1): + tocopy += '\n' + self.copy_to_clipboard(tocopy) + + def paste_cells(self): + pastedtext = self.clip.text() + if not pastedtext: + logger.warning("Nothing to Paste") + return + selected = self.tableMain.selectedItems() + if not selected: + logger.warning("Cannot paste, no editable cells selected") + return + pasted = pastedtext.splitlines() + pastedcells = [] + for row in pasted: + pastedcells.append(row.split('\t')) + pastedcols = len(pastedcells[0]) + pastedrows = len(pastedcells) + if len(selected) > 1: + #discover the size of the selection + mincol = selected[0].column() + if mincol > 16: + logger.error("Cannot copy, all cells out of range") + return + minrow = selected[0].row() + #now fill that list + for cell in selected: + row = cell.row() + col = cell.column() + if col < 17 and (col - mincol) < pastedcols and (row - minrow) < pastedrows and len(pastedcells[row - minrow]): + cell.setText(pastedcells[row - minrow][col - mincol]) + elif selected: + #when only a single cell is selected, paste all the copied item up until the table limits + cell = selected[0] + currow = cell.row() + homecol = cell.column() + tablerows = self.tableMain.rowCount() + for row in pastedcells: + if len(row): + curcol = homecol + if currow < tablerows: + for col in row: + if curcol < 17: + curcell = self.tableMain.item(currow, curcol) + curcell.setText(col) + curcol += 1 + else: + #the row has hit the end of the editable cells + break + currow += 1 + else: + #it's dropped off the bottom of the table + break + else: + logger.warning("Cannot paste, no editable cells selected") + + def copy_to_clipboard(self,text): + self.clip.setText(str(text)) + def _transfer(self): col = 0 row = 0 @@ -683,6 +827,27 @@ def _save_workspaces(self): logger.notice("Could not open save workspace dialog") logger.notice(str(ex)) + def chooseColumns(self): + try: + Dialog = QtGui.QDialog() + u = refl_choose_col.ReflChoose() + u.setupUi(Dialog, self.shownCols, self.tableMain) + if Dialog.exec_(): + settings = QtCore.QSettings() + settings.beginGroup("Mantid/ISISReflGui/Columns") + for key, value in u.visiblestates.iteritems(): + self.shownCols[key] = value + settings.setValue(str(key), value) + if value: + self.tableMain.showColumn(key) + else: + self.tableMain.hideColumn(key) + settings.endGroup() + del settings + except Exception as ex: + logger.notice("Could not open choose columns dialog") + logger.notice(str(ex)) + def _show_help(self): import webbrowser webbrowser.open('http://www.mantidproject.org/ISIS_Reflectometry_GUI') diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.py b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.py index 07aa3b689e6c..61b96814ed5a 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.py +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'D:\mantid\windows\Code\Mantid\scripts\Interface\ui\reflectometer/refl_window.ui' # -# Created: Tue Feb 25 11:55:14 2014 +# Created: Wed Mar 19 16:41:17 2014 # by: PyQt4 UI code generator 4.8.3 # # WARNING! All changes made in this file will be lost! @@ -67,6 +67,9 @@ def setupUi(self, windowRefl): self.layoutTopRow.addWidget(self.comboPolarCorrect) spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.layoutTopRow.addItem(spacerItem2) + self.buttonColumns = QtGui.QPushButton(self.widgetMainRow) + self.buttonColumns.setObjectName(_fromUtf8("buttonColumns")) + self.layoutTopRow.addWidget(self.buttonColumns) self.layoutBase.addLayout(self.layoutTopRow) self.layoutMidRow = QtGui.QHBoxLayout() self.layoutMidRow.setSpacing(12) @@ -106,19 +109,32 @@ def setupUi(self, windowRefl): self.buttonAuto.setObjectName(_fromUtf8("buttonAuto")) self.layoutMidRow.addWidget(self.buttonAuto) self.layoutBase.addLayout(self.layoutMidRow) - self.layoutBottomRow = QtGui.QHBoxLayout() - self.layoutBottomRow.setObjectName(_fromUtf8("layoutBottomRow")) - self.listMain = QtGui.QListWidget(self.widgetMainRow) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.splitterList = QtGui.QSplitter(self.widgetMainRow) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.splitterList.sizePolicy().hasHeightForWidth()) + self.splitterList.setSizePolicy(sizePolicy) + self.splitterList.setOrientation(QtCore.Qt.Horizontal) + self.splitterList.setChildrenCollapsible(False) + self.splitterList.setObjectName(_fromUtf8("splitterList")) + self.listMain = QtGui.QListWidget(self.splitterList) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.listMain.sizePolicy().hasHeightForWidth()) self.listMain.setSizePolicy(sizePolicy) - self.listMain.setMaximumSize(QtCore.QSize(200, 16777215)) + self.listMain.setMinimumSize(QtCore.QSize(100, 0)) + self.listMain.setMaximumSize(QtCore.QSize(500, 16777215)) + self.listMain.setBaseSize(QtCore.QSize(199, 0)) self.listMain.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.listMain.setObjectName(_fromUtf8("listMain")) - self.layoutBottomRow.addWidget(self.listMain) - self.buttonTransfer = QtGui.QPushButton(self.widgetMainRow) + self.widgetBottomRight = QtGui.QWidget(self.splitterList) + self.widgetBottomRight.setObjectName(_fromUtf8("widgetBottomRight")) + self.layoutBottomRow = QtGui.QHBoxLayout(self.widgetBottomRight) + self.layoutBottomRow.setMargin(0) + self.layoutBottomRow.setObjectName(_fromUtf8("layoutBottomRow")) + self.buttonTransfer = QtGui.QPushButton(self.widgetBottomRight) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -129,12 +145,14 @@ def setupUi(self, windowRefl): self.layoutBottomRow.addWidget(self.buttonTransfer) self.layoutTableColumn = QtGui.QVBoxLayout() self.layoutTableColumn.setObjectName(_fromUtf8("layoutTableColumn")) - self.tableMain = QtGui.QTableWidget(self.widgetMainRow) + self.tableMain = QtGui.QTableWidget(self.widgetBottomRight) font = QtGui.QFont() font.setWeight(50) font.setBold(False) self.tableMain.setFont(font) + self.tableMain.setEditTriggers(QtGui.QAbstractItemView.AnyKeyPressed|QtGui.QAbstractItemView.DoubleClicked|QtGui.QAbstractItemView.EditKeyPressed|QtGui.QAbstractItemView.SelectedClicked) self.tableMain.setAlternatingRowColors(True) + self.tableMain.setSelectionMode(QtGui.QAbstractItemView.ContiguousSelection) self.tableMain.setRowCount(100) self.tableMain.setColumnCount(19) self.tableMain.setObjectName(_fromUtf8("tableMain")) @@ -178,14 +196,17 @@ def setupUi(self, windowRefl): self.tableMain.setHorizontalHeaderItem(17, item) item = QtGui.QTableWidgetItem() self.tableMain.setHorizontalHeaderItem(18, item) - self.tableMain.horizontalHeader().setCascadingSectionResizes(True) + self.tableMain.horizontalHeader().setCascadingSectionResizes(False) self.tableMain.horizontalHeader().setDefaultSectionSize(60) self.tableMain.horizontalHeader().setMinimumSectionSize(20) + self.tableMain.horizontalHeader().setStretchLastSection(False) + self.tableMain.verticalHeader().setCascadingSectionResizes(False) self.tableMain.verticalHeader().setDefaultSectionSize(20) + self.tableMain.verticalHeader().setStretchLastSection(False) self.layoutTableColumn.addWidget(self.tableMain) self.layoutTableButton = QtGui.QHBoxLayout() self.layoutTableButton.setObjectName(_fromUtf8("layoutTableButton")) - self.buttonProcess = QtGui.QPushButton(self.widgetMainRow) + self.buttonProcess = QtGui.QPushButton(self.widgetBottomRight) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -193,12 +214,12 @@ def setupUi(self, windowRefl): self.buttonProcess.setSizePolicy(sizePolicy) self.buttonProcess.setObjectName(_fromUtf8("buttonProcess")) self.layoutTableButton.addWidget(self.buttonProcess) - self.buttonClear = QtGui.QPushButton(self.widgetMainRow) + self.buttonClear = QtGui.QPushButton(self.widgetBottomRight) self.buttonClear.setObjectName(_fromUtf8("buttonClear")) self.layoutTableButton.addWidget(self.buttonClear) self.layoutTableColumn.addLayout(self.layoutTableButton) self.layoutBottomRow.addLayout(self.layoutTableColumn) - self.layoutBase.addLayout(self.layoutBottomRow) + self.layoutBase.addWidget(self.splitterList) windowRefl.setCentralWidget(self.widgetMainRow) self.menuBar = QtGui.QMenuBar(windowRefl) self.menuBar.setGeometry(QtCore.QRect(0, 0, 1000, 21)) @@ -209,6 +230,10 @@ def setupUi(self, windowRefl): self.menuHelp.setObjectName(_fromUtf8("menuHelp")) self.menuFunction = QtGui.QMenu(self.menuBar) self.menuFunction.setObjectName(_fromUtf8("menuFunction")) + self.menuEdit = QtGui.QMenu(self.menuBar) + self.menuEdit.setObjectName(_fromUtf8("menuEdit")) + self.menuView = QtGui.QMenu(self.menuBar) + self.menuView.setObjectName(_fromUtf8("menuView")) windowRefl.setMenuBar(self.menuBar) self.statusMain = QtGui.QStatusBar(windowRefl) font = QtGui.QFont() @@ -240,6 +265,16 @@ def setupUi(self, windowRefl): self.actionClear_Table.setObjectName(_fromUtf8("actionClear_Table")) self.actionSearch_RB = QtGui.QAction(windowRefl) self.actionSearch_RB.setObjectName(_fromUtf8("actionSearch_RB")) + self.actionCopy = QtGui.QAction(windowRefl) + self.actionCopy.setObjectName(_fromUtf8("actionCopy")) + self.actionPaste = QtGui.QAction(windowRefl) + self.actionPaste.setObjectName(_fromUtf8("actionPaste")) + self.actionCut = QtGui.QAction(windowRefl) + self.actionCut.setObjectName(_fromUtf8("actionCut")) + self.actionClear = QtGui.QAction(windowRefl) + self.actionClear.setObjectName(_fromUtf8("actionClear")) + self.actionChoose_Columns = QtGui.QAction(windowRefl) + self.actionChoose_Columns.setObjectName(_fromUtf8("actionChoose_Columns")) self.menuFile.addAction(self.actionOpen_Table) self.menuFile.addAction(self.actionReload_from_Disk) self.menuFile.addSeparator() @@ -256,7 +291,14 @@ def setupUi(self, windowRefl): self.menuFunction.addAction(self.actionClear_Table) self.menuFunction.addSeparator() self.menuFunction.addAction(self.actionSearch_RB) + self.menuEdit.addAction(self.actionCopy) + self.menuEdit.addAction(self.actionCut) + self.menuEdit.addAction(self.actionPaste) + self.menuEdit.addAction(self.actionClear) + self.menuView.addAction(self.actionChoose_Columns) self.menuBar.addAction(self.menuFile.menuAction()) + self.menuBar.addAction(self.menuEdit.menuAction()) + self.menuBar.addAction(self.menuView.menuAction()) self.menuBar.addAction(self.menuFunction.menuAction()) self.menuBar.addAction(self.menuHelp.menuAction()) self.labelInstrument.setBuddy(self.comboInstrument) @@ -274,8 +316,7 @@ def setupUi(self, windowRefl): windowRefl.setTabOrder(self.spinDepth, self.buttonSearch) windowRefl.setTabOrder(self.buttonSearch, self.checkTickAll) windowRefl.setTabOrder(self.checkTickAll, self.buttonAuto) - windowRefl.setTabOrder(self.buttonAuto, self.listMain) - windowRefl.setTabOrder(self.listMain, self.buttonTransfer) + windowRefl.setTabOrder(self.buttonAuto, self.buttonTransfer) windowRefl.setTabOrder(self.buttonTransfer, self.tableMain) windowRefl.setTabOrder(self.tableMain, self.buttonProcess) windowRefl.setTabOrder(self.buttonProcess, self.buttonClear) @@ -291,6 +332,7 @@ def retranslateUi(self, windowRefl): self.comboPolarCorrect.setItemText(0, QtGui.QApplication.translate("windowRefl", "None", None, QtGui.QApplication.UnicodeUTF8)) self.comboPolarCorrect.setItemText(1, QtGui.QApplication.translate("windowRefl", "1-PNR", None, QtGui.QApplication.UnicodeUTF8)) self.comboPolarCorrect.setItemText(2, QtGui.QApplication.translate("windowRefl", "2-PA", None, QtGui.QApplication.UnicodeUTF8)) + self.buttonColumns.setText(QtGui.QApplication.translate("windowRefl", "Choose Columns...", None, QtGui.QApplication.UnicodeUTF8)) self.labelRB.setText(QtGui.QApplication.translate("windowRefl", "RB Search:", None, QtGui.QApplication.UnicodeUTF8)) self.textRB.setToolTip(QtGui.QApplication.translate("windowRefl", "The term to search the archives for", None, QtGui.QApplication.UnicodeUTF8)) self.labelDepth.setText(QtGui.QApplication.translate("windowRefl", "Search Depth (Cycles):", None, QtGui.QApplication.UnicodeUTF8)) @@ -324,6 +366,8 @@ def retranslateUi(self, windowRefl): self.menuFile.setTitle(QtGui.QApplication.translate("windowRefl", "File", None, QtGui.QApplication.UnicodeUTF8)) self.menuHelp.setTitle(QtGui.QApplication.translate("windowRefl", "Help", None, QtGui.QApplication.UnicodeUTF8)) self.menuFunction.setTitle(QtGui.QApplication.translate("windowRefl", "Function", None, QtGui.QApplication.UnicodeUTF8)) + self.menuEdit.setTitle(QtGui.QApplication.translate("windowRefl", "Edit", None, QtGui.QApplication.UnicodeUTF8)) + self.menuView.setTitle(QtGui.QApplication.translate("windowRefl", "View", None, QtGui.QApplication.UnicodeUTF8)) self.actionSave_As.setText(QtGui.QApplication.translate("windowRefl", "Save As...", None, QtGui.QApplication.UnicodeUTF8)) self.actionSave_As.setShortcut(QtGui.QApplication.translate("windowRefl", "Ctrl+Alt+S", None, QtGui.QApplication.UnicodeUTF8)) self.actionOpen_Table.setText(QtGui.QApplication.translate("windowRefl", "Open Table...", None, QtGui.QApplication.UnicodeUTF8)) @@ -348,4 +392,14 @@ def retranslateUi(self, windowRefl): self.actionClear_Table.setShortcut(QtGui.QApplication.translate("windowRefl", "Alt+C", None, QtGui.QApplication.UnicodeUTF8)) self.actionSearch_RB.setText(QtGui.QApplication.translate("windowRefl", "Search RB", None, QtGui.QApplication.UnicodeUTF8)) self.actionSearch_RB.setShortcut(QtGui.QApplication.translate("windowRefl", "Alt+R", None, QtGui.QApplication.UnicodeUTF8)) + self.actionCopy.setText(QtGui.QApplication.translate("windowRefl", "Copy", None, QtGui.QApplication.UnicodeUTF8)) + self.actionCopy.setShortcut(QtGui.QApplication.translate("windowRefl", "Ctrl+C", None, QtGui.QApplication.UnicodeUTF8)) + self.actionPaste.setText(QtGui.QApplication.translate("windowRefl", "Paste", None, QtGui.QApplication.UnicodeUTF8)) + self.actionPaste.setShortcut(QtGui.QApplication.translate("windowRefl", "Ctrl+V", None, QtGui.QApplication.UnicodeUTF8)) + self.actionCut.setText(QtGui.QApplication.translate("windowRefl", "Cut", None, QtGui.QApplication.UnicodeUTF8)) + self.actionCut.setShortcut(QtGui.QApplication.translate("windowRefl", "Ctrl+X", None, QtGui.QApplication.UnicodeUTF8)) + self.actionClear.setText(QtGui.QApplication.translate("windowRefl", "Clear", None, QtGui.QApplication.UnicodeUTF8)) + self.actionClear.setShortcut(QtGui.QApplication.translate("windowRefl", "Del", None, QtGui.QApplication.UnicodeUTF8)) + self.actionChoose_Columns.setText(QtGui.QApplication.translate("windowRefl", "Choose Columns...", None, QtGui.QApplication.UnicodeUTF8)) + self.actionChoose_Columns.setShortcut(QtGui.QApplication.translate("windowRefl", "Ctrl+M", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.ui b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.ui index 6e5a7f216511..b55817243741 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.ui +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/refl_window.ui @@ -155,6 +155,13 @@ + + + + Choose Columns... + + + @@ -282,302 +289,344 @@ - - - - - - 0 - 0 - - - - - 200 - 16777215 - - - - QAbstractItemView::ExtendedSelection - - - - - - - - 0 - 0 - - - - - 25 - 16777215 - - - - => - - - - - + + + + 0 + 0 + + + + Qt::Horizontal + + + false + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 500 + 16777215 + + + + + 199 + 0 + + + + QAbstractItemView::ExtendedSelection + + + + - - - - 50 - false - - - - true + + + + 0 + 0 + - - 100 + + + 25 + 16777215 + - - 19 + + => - - true - - - 60 - - - 20 - - - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Run(s) - - - - - Angle 1 - - - - - trans 1 - - - - - qmin_1 - - - - - qmax_1 - - - - - Run(s) - - - - - Angle 2 - - - - - trans 2 - - - - - qmin_2 - - - - - qmax_2 - - - - - Run(s) - - - - - Angle 3 - - - - - trans 3 - - - - - qmin_3 - - - - - qmax_3 - - - - - dq/q - - - - - Scale - - - - - Stitch? - - - - - Plot? - - - + - - - - 0 - 0 - + + + + 50 + false + - - Process + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + true + + + QAbstractItemView::ContiguousSelection + + + 100 + + + 19 + + + false + + + 60 + + + 20 + + + false + + + false + + + 20 + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Run(s) + + + + + Angle 1 + + + + + trans 1 + + + + + qmin_1 + + + + + qmax_1 + + + + + Run(s) + + + + + Angle 2 + + + + + trans 2 + + + + + qmin_2 + + + + + qmax_2 + + + + + Run(s) + + + + + Angle 3 + + + + + trans 3 + + + + + qmin_3 + + + + + qmax_3 + + + + + dq/q + + + + + Scale + + + + + Stitch? + + + + + Plot? + + - - - Clear all - - + + + + + + 0 + 0 + + + + Process + + + + + + + Clear all + + + + - - + + + splitterList @@ -621,7 +670,24 @@ + + + Edit + + + + + + + + + View + + + + + @@ -728,6 +794,46 @@ Alt+R + + + Copy + + + Ctrl+C + + + + + Paste + + + Ctrl+V + + + + + Cut + + + Ctrl+X + + + + + Clear + + + Del + + + + + Choose Columns... + + + Ctrl+M + + comboInstrument @@ -738,7 +844,6 @@ buttonSearch checkTickAll buttonAuto - listMain buttonTransfer tableMain buttonProcess