diff --git a/Code/Mantid/Build/CMake/VersionNumber.cmake b/Code/Mantid/Build/CMake/VersionNumber.cmake index b7da7f4eb821946f8a26ddc7c769952a88f62f01..c0ca8be81a271bb2977160e6ff0a7e7972fc385c 100644 --- a/Code/Mantid/Build/CMake/VersionNumber.cmake +++ b/Code/Mantid/Build/CMake/VersionNumber.cmake @@ -1,7 +1,7 @@ # Set the version number here for MantidVersion and the package filenames set ( VERSION_MAJOR 3 ) -set ( VERSION_MINOR 4 ) +set ( VERSION_MINOR 5 ) # UNCOMMENT the next 'set' line to 'force' the patch version number to # a value (instead of using the count coming out of 'git describe') diff --git a/Code/Mantid/Build/Jenkins/doctests b/Code/Mantid/Build/Jenkins/doctests index f17f988f6d591144e7f8bc3bf244b77aa8fe99c7..3d3d8f98cf19bac1fe5416b7eb7fa9785fc0d542 100755 --- a/Code/Mantid/Build/Jenkins/doctests +++ b/Code/Mantid/Build/Jenkins/doctests @@ -18,7 +18,10 @@ cmake --version ##################################################################################### # Find and install package ##################################################################################### -python $WORKSPACE/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py install $WORKSPACE +INSTALLER_SCRIPT=$WORKSPACE/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py +EXE_PATH_FILE=$PWD/mantidplotpath.txt +python ${INSTALLER_SCRIPT} install $WORKSPACE --dump-exe-path=${EXE_PATH_FILE} +MANTIDPLOT_EXE=$(cat ${EXE_PATH_FILE}) ############################################################################### # Set up the location for the local object store outside of the build and @@ -72,13 +75,13 @@ echo "UpdateInstrumentDefinitions.OnStartup = 0" >> $userprops echo "usagereports.enabled = 0" >> $userprops set +e #don't immediately exit on failure so that we can remove the package -/opt/mantidnightly/bin/MantidPlot -xq docs/runsphinx_doctest.py +${MANTIDPLOT_EXE} -xq docs/runsphinx_doctest.py status=$? set -e #exit on failures from now on ##################################################################################### # Remove package ##################################################################################### -python $WORKSPACE/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py uninstall $WORKSPACE +python ${INSTALLER_SCRIPT} uninstall $WORKSPACE exit $status diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h index da0d69ffe73332641d686d28a75e4719c41e8ea1..1a5368c75e418df59f18a7a9f9ccf6d15cf229af 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h @@ -85,6 +85,14 @@ public: virtual void setCoordinateSystem( const Mantid::Kernel::SpecialCoordinateSystem coordinateSystem) = 0; + /// Preferred visual normalizaiton method for any histo workspaces created from this. + virtual void setDisplayNormalizationHisto(Mantid::API::MDNormalization preferredNormalizationHisto) = 0; + virtual Mantid::API::MDNormalization displayNormalizationHisto() const = 0; + + /// Preferred visual normalization method. + virtual void setDisplayNormalization(Mantid::API::MDNormalization preferredNormalization) = 0; + virtual Mantid::API::MDNormalization displayNormalization() const = 0; + protected: /// Protected copy constructor. May be used by childs for cloning. IMDEventWorkspace(const IMDEventWorkspace &other); diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h index 3f9dd4549f9d36ebc464abbf2d83df7f4b9635a8..9c5c55b504522f00c1ed8bf914332f7c264ece7c 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDHistoWorkspace.h @@ -96,6 +96,8 @@ public: virtual void setCoordinateSystem( const Kernel::SpecialCoordinateSystem coordinateSystem) = 0; + virtual void setDisplayNormalization( + const Mantid::API::MDNormalization &preferredNormalization) = 0; protected: /// Protected copy constructor. May be used by childs for cloning. diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDWorkspace.h index 60ca7df82c32da0af0c6fa5fc48806ce7b67f74f..2d5a6819ddbba3f801d74cfd109a2418dc98ecd1 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDWorkspace.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDWorkspace.h @@ -137,6 +137,9 @@ public: // Preferred normalization to use for display virtual MDNormalization displayNormalization() const; + // Preferred normalization to use for displaying histo workspaces + virtual MDNormalization displayNormalizationHisto() const; + protected: /// Protected copy constructor. May be used by childs for cloning. IMDWorkspace(const IMDWorkspace &other); diff --git a/Code/Mantid/Framework/API/src/IMDWorkspace.cpp b/Code/Mantid/Framework/API/src/IMDWorkspace.cpp index e5484916df383d96b3904bcaacbf82dd17167c0b..9812d703f61a2611eb031ab7468eefabacd47c68 100644 --- a/Code/Mantid/Framework/API/src/IMDWorkspace.cpp +++ b/Code/Mantid/Framework/API/src/IMDWorkspace.cpp @@ -129,6 +129,13 @@ void IMDWorkspace::getLinePlot(const Mantid::Kernel::VMD &start, MDNormalization IMDWorkspace::displayNormalization() const { return NoNormalization; } + +/** +@return normalization preferred for visualization of histo workspaces. Set to none for the generic case, but overriden elsewhere. +*/ +MDNormalization IMDWorkspace::displayNormalizationHisto() const { + return NoNormalization; +} } } diff --git a/Code/Mantid/Framework/Algorithms/src/RemovePromptPulse.cpp b/Code/Mantid/Framework/Algorithms/src/RemovePromptPulse.cpp index f3f00a8d7ab17325b12b387f793814f002461b11..ceaecb85d4746b238478623d474eab6efed925c3 100644 --- a/Code/Mantid/Framework/Algorithms/src/RemovePromptPulse.cpp +++ b/Code/Mantid/Framework/Algorithms/src/RemovePromptPulse.cpp @@ -136,14 +136,18 @@ void RemovePromptPulse::exec() { // run maskbins to do the work on the first prompt pulse IAlgorithm_sptr algo = this->createChildAlgorithm("MaskBins"); - if (outputWS) + if (outputWS) { algo->setProperty<MatrixWorkspace_sptr>( "InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(outputWS)); - else + } else { // should only be first time algo->setProperty<MatrixWorkspace_sptr>( "InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(inputWS)); + outputWS = this->getProperty("OutputWorkspace"); + } + // always write to correct output workspace + algo->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); algo->setProperty<double>("XMin", *left); algo->setProperty<double>("XMax", right); algo->executeAsChildAlg(); diff --git a/Code/Mantid/Framework/Algorithms/src/SetUncertainties.cpp b/Code/Mantid/Framework/Algorithms/src/SetUncertainties.cpp index a793aa19ac9ebfdb25a12a39ad04a8c358b7006f..d911fc86fda156dba0f8af39b517e46d36a9bc62 100644 --- a/Code/Mantid/Framework/Algorithms/src/SetUncertainties.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SetUncertainties.cpp @@ -14,6 +14,11 @@ DECLARE_ALGORITHM(SetUncertainties) using namespace Kernel; using namespace API; +namespace { +/// Used to compare signal to zero +const double TOLERANCE=1.e-10; +} + /// (Empty) Constructor SetUncertainties::SetUncertainties() : API::Algorithm() {} @@ -70,7 +75,9 @@ void SetUncertainties::exec() { MantidVec &E = outputWorkspace->dataE(i); std::size_t numE = E.size(); for (std::size_t j = 0; j < numE; j++) { - E[j] = sqrt(fabs(Y[j])); + const double y_val = fabs(Y[j]); + if (y_val > TOLERANCE) + E[j] = sqrt(y_val); } } diff --git a/Code/Mantid/Framework/Algorithms/test/MayersSampleCorrectionStrategyTest.h b/Code/Mantid/Framework/Algorithms/test/MayersSampleCorrectionStrategyTest.h index 315dcae787eee24f3cf242887be7db1ee1bb9ecf..436c5fa8471da63f8b56b74b3fb2fbe1ff412458 100644 --- a/Code/Mantid/Framework/Algorithms/test/MayersSampleCorrectionStrategyTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MayersSampleCorrectionStrategyTest.h @@ -31,9 +31,7 @@ public: TS_ASSERT_DELTA(0.00030887, absFactor, delta); } - // clang-format off void test_Multiple_Scattering_With_Fixed_Mur_And_Absorption_Correction_Factor() - // clang-format on { std::vector<double> dummy(2, 0.0); dummy[1] = 1.0; @@ -73,9 +71,7 @@ public: TS_ASSERT_DELTA(0.2660792, error.back(), delta); } - // clang-format off void test_Corrects_Both_Absorption_And_Multiple_Scattering_For_Histogram_Data() - // clang-format on { using std::sqrt; const size_t nypts(100); diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 7379affafbe812884f07186fe100ad7759efae27..049c3199007152f5bf2e911d9557314d0282e510 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -139,6 +139,7 @@ set ( SRC_FILES src/SaveNXTomo.cpp src/SaveNexus.cpp src/SaveNexusProcessed.cpp + src/SaveOpenGenieAscii.cpp src/SavePAR.cpp src/SavePDFGui.cpp src/SavePHX.cpp @@ -293,6 +294,7 @@ set ( INC_FILES inc/MantidDataHandling/SaveNXTomo.h inc/MantidDataHandling/SaveNexus.h inc/MantidDataHandling/SaveNexusProcessed.h + inc/MantidDataHandling/SaveOpenGenieAscii.h inc/MantidDataHandling/SavePAR.h inc/MantidDataHandling/SavePDFGui.h inc/MantidDataHandling/SavePHX.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveOpenGenieAscii.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveOpenGenieAscii.h new file mode 100644 index 0000000000000000000000000000000000000000..514e1a4c4b3bcc34481c8cf0fa24b55e42264e3a --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveOpenGenieAscii.h @@ -0,0 +1,77 @@ +#ifndef DATAHANDING_SAVEOPENGENIEASCII_H_ +#define DATAHANDING_SAVEOPENGENIEASCII_H_ + +//--------------------------------------------------- +// Includes +//--------------------------------------------------- +#include "MantidAPI/Algorithm.h" +#include "MantidKernel/cow_ptr.h" +#include "MantidKernel/TimeSeriesProperty.h" + +namespace Mantid { +namespace DatHandling { + +class DLLExport SaveOpenGenieAscii : public Mantid::API::Algorithm { +public: + /// (Empty) Constructor + SaveOpenGenieAscii(); + + //// Virtual destructor + virtual ~SaveOpenGenieAscii() {} + + /// Algorithm's name + virtual const std::string name() const { return "SaveOpenGenieAscii"; } + + /// Summary of algorithms purpose + virtual const std::string summary() const { + return "Saves a focused data set into an OpenGenie ASCII file "; + } + + /// Algorithm's version + virtual int version() const { return (1); } + + /// Algorithm's category for identification + virtual const std::string category() const { + return "Diffraction;DataHandling\\Text"; + } + +private: + /// Initialisation code + void init(); + + /// Execution code + void exec(); + + // write file header + void writeFileHeader(std::ofstream &outfile); + + /// Uses AxisHeader and WriteAxisValues to write out file + void axisToFile(const std::string alpha, const std::string singleSpc, + const std::string fourspc, int nBins, bool isHistogram); + + /// Generates the header for the axis which saves to file + std::string getAxisHeader(const std::string alpha, + const std::string singleSpc, + const std::string fourspc, int nBins); + + /// Reads if alpha is e then reads the E values accordingly + std::string getAxisValues(std::string alpha, int bin, + const std::string singleSpc); + + /// Generates the header which saves to the openGenie file + void getSampleLogs(std::string fourspc); + + /// sort and write out the sample logs + void writeSampleLogs(std::ofstream &outfile); + + /// add ntc field which is required for OpenGenie + void addNtc(const std::string fourspc, int nBins); + + /// Vector to safe sample log + std::vector<std::string> logVector; + /// Workspace + API::MatrixWorkspace_sptr ws; +}; +} +} +#endif // DATAHANDING_SAVEOPENGENIEASCII_H_ diff --git a/Code/Mantid/Framework/DataHandling/src/LoadDiffCal.cpp b/Code/Mantid/Framework/DataHandling/src/LoadDiffCal.cpp index 36db1c26b4fe7001fa5eba108f6a29d13f84a9a7..32771d165a676032cea9c62801dcf253b53ce314 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadDiffCal.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadDiffCal.cpp @@ -359,8 +359,8 @@ void LoadDiffCal::runLoadCalFile() { alg->setPropertyValue("InstrumentFilename", getPropertyValue("InstrumentFilename")); alg->setProperty<bool>("MakeOffsetsWorkspace", makeCalWS); - alg->setProperty<bool>("MakeGroupingWorkspace", makeMaskWS); - alg->setProperty<bool>("MakeMaskWorkspace", makeGroupWS); + alg->setProperty<bool>("MakeGroupingWorkspace", makeGroupWS); + alg->setProperty<bool>("MakeMaskWorkspace", makeMaskWS); alg->setPropertyValue("WorkspaceName", m_workspaceName); alg->executeAsChildAlg(); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp index 19de2c253b74c8db162ca08f49d10e546b81908e..1734ed99eda06498bfa23cd22d68a6b5bf332f8e 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp @@ -16,10 +16,6 @@ using namespace Mantid::DataHandling; using namespace Mantid::DataObjects; using namespace Mantid::API; using namespace Mantid::Kernel; -using namespace std; -using namespace boost; - -namespace {} namespace Mantid { namespace DataHandling { @@ -203,9 +199,9 @@ void LoadFITS::doLoadFiles(const std::vector<std::string> &paths, } MantidImage imageY(headers[0].axisPixelLengths[1], - vector<double>(headers[0].axisPixelLengths[0])); + std::vector<double>(headers[0].axisPixelLengths[0])); MantidImage imageE(headers[0].axisPixelLengths[1], - vector<double>(headers[0].axisPixelLengths[0])); + std::vector<double>(headers[0].axisPixelLengths[0])); size_t bytes = (headers[0].bitsPerPixel / 8) * m_pixelCount; std::vector<char> buffer; @@ -219,7 +215,7 @@ void LoadFITS::doLoadFiles(const std::vector<std::string> &paths, // Create a group for these new workspaces, if the group already exists, add // to it. - string groupName = outWSName; + std::string groupName = outWSName; // This forms the name of the group m_baseName = getPropertyValue("OutputWorkspace") + "_"; @@ -266,11 +262,11 @@ void LoadFITS::doLoadFiles(const std::vector<std::string> &paths, directoryName = directoryName + "/IMAT_Definition.xml"; loadInst->setPropertyValue("Filename", directoryName); loadInst->setProperty<MatrixWorkspace_sptr>( - "Workspace", dynamic_pointer_cast<MatrixWorkspace>(latestWS)); + "Workspace", boost::dynamic_pointer_cast<MatrixWorkspace>(latestWS)); loadInst->execute(); } catch (std::exception &ex) { g_log.information("Cannot load the instrument definition. " + - string(ex.what())); + std::string(ex.what())); } } @@ -335,7 +331,7 @@ void LoadFITS::doLoadHeaders(const std::vector<std::string> &paths, } try { - headers[i].bitsPerPixel = lexical_cast<int>(tmpBitPix); + headers[i].bitsPerPixel = boost::lexical_cast<int>(tmpBitPix); } catch (std::exception &e) { throw std::runtime_error( "Coult not interpret the entry number of bits per pixel (" + @@ -376,7 +372,7 @@ void LoadFITS::doLoadHeaders(const std::vector<std::string> &paths, headers[i].numberOfAxis = static_cast<int>(m_headerAxisNameKeys.size()); for (int j = 0; headers.size() > i && j < headers[i].numberOfAxis; ++j) { - headers[i].axisPixelLengths.push_back(lexical_cast<size_t>( + headers[i].axisPixelLengths.push_back(boost::lexical_cast<size_t>( headers[i].headerKeys[m_headerAxisNameKeys[j]])); g_log.information() << "Found axis length header entry: " << m_headerAxisNameKeys[j] @@ -399,8 +395,8 @@ void LoadFITS::doLoadHeaders(const std::vector<std::string> &paths, headers[i].scale = 1; } else { try { - headers[i].scale = - lexical_cast<double>(headers[i].headerKeys[m_headerScaleKey]); + headers[i].scale = boost::lexical_cast<double>( + headers[i].headerKeys[m_headerScaleKey]); } catch (std::exception &e) { throw std::runtime_error( "Coult not interpret the entry number of bits per pixel (" + @@ -416,14 +412,14 @@ void LoadFITS::doLoadHeaders(const std::vector<std::string> &paths, } else { try { headers[i].offset = - lexical_cast<int>(headers[i].headerKeys[m_headerOffsetKey]); + boost::lexical_cast<int>(headers[i].headerKeys[m_headerOffsetKey]); } catch (std::exception & /*e*/) { // still, second try with floating point format (as used for example // by // Starlight XPRESS cameras) try { - double doff = - lexical_cast<double>(headers[i].headerKeys[m_headerOffsetKey]); + double doff = boost::lexical_cast<double>( + headers[i].headerKeys[m_headerOffsetKey]); double intPart; if (0 != modf(doff, &intPart)) { // anyway we'll do a cast, but warn if there was a fraction @@ -465,7 +461,7 @@ void LoadFITS::doLoadHeaders(const std::vector<std::string> &paths, */ void LoadFITS::parseHeader(FITSInfo &headerInfo) { headerInfo.headerSizeMultiplier = 0; - ifstream istr(headerInfo.filePath.c_str(), ios::binary); + std::ifstream istr(headerInfo.filePath.c_str(), std::ios::binary); Poco::BinaryReader reader(istr); // Iterate 80 bytes at a time until header is parsed | 2880 bytes is the @@ -477,7 +473,7 @@ void LoadFITS::parseHeader(FITSInfo &headerInfo) { for (int i = 0; i < 36; ++i) { // Keep vect of each header item, including comments, and also keep a // map of individual keys. - string part; + std::string part; reader.readRaw(80, part); headerInfo.headerItems.push_back(part); @@ -486,8 +482,8 @@ void LoadFITS::parseHeader(FITSInfo &headerInfo) { // unique auto eqPos = part.find('='); if (eqPos > 0) { - string key = part.substr(0, eqPos); - string value = part.substr(eqPos + 1); + std::string key = part.substr(0, eqPos); + std::string value = part.substr(eqPos + 1); // Comments are added after the value separated by a / symbol. Remove. auto slashPos = value.find('/'); @@ -534,10 +530,10 @@ LoadFITS::makeWorkspace(const FITSInfo &fileInfo, size_t &newFileNumber, MantidImage &imageE, const Workspace2D_sptr parent, bool loadAsRectImg) { - string currNumberS = padZeros(newFileNumber, g_DIGIT_SIZE_APPEND); + std::string currNumberS = padZeros(newFileNumber, g_DIGIT_SIZE_APPEND); ++newFileNumber; - string baseName = m_baseName + currNumberS; + std::string baseName = m_baseName + currNumberS; // set data readDataToImgs(fileInfo, imageY, imageE, buffer); @@ -547,12 +543,12 @@ LoadFITS::makeWorkspace(const FITSInfo &fileInfo, size_t &newFileNumber, if (!parent) { if (!loadAsRectImg) { size_t finalPixelCount = m_pixelCount / m_rebin * m_rebin; - ws = - dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create( - "Workspace2D", finalPixelCount, 2, 1)); + ws = boost::dynamic_pointer_cast<Workspace2D>( + WorkspaceFactory::Instance().create("Workspace2D", finalPixelCount, 2, + 1)); } else { - ws = - dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create( + ws = boost::dynamic_pointer_cast<Workspace2D>( + WorkspaceFactory::Instance().create( "Workspace2D", fileInfo.axisPixelLengths[1] / m_rebin, // one bin per column fileInfo.axisPixelLengths[0] / m_rebin + @@ -560,7 +556,7 @@ LoadFITS::makeWorkspace(const FITSInfo &fileInfo, size_t &newFileNumber, fileInfo.axisPixelLengths[0] / m_rebin)); } } else { - ws = dynamic_pointer_cast<Workspace2D>( + ws = boost::dynamic_pointer_cast<Workspace2D>( WorkspaceFactory::Instance().create(parent)); } @@ -634,7 +630,7 @@ LoadFITS::makeWorkspace(const FITSInfo &fileInfo, size_t &newFileNumber, ++it) { ws->mutableRun().removeLogData(it->first, true); ws->mutableRun().addLogData( - new PropertyWithValue<string>(it->first, it->second)); + new PropertyWithValue<std::string>(it->first, it->second)); } // Add rotational data to log. Clear first from copied WS @@ -828,8 +824,8 @@ void LoadFITS::doRebin(size_t rebin, MantidImage &imageY, MantidImage &imageE, for (size_t i = 0; i < (rebinnedY[0].size() - rebin + 1); ++i) { double accumY = 0.0; double accumE = 0.0; - size_t origJ = j*rebin; - size_t origI = i*rebin; + size_t origJ = j * rebin; + size_t origI = i * rebin; for (size_t k = 0; k < rebin; ++k) { for (size_t l = 0; l < rebin; ++l) { accumY += imageY[origJ + k][origI + l]; @@ -945,14 +941,14 @@ bool LoadFITS::isInstrOtherThanIMAT(FITSInfo &hdr) { * and leading 0's */ size_t LoadFITS::fetchNumber(const std::string &name) { - string tmpStr = ""; + std::string tmpStr = ""; for (auto it = name.end() - 1; isdigit(*it); --it) { tmpStr.insert(0, 1, *it); } while (tmpStr.length() > 0 && tmpStr[0] == '0') { tmpStr.erase(tmpStr.begin()); } - return (tmpStr.length() > 0) ? lexical_cast<size_t>(tmpStr) : 0; + return (tmpStr.length() > 0) ? boost::lexical_cast<size_t>(tmpStr) : 0; } /** @@ -984,14 +980,14 @@ void LoadFITS::mapHeaderKeys() { // If a map file is selected, use that. std::string name = getPropertyValue(g_HEADER_MAP_NAME); - ifstream fStream(name.c_str()); + std::ifstream fStream(name.c_str()); try { // Ensure valid file if (fStream.good()) { // Get lines, split words, verify and add to map. std::string line; - vector<std::string> lineSplit; + std::vector<std::string> lineSplit; while (getline(fStream, line)) { boost::split(lineSplit, line, boost::is_any_of("=")); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadSpice2D.cpp b/Code/Mantid/Framework/DataHandling/src/LoadSpice2D.cpp index 49b271ef922119cdc8cc72c0aa813f1c0de1d7e0..a393b859b983242d2db843750dcd928dec41ff29 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadSpice2D.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadSpice2D.cpp @@ -373,10 +373,6 @@ void LoadSpice2D::exec() { ipixel++; } - // run load instrument - runLoadInstrument(instrument, ws); - runLoadMappingTable(ws, numberXPixels, numberYPixels); - // Set the run properties ws->mutableRun().addProperty("sample-detector-distance", distance, "mm", true); @@ -399,6 +395,10 @@ void LoadSpice2D::exec() { ws->mutableRun().addProperty("start_time", start_time, "", true); ws->mutableRun().addProperty("run_start", start_time, "", true); + // run load instrument + runLoadInstrument(instrument, ws); + runLoadMappingTable(ws, numberXPixels, numberYPixels); + // Move the detector to the right position API::IAlgorithm_sptr mover = createChildAlgorithm("MoveInstrumentComponent"); diff --git a/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp b/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp index f06c8d23e35e7baebdc87e356d62239db02bd22e..960422514becf2359a87f953e7126a8d71a4c92c 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveGSS.cpp @@ -21,11 +21,30 @@ using namespace Mantid::API; // Register the algorithm into the AlgorithmFactory DECLARE_ALGORITHM(SaveGSS) +namespace { const std::string RALF("RALF"); const std::string SLOG("SLOG"); +const double TOLERANCE = 1.e-10; +} SaveGSS::SaveGSS() : Mantid::API::Algorithm(), m_useSpecAsBank(false) {} +bool isEqual(const double left, const double right) { + if (left == right) + return true; + return (2.*std::fabs(left - right) <= std::fabs(TOLERANCE * (right+left))); +} + +bool isConstantDelta(const MantidVec &xAxis) { + const double deltaX = (xAxis[1] - xAxis[0]); + for (std::size_t i = 1; i < xAxis.size(); ++i) { + if (!isEqual(xAxis[i] - xAxis[i - 1], deltaX)) { + return false; + } + } + return true; +} + //--------------------------------------------------- // Private member functions //--------------------------------------------------- @@ -551,6 +570,12 @@ void SaveGSS::writeSLOGdata(const int bank, const bool MultiplyByBinWidth, throw std::runtime_error( "Cannot write out logarithmic data starting at zero"); } + if (isConstantDelta(X)) { + std::stringstream msg; + msg << "While writing SLOG format: Found constant delta-T binning for bank " + << bank; + throw std::runtime_error(msg.str()); + } double bc2 = 0.5 * (*(X.rbegin()) + *(X.rbegin() + 1)); // maximum TOF (in microseconds?) double bc3 = (*(X.begin() + 1) - bc1) / bc1; // deltaT/T diff --git a/Code/Mantid/Framework/DataHandling/src/SaveOpenGenieAscii.cpp b/Code/Mantid/Framework/DataHandling/src/SaveOpenGenieAscii.cpp new file mode 100644 index 0000000000000000000000000000000000000000..806fe29cb4ca6b83765e9b96a5fccaa5371256ab --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/src/SaveOpenGenieAscii.cpp @@ -0,0 +1,304 @@ +//--------------------------------------------------- +// Includes +//--------------------------------------------------- +#include "MantidAPI/FileProperty.h" +#include "MantidDataHandling/SaveOpenGenieAscii.h" +#include "MantidKernel/ListValidator.h" +#include "MantidKernel/Exception.h" +#include "MantidKernel/Property.h" + +#include <exception> +#include <fstream> +#include <list> +#include <vector> +#include <Poco/File.h> +#include <Poco/Path.h> + +namespace Mantid { +namespace DatHandling { + +using namespace Kernel; +using namespace Mantid::API; + +// Register the algorithm into the AlgorithmFactory +DECLARE_ALGORITHM(SaveOpenGenieAscii) + +/// Empty constructor +SaveOpenGenieAscii::SaveOpenGenieAscii() : Mantid::API::Algorithm() {} + +//--------------------------------------------------- +// Private member functions +//--------------------------------------------------- +/** + * Initialise the algorithm + */ + +void SaveOpenGenieAscii::init() { + declareProperty( + new API::WorkspaceProperty<>("InputWorkspace", "", + Kernel::Direction::Input), + "The name of the workspace containing the data you wish to save"); + + // Declare required parameters, filename with ext {.his} and input + // workspac + std::vector<std::string> his_exts; + his_exts.push_back(".his"); + his_exts.push_back(".txt"); + his_exts.push_back(""); + declareProperty( + new API::FileProperty("Filename", "", API::FileProperty::Save, his_exts), + "The filename to use for the saved data"); + declareProperty("IncludeHeader", true, + "Whether to include the header lines (default: true)"); +} + +void SaveOpenGenieAscii::exec() { + // Process properties + + // Retrieve the input workspace + /// Workspace + ws = getProperty("InputWorkspace"); + int nSpectra = static_cast<int>(ws->getNumberHistograms()); + int nBins = static_cast<int>(ws->blocksize()); + + // Retrieve the filename from the properties + std::string filename = getProperty("Filename"); + + // Output string variables + const std::string singleSpc = " "; + const std::string fourspc = " "; + + // file + std::ofstream outfile(filename.c_str()); + if (!outfile) { + g_log.error("Unable to create file: " + filename); + throw Exception::FileError("Unable to create file: ", filename); + } + if (nBins == 0 || nSpectra == 0) + throw std::runtime_error("Trying to save an empty workspace"); + + // Axis alphabets + const std::string Alpha[] = {"\"e\"", "\"x\"", "\"y\""}; + + const bool headers = getProperty("IncludeHeader"); + // if true write file header + if (headers) { + writeFileHeader(outfile); + } + + bool isHistogram = ws->isHistogramData(); + Progress progress(this, 0, 1, nBins); + + // writes out x, y, e to vector + std::string alpha; + for (int Num = 0; Num < 3; Num++) { + alpha = Alpha[Num]; + axisToFile(alpha, singleSpc, fourspc, nBins, isHistogram); + } + + // get all the sample in workspace + getSampleLogs(fourspc); + + // add ntc sample log + addNtc(fourspc, nBins); + + // write out all samples in the vector + writeSampleLogs(outfile); + + progress.report(); + return; +} + +// ----------------------------------------------------------------------------- +/** generates the OpenGenie file header + * @param outfile :: File it will save it out to + */ +void SaveOpenGenieAscii::writeFileHeader(std::ofstream &outfile) { + + const std::vector<Property *> &logData = ws->run().getLogData(); + auto &log = logData; + // get total number of sample logs + auto samplenumber = (&log)->size(); + samplenumber += 3; // x, y, e + + outfile << "# Open Genie ASCII File #" << std::endl + << "# label " << std::endl + << "GXWorkspace" << std::endl + // number of entries + << samplenumber << std::endl; +} + +//------------------------------------------------------------------------------ +/** generates the header for the axis which saves to file + * @param alpha :: onstant string Axis letter that is being used + * @param singleSpc :: Constant string for single space + * @param fourspc :: Constant string for four spaces + * @param nBins :: Number of bins + * @return A string of of the header for the x y and e + */ +std::string SaveOpenGenieAscii::getAxisHeader(const std::string alpha, + const std::string singleSpc, + const std::string fourspc, + int nBins) { + std::string outStr = ""; + const std::string GXR = "GXRealarray"; + const std::string banknum = "1"; + const std::string twospc = " "; + + outStr += twospc + singleSpc + alpha + "\n"; + outStr += fourspc + GXR + "\n"; + outStr += fourspc + banknum + "\n"; + outStr += fourspc + boost::lexical_cast<std::string>(nBins) + "\n"; + + return outStr; +} + +//----------------------------------------------------------------------------- +/** Uses AxisHeader and WriteAxisValues to write in vector + * @param alpha :: Axis letter that is being used + * @param singleSpc :: Constant string for single space + * @param fourspc :: Constant string for four spaces + * @param nBins :: number of bins + * @param isHistogram :: If its a histogram + */ +void SaveOpenGenieAscii::axisToFile(const std::string alpha, + const std::string singleSpc, + const std::string fourspc, int nBins, + bool isHistogram) { + std::string out_str = getAxisHeader(alpha, singleSpc, fourspc, nBins); + for (int bin = 0; bin < nBins; bin++) { + if (isHistogram) // bin centres + { + if (bin == 0) { + out_str += fourspc; + } + auto axisStr = getAxisValues(alpha, bin, singleSpc); + out_str += axisStr; + + if ((bin + 1) % 10 == 0 && bin != (nBins - 1)) { + out_str += "\n" + fourspc; + } + } + } + out_str += "\n"; + logVector.push_back(out_str); +} + +//------------------------------------------------------------------------ +/** Reads if alpha is e then reads the E values accordingly + * @param alpha :: Axis letter that is being used + * @param bin :: bin counter which goes through all the bin + * @param singleSpc :: Constant string for single space + * @return A string of either e, x or y + */ +std::string SaveOpenGenieAscii::getAxisValues(std::string alpha, int bin, + const std::string singleSpc) { + std::string output = ""; + if (alpha == "\"e\"") { + output += boost::lexical_cast<std::string>(ws->readE(0)[bin]) + singleSpc; + } + if (alpha == "\"x\"") { + output += boost::lexical_cast<std::string>(ws->readX(0)[bin]) + singleSpc; + } + if (alpha == "\"y\"") { + output += boost::lexical_cast<std::string>(ws->readY(0)[bin]) + singleSpc; + } + return output; +} + +//----------------------------------------------------------------------- +/** Reads the sample logs and writes to vector + * @param fourspc :: Constant string for four spaces + */ +void SaveOpenGenieAscii::getSampleLogs(std::string fourspc) { + const std::vector<Property *> &logData = ws->run().getLogData(); + + for (auto log = logData.begin(); log != logData.end(); ++log) { + std::string name = (*log)->name(); + std::string type = (*log)->type(); + std::string value = (*log)->value(); + + if (type.std::string::find("vector") && + type.std::string::find("double") != std::string::npos) { + + auto tsp = ws->run().getTimeSeriesProperty<double>(name); + value = boost::lexical_cast<std::string>(tsp->timeAverageValue()); + } + + else if (type.std::string::find("vector") && + type.std::string::find("int") != std::string::npos) { + + auto tsp = ws->run().getTimeSeriesProperty<int>(name); + value = boost::lexical_cast<std::string>(tsp->timeAverageValue()); + } + + else if (type.std::string::find("vector") && + type.std::string::find("bool") != std::string::npos) { + + auto tsp = ws->run().getTimeSeriesProperty<bool>(name); + value = boost::lexical_cast<std::string>(tsp->timeAverageValue()); + } + + else if (type.std::string::find("vector") && + type.std::string::find("char") != std::string::npos) { + + auto tsp = ws->run().getTimeSeriesProperty<std::string>(name); + value = (tsp->lastValue()); + } + + if ((type.std::string::find("number") != std::string::npos) || + (type.std::string::find("double") != std::string::npos) || + (type.std::string::find("dbl list") != std::string::npos)) { + type = "Float"; + } + + else if ((type.std::string::find("TimeValueUnit<bool>") != + std::string::npos) || + (type.std::string::find("TimeValueUnit<int>") != + std::string::npos)) { + type = "Integer"; + } + + else if (type.std::string::find("string") != std::string::npos) { + type = "String"; + } + + if (name != "x" && name != "y" && name != "e") { + std::string outStr = (" \"" + name + "\"" + "\n" + fourspc + type + + "\n" + fourspc + value + "\n"); + + logVector.push_back(outStr); + } + } +} + +//------------------------------------------------------------------------------ +/** Sorts the vector and writes outt he sample logs to file + * @param outfile :: File it will save it out to + */ +void SaveOpenGenieAscii::writeSampleLogs(std::ofstream &outfile) { + sort(logVector.begin(), logVector.end()); + + for (std::vector<std::string>::const_iterator i = logVector.begin(); + i != logVector.end(); ++i) { + outfile << *i << ' '; + } +} + +//------------------------------------------------------------------------------ +/** Add ntc field (num of bins) required to run open genie + * @param fourspc :: Constant string for four spaces + * @param nBins :: Number of bins + */ +void SaveOpenGenieAscii::addNtc(const std::string fourspc, int nBins) { + std::string outStr = ""; + std::string ntc = "ntc"; + + outStr += (" \"" + ntc + "\"" + "\n" + fourspc + "Integer" + "\n" + fourspc + + boost::lexical_cast<std::string>(nBins) + "\n"); + + logVector.push_back(outStr); +} + +} // namespace DataHandling +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventFactory.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventFactory.h index ed449357da9320dcf3a5fdb3bd7ae34460720d3f..23b36f832d7c6cd913eb5543895c82d7e032e4c7 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventFactory.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventFactory.h @@ -46,9 +46,14 @@ public: }; MDEventFactory() {} ~MDEventFactory() {} + // create MD workspace factory call static API::IMDEventWorkspace_sptr - CreateMDWorkspace(size_t nd, const std::string &eventType = "MDLeanEvent"); + CreateMDWorkspace(size_t nd, const std::string &eventType = "MDLeanEvent", + const Mantid::API::MDNormalization& preferredNormalization = + Mantid::API::MDNormalization::VolumeNormalization, + const Mantid::API::MDNormalization& preferredNormalizationHisto = + Mantid::API::MDNormalization::VolumeNormalization); // create MDBox factory call static API::IMDNode * @@ -73,7 +78,10 @@ private: // typedef for the class function pointer to the function, which creates MD // Workspaces - typedef API::IMDEventWorkspace *(*fpCreateMDWS)(const std::string &eventType); + typedef API::IMDEventWorkspace *(*fpCreateMDWS)( + const std::string &eventType, + const Mantid::API::MDNormalization &preferredNormalization, + const Mantid::API::MDNormalization &preferredNormalizationHisto); // vector of function pointers to the funcions static std::vector<fpCreateMDWS> wsCreatorFP; @@ -82,7 +90,9 @@ private: // custom memory allocator template <size_t nd> static API::IMDEventWorkspace * - createMDWorkspaceND(const std::string &eventType); + createMDWorkspaceND(const std::string &eventType, + const Mantid::API::MDNormalization& preferredNormalization, + const Mantid::API::MDNormalization& preferredNormalizationHisto); // local wrappers around the MDBox/MDGridBox constructors as the constructor's // address can not be taken. This can also help in a future when writing diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.h index 50adc6e03b80e802bec95cb242673a33de7bdc03..233d8f29ad315e534dbaa8243d29c1c5d9ccc41e 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.h @@ -39,7 +39,9 @@ public: /// Typedef to access the MDEventType. typedef MDE MDEventType; - MDEventWorkspace(); + MDEventWorkspace(Mantid::API::MDNormalization preferredNormalization = Mantid::API::MDNormalization::VolumeNormalization, + Mantid::API::MDNormalization preferredNormalizationHisto = Mantid::API::MDNormalization::VolumeNormalization); + virtual ~MDEventWorkspace(); /// Returns a clone of the workspace @@ -166,7 +168,12 @@ public: /// and close back-up files. virtual void clearFileBacked(bool LoadFileBackedData); + /// Preferred visual normalizaiton method for any histo workspaces created from this. + virtual void setDisplayNormalizationHisto(Mantid::API::MDNormalization preferredNormalizationHisto); + virtual Mantid::API::MDNormalization displayNormalizationHisto() const; + /// Preferred visual normalization method. + virtual void setDisplayNormalization(Mantid::API::MDNormalization preferredNormalization); virtual Mantid::API::MDNormalization displayNormalization() const; protected: @@ -189,6 +196,11 @@ protected: /// Box controller in use API::BoxController_sptr m_BoxController; // boost::shared_ptr<BoxCtrlChangesList > m_BoxController; + /// Display normalization for the event workspace itself + Mantid::API::MDNormalization m_displayNormalization; + /// Display normalization to pass onto generated histo workspaces + Mantid::API::MDNormalization m_displayNormalizationHisto; + private: virtual MDEventWorkspace *doClone() const { return new MDEventWorkspace(*this); diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.tcc b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.tcc index a47b7f94a3547e13d29e0ddc6e7a25f02b14f64b..bead61c930ea1c0d4afcdadde34ce9a17ef7e7de 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.tcc +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDEventWorkspace.tcc @@ -31,13 +31,19 @@ namespace Mantid { namespace DataObjects { //----------------------------------------------------------------------------------------------- -/** Default constructor +/** Constructor */ -TMDE(MDEventWorkspace)::MDEventWorkspace() + +TMDE(MDEventWorkspace)::MDEventWorkspace( + Mantid::API::MDNormalization preferredNormalization, + Mantid::API::MDNormalization preferredNormalizationHisto) : API::IMDEventWorkspace(), data(NULL), - m_BoxController(new BoxController(nd)), m_coordSystem(None) { + m_BoxController(new BoxController(nd)), + m_displayNormalization(preferredNormalization), + m_displayNormalizationHisto(preferredNormalizationHisto), + m_coordSystem(None) { // First box is at depth 0, and has this default boxController - data = new MDBox<MDE, nd>(m_BoxController.get(), 0); + data = new MDBox<MDE, nd>(m_BoxController.get(), 0); } //----------------------------------------------------------------------------------------------- @@ -45,7 +51,10 @@ TMDE(MDEventWorkspace)::MDEventWorkspace() */ TMDE(MDEventWorkspace)::MDEventWorkspace(const MDEventWorkspace<MDE, nd> &other) : IMDEventWorkspace(other), data(NULL), - m_BoxController(other.m_BoxController->clone()), m_coordSystem(other.m_coordSystem) { + m_BoxController(other.m_BoxController->clone()), + m_displayNormalization(other.m_displayNormalization), + m_displayNormalizationHisto(other.m_displayNormalizationHisto), + m_coordSystem(other.m_coordSystem) { const MDBox<MDE, nd> *mdbox = dynamic_cast<const MDBox<MDE, nd> *>(other.data); @@ -799,13 +808,43 @@ TMDE(void MDEventWorkspace)::setCoordinateSystem( m_coordSystem = coordSystem; } + +/** + Set the display normalization for any subsequently generated histoworkspaces. + @param preferredNormalization : Display normalization preference to pass on to generated histo workspaces. +*/ +TMDE(void MDEventWorkspace)::setDisplayNormalizationHisto( + const Mantid::API::MDNormalization preferredNormalizationHisto) { + m_displayNormalizationHisto = preferredNormalizationHisto; +} + +/** +Return the preferred normalization preference for subsequent histoworkspaces. +*/ +TMDE(MDNormalization MDEventWorkspace)::displayNormalizationHisto() const { + return m_displayNormalizationHisto; +} + + +/** + Set the display normalization + @param preferredNormalization : Display normalization preference. +*/ +TMDE(void MDEventWorkspace)::setDisplayNormalization( + const Mantid::API::MDNormalization preferredNormalization) { + m_displayNormalization = preferredNormalization; +} + + /** Return the preferred normalization to use for visualization. */ TMDE(MDNormalization MDEventWorkspace)::displayNormalization() const { - return VolumeNormalization; // volume normalization preferred for display purposes. + return m_displayNormalization ; } + + } // namespace DataObjects } // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDHistoWorkspace.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDHistoWorkspace.h index 8e6eaca21128413edfb3dda1b232c9a73f2ca8a3..fe7f85112132ec008f042285c305905c866bddec 100644 --- a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDHistoWorkspace.h +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/MDHistoWorkspace.h @@ -40,12 +40,16 @@ public: Mantid::Geometry::MDHistoDimension_sptr dimZ = Mantid::Geometry::MDHistoDimension_sptr(), Mantid::Geometry::MDHistoDimension_sptr dimT = - Mantid::Geometry::MDHistoDimension_sptr()); + Mantid::Geometry::MDHistoDimension_sptr(), + Mantid::API::MDNormalization displayNormalization + = Mantid::API::NoNormalization); MDHistoWorkspace( - std::vector<Mantid::Geometry::MDHistoDimension_sptr> &dimensions); + std::vector<Mantid::Geometry::MDHistoDimension_sptr> &dimensions, Mantid::API::MDNormalization displayNormalization + = Mantid::API::NoNormalization); MDHistoWorkspace( - std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions); + std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions, Mantid::API::MDNormalization displayNormalization + = Mantid::API::NoNormalization); virtual ~MDHistoWorkspace(); @@ -386,6 +390,11 @@ public: /// Preferred visual normalization method. virtual Mantid::API::MDNormalization displayNormalization() const; + /// Preferred visual normalization method. + virtual Mantid::API::MDNormalization displayNormalizationHisto() const; + + virtual void setDisplayNormalization(const Mantid::API::MDNormalization& preferredNormalization); + private: virtual MDHistoWorkspace *doClone() const { return new MDHistoWorkspace(*this); @@ -432,6 +441,9 @@ private: Kernel::SpecialCoordinateSystem m_coordSystem; + /// Display normalization to use + Mantid::API::MDNormalization m_displayNormalization; + protected: /// Protected copy constructor. May be used by childs for cloning. MDHistoWorkspace(const MDHistoWorkspace &other); diff --git a/Code/Mantid/Framework/DataObjects/src/MDBoxFlatTree.cpp b/Code/Mantid/Framework/DataObjects/src/MDBoxFlatTree.cpp index 19117d593b5817e345a0a7107f260db74161a485..93b3ee3710c6fe478142e490f5051a734bc2a6b3 100644 --- a/Code/Mantid/Framework/DataObjects/src/MDBoxFlatTree.cpp +++ b/Code/Mantid/Framework/DataObjects/src/MDBoxFlatTree.cpp @@ -749,6 +749,14 @@ void MDBoxFlatTree::saveWSGenericInfo(::NeXus::File *const file, file->writeData("coordinate_system", static_cast<uint32_t>(ws->getSpecialCoordinateSystem())); + // Write out the set display normalization + file->writeData("visual_normalization", + static_cast<uint32_t>(ws->displayNormalization())); + + // Write out the set display normalization carried for spawned histo workspaces. + file->writeData("visual_normalization_histo", + static_cast<uint32_t>(ws->displayNormalizationHisto())); + // Save the algorithm history under "process" ws->getHistory().saveNexus(file); diff --git a/Code/Mantid/Framework/DataObjects/src/MDEventFactory.cpp b/Code/Mantid/Framework/DataObjects/src/MDEventFactory.cpp index f6ec2184c67b6666a151c7b15cbdadf738a0d07e..ca317a01210dad8edc87bf29ee1abfdbedcb73e0 100644 --- a/Code/Mantid/Framework/DataObjects/src/MDEventFactory.cpp +++ b/Code/Mantid/Framework/DataObjects/src/MDEventFactory.cpp @@ -184,19 +184,23 @@ template DLLExport class MDBoxIterator<MDLeanEvent<9>, 9>; /** Create a MDEventWorkspace of the given type @param nd :: number of dimensions @param eventType :: string describing the event type (MDEvent or MDLeanEvent) +@param preferredNormalization: the preferred normalization for the event workspace +@param preferredNormalizationHisto: preferred normalization for histo workspaces which derive + from this event workspace @return shared pointer to the MDEventWorkspace created (as a IMDEventWorkspace). */ -API::IMDEventWorkspace_sptr -MDEventFactory::CreateMDWorkspace(size_t nd, const std::string &eventType) { - +API::IMDEventWorkspace_sptr MDEventFactory::CreateMDWorkspace( + size_t nd, const std::string &eventType, + const Mantid::API::MDNormalization& preferredNormalization, + const Mantid::API::MDNormalization& preferredNormalizationHisto) { if (nd > MAX_MD_DIMENSIONS_NUM) throw std::invalid_argument( " there are more dimensions requested then instantiated"); - - API::IMDEventWorkspace *pWs = (*(wsCreatorFP[nd]))(eventType); - + API::IMDEventWorkspace *pWs = (*(wsCreatorFP[nd]))( + eventType, preferredNormalization, preferredNormalizationHisto); return boost::shared_ptr<API::IMDEventWorkspace>(pWs); } + /** Create a MDBox or MDGridBoxof the given type @param nDimensions :: number of dimensions @param Type :: enum descibing the box (MDBox or MDGridBox) and the event @@ -259,32 +263,47 @@ std::vector<MDEventFactory::fpCreateMDWS> //-------------------------------------------------------------- MD Workspace // constructor wrapper -/** Template to create md workspace with specific number of dimentisons +/** Template to create md workspace with specific number of dimensions * @param eventType -- type of event (lean or full) to generate workspace for + * @param preferredNormalization: the preferred normalization for the event + * workspace + * @param preferredNormalizationHisto: the preferred normalization for a derived + * histo workspace */ template <size_t nd> -API::IMDEventWorkspace * -MDEventFactory::createMDWorkspaceND(const std::string &eventType) { +API::IMDEventWorkspace *MDEventFactory::createMDWorkspaceND( + const std::string &eventType, + const Mantid::API::MDNormalization& preferredNormalization, + const Mantid::API::MDNormalization& preferredNormalizationHisto) { if (eventType == "MDEvent") - return new MDEventWorkspace<MDEvent<nd>, nd>; + return new MDEventWorkspace<MDEvent<nd>, nd>(preferredNormalization, + preferredNormalizationHisto); else if (eventType == "MDLeanEvent") - return new MDEventWorkspace<MDLeanEvent<nd>, nd>; + return new MDEventWorkspace<MDLeanEvent<nd>, nd>( + preferredNormalization, preferredNormalizationHisto); else throw std::invalid_argument("Unknown event type " + eventType + " passed to CreateMDWorkspace."); } -/** Template to create md workspace with 0 number of dimentisons. As this is +/** Template to create md workspace w ith 0 number of dimentisons. As this is * wrong, just throws. Used as terminator and check for the wrong dimensions * number * @param eventType -- type of event (lean or full) to generate workspace for - * -does not actually used. + * @param preferredNormalization: the preferred normalization of the workspace + * @param preferredNormalizationHisto: the preferred normalization of the derived histo workspace */ template <> -API::IMDEventWorkspace * -MDEventFactory::createMDWorkspaceND<0>(const std::string &eventType) { +API::IMDEventWorkspace *MDEventFactory::createMDWorkspaceND<0>( + const std::string &eventType, + const Mantid::API::MDNormalization& preferredNormalization, + const Mantid::API::MDNormalization& preferredNormalizationHisto) { UNUSED_ARG(eventType); + UNUSED_ARG(preferredNormalization); + UNUSED_ARG(preferredNormalizationHisto); throw std::invalid_argument("Workspace can not have 0 dimensions"); } + //-------------------------------------------------------------- MD BOX // constructor wrapper /** Method to create any MDBox type with 0 number of dimensions. As it is wrong, diff --git a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspace.cpp b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspace.cpp index b1687145357598e2bc49e6c4c4822dcd663e0adc..b842deb0be1addd99c1f85e78e3c4b5ca07ef0f2 100644 --- a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspace.cpp +++ b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspace.cpp @@ -26,14 +26,17 @@ namespace DataObjects { * @param dimY :: Y dimension binning parameters * @param dimZ :: Z dimension binning parameters * @param dimT :: T (time) dimension binning parameters + * @param displayNormalization :: optional display normalization to use as the default. */ MDHistoWorkspace::MDHistoWorkspace(Mantid::Geometry::MDHistoDimension_sptr dimX, Mantid::Geometry::MDHistoDimension_sptr dimY, Mantid::Geometry::MDHistoDimension_sptr dimZ, - Mantid::Geometry::MDHistoDimension_sptr dimT) + Mantid::Geometry::MDHistoDimension_sptr dimT, + Mantid::API::MDNormalization displayNormalization + ) : IMDHistoWorkspace(), numDimensions(0), m_nEventsContributed(std::numeric_limits<uint64_t>::quiet_NaN()), - m_coordSystem(None) { + m_coordSystem(None), m_displayNormalization(displayNormalization) { std::vector<Mantid::Geometry::MDHistoDimension_sptr> dimensions; if (dimX) dimensions.push_back(dimX); @@ -49,24 +52,28 @@ MDHistoWorkspace::MDHistoWorkspace(Mantid::Geometry::MDHistoDimension_sptr dimX, //---------------------------------------------------------------------------------------------- /** Constructor given a vector of dimensions * @param dimensions :: vector of MDHistoDimension; no limit to how many. + * @param displayNormalization :: optional display normalization to use as the default. */ MDHistoWorkspace::MDHistoWorkspace( - std::vector<Mantid::Geometry::MDHistoDimension_sptr> &dimensions) + std::vector<Mantid::Geometry::MDHistoDimension_sptr> &dimensions, + Mantid::API::MDNormalization displayNormalization) : IMDHistoWorkspace(), numDimensions(0), m_numEvents(NULL), m_nEventsContributed(std::numeric_limits<uint64_t>::quiet_NaN()), - m_coordSystem(None) { + m_coordSystem(None), m_displayNormalization(displayNormalization) { this->init(dimensions); } //---------------------------------------------------------------------------------------------- /** Constructor given a vector of dimensions * @param dimensions :: vector of MDHistoDimension; no limit to how many. + * @param displayNormalization :: optional display normalization to use as the default. */ MDHistoWorkspace::MDHistoWorkspace( - std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions) + std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions, + Mantid::API::MDNormalization displayNormalization) : IMDHistoWorkspace(), numDimensions(0), m_numEvents(NULL), m_nEventsContributed(std::numeric_limits<uint64_t>::quiet_NaN()), - m_coordSystem(None) { + m_coordSystem(None), m_displayNormalization(displayNormalization) { this->init(dimensions); } @@ -86,6 +93,7 @@ MDHistoWorkspace::MDHistoWorkspace(const MDHistoWorkspace &other) m_masks = new bool[m_length]; m_nEventsContributed = other.m_nEventsContributed; this->setCoordinateSystem(other.getSpecialCoordinateSystem()); + m_displayNormalization = other.displayNormalization(); // Now copy all the data for (size_t i = 0; i < m_length; ++i) { m_signals[i] = other.m_signals[i]; @@ -1229,7 +1237,18 @@ size_t MDHistoWorkspace::sizeOfElement() { Preferred normalization to use for visual purposes. */ MDNormalization MDHistoWorkspace::displayNormalization() const { - return NumEventsNormalization; // Normalize by the number of events. + return m_displayNormalization;// Normalize by the number of events. +} + +/** +Preferred normalization to use for visual purposes. +*/ +MDNormalization MDHistoWorkspace::displayNormalizationHisto() const { + return displayNormalization();// Normalize by the number of events. +} + +void MDHistoWorkspace::setDisplayNormalization(const Mantid::API::MDNormalization& preferredNormalization) { + m_displayNormalization = preferredNormalization; } } // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp index f18a82bc58547428832e5c940dd95d5af83acb72..d1c855d8fdbdaf3f63c97a1abe5242013cdcbe56 100644 --- a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp +++ b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp @@ -12,6 +12,50 @@ using namespace Mantid::Kernel; using namespace Mantid::API; using Mantid::Geometry::IMDDimension_const_sptr; + +namespace { + //To get the rounded difference, we need to take into account precision issues which arise when + // the bin centres match +Mantid::coord_t getDExact(Mantid::coord_t location, Mantid::coord_t origin, Mantid::coord_t binWidth) { + auto dExact = (location - origin) / binWidth; + const Mantid::coord_t tolerance = Mantid::coord_t(1e-5); + + // Expl. of the steps below + // -1 -0.5 0 0.5 1 where integer values are bin boundaries and half-values + // | | | | | are bin centres + // | + // Location + // Goal: Find distance to closest bin centre: + // 1. Get the predecimal value of the location: here 0 + // 2. Add and subtract 0.5 to find two possible centres: here -0.5 adn + 0.5 + // 3. Find the centre which minimizes the difference to the location + // 4. Keep the difference (distance) that was calculation in the step above + + // Get the two centre indices which are the closest to dExact. + const auto centre1 = static_cast<Mantid::coord_t>(size_t(dExact)) + 0.5; + const auto centre2 = static_cast<Mantid::coord_t>(size_t(dExact)) - 0.5; + + // Calculate the distance of the location to the centres + const auto diff1 = static_cast<Mantid::coord_t>(fabs(centre1 - dExact)); + const auto diff2 = static_cast<Mantid::coord_t>(fabs(centre2 - dExact)); + + const auto difference = diff1 < diff2 ? diff1 : diff2; + + // If the differnce is within the tolerance, ie the location is essentially on the centre, then + // we want to be on the left of that centre. The correct index for when we are on the centre, + // is the lower next integer value. + if (difference < tolerance) { + if (difference == 0.0f) { + dExact -= tolerance; // When we have an exact hit in the centre, give it a nudge to the lower bin boundary + } else { + dExact -= 2*difference; // Need to subtract twice the differnce, in order to be guaranteed below the centre + } + } + return dExact; +} +} + + namespace Mantid { namespace DataObjects { @@ -215,11 +259,10 @@ void MDHistoWorkspaceIterator::jumpTo(size_t index) { */ Mantid::coord_t MDHistoWorkspaceIterator::jumpToNearest(const VMD& fromLocation) { - std::vector<size_t> indexes(m_nd); coord_t sqDiff = 0; for(size_t d = 0; d < m_nd; ++d) { - coord_t dExact = (fromLocation[d] - m_origin[d]) / m_binWidth[d]; // Index position in this space. + coord_t dExact = getDExact(fromLocation[d], m_origin[d], m_binWidth[d]); size_t dRound = size_t(dExact + 0.5); // Round to nearest bin edge. sqDiff += (dExact - coord_t(dRound)) * (dExact - coord_t(dRound)) * m_binWidth[d] * m_binWidth[d]; indexes[d] = dRound; diff --git a/Code/Mantid/Framework/DataObjects/test/MDEventFactoryTest.h b/Code/Mantid/Framework/DataObjects/test/MDEventFactoryTest.h index ea83166110460b36e1e9ec8260de978cdee75274..7d8405c8d77067357d385daec8ff90ccda3a7870 100644 --- a/Code/Mantid/Framework/DataObjects/test/MDEventFactoryTest.h +++ b/Code/Mantid/Framework/DataObjects/test/MDEventFactoryTest.h @@ -23,10 +23,16 @@ public: IMDEventWorkspace_sptr ew; ew = MDEventFactory::CreateMDWorkspace(4, "MDLeanEvent"); TS_ASSERT_EQUALS( ew->getNumDims(), 4); + TSM_ASSERT_EQUALS("Should have volume normalization as a default", ew->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should have volume normalization as a default", ew->displayNormalizationHisto(), Mantid::API::VolumeNormalization); size_t n = 9; - ew = MDEventFactory::CreateMDWorkspace(n); + auto eventNormalization = Mantid::API::NoNormalization; + auto histoNormalization = Mantid::API::NumEventsNormalization; + ew = MDEventFactory::CreateMDWorkspace(n, "MDLeanEvent", eventNormalization, histoNormalization); TS_ASSERT_EQUALS( ew->getNumDims(), n); + TSM_ASSERT_EQUALS("Should have no normalization set.", ew->displayNormalization(), eventNormalization); + TSM_ASSERT_EQUALS("Should have number of events set.", ew->displayNormalizationHisto(), histoNormalization); TS_ASSERT_THROWS( ew = MDEventFactory::CreateMDWorkspace(0), std::invalid_argument); } diff --git a/Code/Mantid/Framework/DataObjects/test/MDEventWorkspaceTest.h b/Code/Mantid/Framework/DataObjects/test/MDEventWorkspaceTest.h index d048cfaa95f72347ae54fa7835c6226b44060ec7..be684b1242a28911b7c9df825b04792ab9db21ed 100644 --- a/Code/Mantid/Framework/DataObjects/test/MDEventWorkspaceTest.h +++ b/Code/Mantid/Framework/DataObjects/test/MDEventWorkspaceTest.h @@ -521,6 +521,37 @@ public: } } + void test_that_sets_default_normalization_flags_to_volume_normalization() { + // Arrange + Act + MDEventWorkspace3Lean::sptr ew = MDEventsTestHelper::makeMDEW<3>(4, 0.0, 7.0, 3); + // Assert + TSM_ASSERT_EQUALS("Should default to volume normalization", ew->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should default to volume normalization", ew->displayNormalizationHisto(), Mantid::API::VolumeNormalization); + } + + void test_can_set_normalization_in_constructor() { + // Arrange + auto eventSetting = Mantid::API::NoNormalization; + auto histoSetting = Mantid::API::NumEventsNormalization; + // Act + boost::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDLeanEvent<3>, 3>> ew(new Mantid::DataObjects::MDEventWorkspace<MDLeanEvent<3>, 3>(eventSetting, histoSetting)); + // Assert + TSM_ASSERT_EQUALS("Should be set to nonormalization", ew->displayNormalization(), eventSetting); + TSM_ASSERT_EQUALS("Should be set to number of events normalizationnormalization", ew->displayNormalizationHisto(), histoSetting); + } + + void test_that_sets_normalization_correctly() { + // Arrange + MDEventWorkspace3Lean::sptr ew = MDEventsTestHelper::makeMDEW<3>(4, 0.0, 7.0, 3); + auto eventSetting = Mantid::API::NoNormalization; + auto histoSetting = Mantid::API::NumEventsNormalization; + // Act + ew->setDisplayNormalization(eventSetting); + ew->setDisplayNormalizationHisto(histoSetting); + // Assert + TSM_ASSERT_EQUALS("Should be set to nonormalization", ew->displayNormalization(), eventSetting); + TSM_ASSERT_EQUALS("Should be set to number of events normalizationnormalization", ew->displayNormalizationHisto(), histoSetting); + } }; diff --git a/Code/Mantid/Framework/DataObjects/test/MDHistoWorkspaceTest.h b/Code/Mantid/Framework/DataObjects/test/MDHistoWorkspaceTest.h index 32df9050aac51bd29d85c8a4959d339d2f2ea955..00aa25545561aefefcc8f21600791d130fbd4e9c 100644 --- a/Code/Mantid/Framework/DataObjects/test/MDHistoWorkspaceTest.h +++ b/Code/Mantid/Framework/DataObjects/test/MDHistoWorkspaceTest.h @@ -28,19 +28,16 @@ using namespace Mantid::API; using namespace Mantid::Kernel; using namespace Mantid; -class MDHistoWorkspaceTest : public CxxTest::TestSuite -{ +class MDHistoWorkspaceTest : public CxxTest::TestSuite { private: - /// Helper function to return the number of masked bins in a workspace. TODO: move helper into test helpers - size_t getNumberMasked(Mantid::API::IMDWorkspace_sptr ws) - { - Mantid::API::IMDIterator* it = ws->createIterator(NULL); + /// Helper function to return the number of masked bins in a workspace. TODO: + /// move helper into test helpers + size_t getNumberMasked(Mantid::API::IMDWorkspace_sptr ws) { + Mantid::API::IMDIterator *it = ws->createIterator(NULL); size_t numberMasked = 0; size_t counter = 0; - for(;counter < it->getDataSize(); ++counter) - { - if(it->getIsMasked()) - { + for (; counter < it->getDataSize(); ++counter) { + if (it->getIsMasked()) { ++numberMasked; } it->next(1); @@ -49,42 +46,38 @@ private: return numberMasked; } /// Helper method returns the size of an element in the MDHistoWorkspace - size_t sizeOfElement() - { - return (sizeof(double)*3 + sizeof(bool)); - } + size_t sizeOfElement() { return (sizeof(double) * 3 + sizeof(bool)); } + public: // This pair of boilerplate methods prevent the suite being created statically // This means the constructor isn't called when running other tests - static MDHistoWorkspaceTest *createSuite() { return new MDHistoWorkspaceTest(); } - static void destroySuite( MDHistoWorkspaceTest *suite ) { delete suite; } + static MDHistoWorkspaceTest *createSuite() { + return new MDHistoWorkspaceTest(); + } + static void destroySuite(MDHistoWorkspaceTest *suite) { delete suite; } MDHistoWorkspace_sptr two; MDHistoWorkspace_sptr three; /** Create some fake workspace, 5x5, with 2.0 and 3.0 each */ - MDHistoWorkspaceTest() - { + MDHistoWorkspaceTest() { two = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0); three = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0); } /** Check that a workspace has the right signal/error*/ - void checkWorkspace(MDHistoWorkspace_sptr ws, double expectedSignal, double expectedErrorSquared, - double expectedNumEvents=1.0) - { - for (size_t i=0; i < ws->getNPoints(); i++) - { - TS_ASSERT_DELTA( ws->getSignalAt(i), expectedSignal, 1e-5 ); - TS_ASSERT_DELTA( ws->getErrorAt(i), std::sqrt(expectedErrorSquared), 1e-5 ); - TS_ASSERT_DELTA( ws->getNumEventsAt(i), expectedNumEvents, 1e-5 ); + void checkWorkspace(MDHistoWorkspace_sptr ws, double expectedSignal, + double expectedErrorSquared, + double expectedNumEvents = 1.0) { + for (size_t i = 0; i < ws->getNPoints(); i++) { + TS_ASSERT_DELTA(ws->getSignalAt(i), expectedSignal, 1e-5); + TS_ASSERT_DELTA(ws->getErrorAt(i), std::sqrt(expectedErrorSquared), 1e-5); + TS_ASSERT_DELTA(ws->getNumEventsAt(i), expectedNumEvents, 1e-5); } } - //-------------------------------------------------------------------------------------- - void test_constructor() - { + void test_constructor() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 5)); MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -10, 10, 5)); @@ -92,119 +85,125 @@ public: MDHistoWorkspace ws(dimX, dimY, dimZ, dimT); - TS_ASSERT_EQUALS( ws.getNumDims(), 4); - TS_ASSERT_EQUALS( ws.getNPoints(), 5*5*5*5); - TS_ASSERT_EQUALS( ws.getMemorySize(), 5*5*5*5 * sizeOfElement()); - TS_ASSERT_EQUALS( ws.getXDimension(), dimX); - TS_ASSERT_EQUALS( ws.getYDimension(), dimY); - TS_ASSERT_EQUALS( ws.getZDimension(), dimZ); - TS_ASSERT_EQUALS( ws.getTDimension(), dimT); + TS_ASSERT_EQUALS(ws.getNumDims(), 4); + TS_ASSERT_EQUALS(ws.getNPoints(), 5 * 5 * 5 * 5); + TS_ASSERT_EQUALS(ws.getMemorySize(), 5 * 5 * 5 * 5 * sizeOfElement()); + TS_ASSERT_EQUALS(ws.getXDimension(), dimX); + TS_ASSERT_EQUALS(ws.getYDimension(), dimY); + TS_ASSERT_EQUALS(ws.getZDimension(), dimZ); + TS_ASSERT_EQUALS(ws.getTDimension(), dimT); // The values are cleared at the start - for (size_t i=0; i < ws.getNPoints(); i++) - { - TS_ASSERT( boost::math::isnan( ws.getSignalAt(i) )); - TS_ASSERT( boost::math::isnan( ws.getErrorAt(i) )); - TS_ASSERT( boost::math::isnan( ws.getSignalNormalizedAt(i) )); - TS_ASSERT( boost::math::isnan( ws.getErrorNormalizedAt(i) )); - TS_ASSERT( !ws.getIsMaskedAt(i)); + for (size_t i = 0; i < ws.getNPoints(); i++) { + TS_ASSERT(boost::math::isnan(ws.getSignalAt(i))); + TS_ASSERT(boost::math::isnan(ws.getErrorAt(i))); + TS_ASSERT(boost::math::isnan(ws.getSignalNormalizedAt(i))); + TS_ASSERT(boost::math::isnan(ws.getErrorNormalizedAt(i))); + TS_ASSERT(!ws.getIsMaskedAt(i)); } // Setting and getting - ws.setSignalAt(5,2.3456); - TS_ASSERT_DELTA( ws.getSignalAt(5), 2.3456, 1e-5); - TS_ASSERT_DELTA( ws.getSignalNormalizedAt(5), 2.3456 / 256.0, 1e-5); // Cell volume is 256 + ws.setSignalAt(5, 2.3456); + TS_ASSERT_DELTA(ws.getSignalAt(5), 2.3456, 1e-5); + TS_ASSERT_DELTA(ws.getSignalNormalizedAt(5), 2.3456 / 256.0, + 1e-5); // Cell volume is 256 - ws.setErrorSquaredAt(5,1.234); - TS_ASSERT_DELTA( ws.getErrorAt(5), sqrt(1.234), 1e-5); - TS_ASSERT_DELTA( ws.getErrorNormalizedAt(5), sqrt(1.234) / 256.0, 1e-5); // Cell volume is 256 + ws.setErrorSquaredAt(5, 1.234); + TS_ASSERT_DELTA(ws.getErrorAt(5), sqrt(1.234), 1e-5); + TS_ASSERT_DELTA(ws.getErrorNormalizedAt(5), sqrt(1.234) / 256.0, + 1e-5); // Cell volume is 256 std::vector<signal_t> data = ws.getSignalDataVector(); - TS_ASSERT_EQUALS(data.size(), 5*5*5*5); - TS_ASSERT_DELTA( data[5], 2.3456, 1e-5); + TS_ASSERT_EQUALS(data.size(), 5 * 5 * 5 * 5); + TS_ASSERT_DELTA(data[5], 2.3456, 1e-5); // Set a different value at every point - for (size_t i=0; i < ws.getNPoints(); ++i) - { - ws.setSignalAt(i, (signal_t) i); - ws.setErrorSquaredAt(i, (signal_t) i); + for (size_t i = 0; i < ws.getNPoints(); ++i) { + ws.setSignalAt(i, (signal_t)i); + ws.setErrorSquaredAt(i, (signal_t)i); } // Test the 4 overloads of each method. Phew! - TS_ASSERT_DELTA( ws.getSignalAt(1), 1.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalAt(1,2), 1.0+2*5.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalAt(1,2,3), 1.0+2*5.0+3*25.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalAt(1,2,3,4), 1.0+2*5.0+3*25.0+4*125.0, 1e-4); - TS_ASSERT_DELTA( ws.getErrorAt(1), sqrt(1.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorAt(1,2), sqrt(1.0+2*5.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorAt(1,2,3), sqrt(1.0+2*5.0+3*25.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorAt(1,2,3,4), sqrt(1.0+2*5.0+3*25.0+4*125.0), 1e-4); - TS_ASSERT_DELTA( ws.getSignalNormalizedAt(1)*256.0, 1.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalNormalizedAt(1,2)*256.0, 1.0+2*5.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalNormalizedAt(1,2,3)*256.0, 1.0+2*5.0+3*25.0, 1e-4); - TS_ASSERT_DELTA( ws.getSignalNormalizedAt(1,2,3,4)*256.0, 1.0+2*5.0+3*25.0+4*125.0, 1e-4); - TS_ASSERT_DELTA( ws.getErrorNormalizedAt(1)*256.0, sqrt(1.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorNormalizedAt(1,2)*256.0, sqrt(1.0+2*5.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorNormalizedAt(1,2,3)*256.0, sqrt(1.0+2*5.0+3*25.0), 1e-4); - TS_ASSERT_DELTA( ws.getErrorNormalizedAt(1,2,3,4)*256.0, sqrt(1.0+2*5.0+3*25.0+4*125.0), 1e-4); + TS_ASSERT_DELTA(ws.getSignalAt(1), 1.0, 1e-4); + TS_ASSERT_DELTA(ws.getSignalAt(1, 2), 1.0 + 2 * 5.0, 1e-4); + TS_ASSERT_DELTA(ws.getSignalAt(1, 2, 3), 1.0 + 2 * 5.0 + 3 * 25.0, 1e-4); + TS_ASSERT_DELTA(ws.getSignalAt(1, 2, 3, 4), + 1.0 + 2 * 5.0 + 3 * 25.0 + 4 * 125.0, 1e-4); + TS_ASSERT_DELTA(ws.getErrorAt(1), sqrt(1.0), 1e-4); + TS_ASSERT_DELTA(ws.getErrorAt(1, 2), sqrt(1.0 + 2 * 5.0), 1e-4); + TS_ASSERT_DELTA(ws.getErrorAt(1, 2, 3), sqrt(1.0 + 2 * 5.0 + 3 * 25.0), + 1e-4); + TS_ASSERT_DELTA(ws.getErrorAt(1, 2, 3, 4), + sqrt(1.0 + 2 * 5.0 + 3 * 25.0 + 4 * 125.0), 1e-4); + TS_ASSERT_DELTA(ws.getSignalNormalizedAt(1) * 256.0, 1.0, 1e-4); + TS_ASSERT_DELTA(ws.getSignalNormalizedAt(1, 2) * 256.0, 1.0 + 2 * 5.0, + 1e-4); + TS_ASSERT_DELTA(ws.getSignalNormalizedAt(1, 2, 3) * 256.0, + 1.0 + 2 * 5.0 + 3 * 25.0, 1e-4); + TS_ASSERT_DELTA(ws.getSignalNormalizedAt(1, 2, 3, 4) * 256.0, + 1.0 + 2 * 5.0 + 3 * 25.0 + 4 * 125.0, 1e-4); + TS_ASSERT_DELTA(ws.getErrorNormalizedAt(1) * 256.0, sqrt(1.0), 1e-4); + TS_ASSERT_DELTA(ws.getErrorNormalizedAt(1, 2) * 256.0, sqrt(1.0 + 2 * 5.0), + 1e-4); + TS_ASSERT_DELTA(ws.getErrorNormalizedAt(1, 2, 3) * 256.0, + sqrt(1.0 + 2 * 5.0 + 3 * 25.0), 1e-4); + TS_ASSERT_DELTA(ws.getErrorNormalizedAt(1, 2, 3, 4) * 256.0, + sqrt(1.0 + 2 * 5.0 + 3 * 25.0 + 4 * 125.0), 1e-4); } - //--------------------------------------------------------------------------------------------------- /** Create a dense histogram with only 2 dimensions */ - void test_constructor_fewerDimensions() - { + void test_constructor_fewerDimensions() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 5)); MDHistoWorkspace ws(dimX, dimY); - TS_ASSERT_EQUALS( ws.getNumDims(), 2); - TS_ASSERT_EQUALS( ws.getNPoints(), 5*5); - TS_ASSERT_EQUALS( ws.getMemorySize(), 5*5 * sizeOfElement()); - TS_ASSERT_EQUALS( ws.getXDimension(), dimX); - TS_ASSERT_EQUALS( ws.getYDimension(), dimY); - TS_ASSERT_THROWS_ANYTHING( ws.getZDimension()); - TS_ASSERT_THROWS_ANYTHING( ws.getTDimension()); + TS_ASSERT_EQUALS(ws.getNumDims(), 2); + TS_ASSERT_EQUALS(ws.getNPoints(), 5 * 5); + TS_ASSERT_EQUALS(ws.getMemorySize(), 5 * 5 * sizeOfElement()); + TS_ASSERT_EQUALS(ws.getXDimension(), dimX); + TS_ASSERT_EQUALS(ws.getYDimension(), dimY); + TS_ASSERT_THROWS_ANYTHING(ws.getZDimension()); + TS_ASSERT_THROWS_ANYTHING(ws.getTDimension()); // Setting and getting - ws.setSignalAt(5,2.3456); - TS_ASSERT_DELTA( ws.getSignalAt(5), 2.3456, 1e-5); + ws.setSignalAt(5, 2.3456); + TS_ASSERT_DELTA(ws.getSignalAt(5), 2.3456, 1e-5); - ws.setErrorSquaredAt(5,1.234); - TS_ASSERT_DELTA( ws.getErrorAt(5), sqrt(1.234), 1e-5); + ws.setErrorSquaredAt(5, 1.234); + TS_ASSERT_DELTA(ws.getErrorAt(5), sqrt(1.234), 1e-5); std::vector<signal_t> data = ws.getSignalDataVector(); - TS_ASSERT_EQUALS(data.size(), 5*5); - TS_ASSERT_DELTA( data[5], 2.3456, 1e-5); + TS_ASSERT_EQUALS(data.size(), 5 * 5); + TS_ASSERT_DELTA(data[5], 2.3456, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Create a dense histogram with 7 dimensions */ - void test_constructor_MoreThanFourDimensions() - { + void test_constructor_MoreThanFourDimensions() { std::vector<MDHistoDimension_sptr> dimensions; - for (size_t i=0; i<7; i++) - { - dimensions.push_back(MDHistoDimension_sptr(new MDHistoDimension("Dim", "Dim", "m", -10, 10, 3))); + for (size_t i = 0; i < 7; i++) { + dimensions.push_back(MDHistoDimension_sptr( + new MDHistoDimension("Dim", "Dim", "m", -10, 10, 3))); } MDHistoWorkspace ws(dimensions); - TS_ASSERT_EQUALS( ws.getNumDims(), 7); - TS_ASSERT_EQUALS( ws.getNPoints(), 3*3*3*3*3*3*3); - TS_ASSERT_EQUALS( ws.getMemorySize(), ws.getNPoints() * sizeOfElement()); + TS_ASSERT_EQUALS(ws.getNumDims(), 7); + TS_ASSERT_EQUALS(ws.getNPoints(), 3 * 3 * 3 * 3 * 3 * 3 * 3); + TS_ASSERT_EQUALS(ws.getMemorySize(), ws.getNPoints() * sizeOfElement()); // Setting and getting - ws.setSignalAt(5,2.3456); - TS_ASSERT_DELTA( ws.getSignalAt(5), 2.3456, 1e-5); + ws.setSignalAt(5, 2.3456); + TS_ASSERT_DELTA(ws.getSignalAt(5), 2.3456, 1e-5); - ws.setErrorSquaredAt(5,1.234); - TS_ASSERT_DELTA( ws.getErrorAt(5), sqrt(1.234), 1e-5); + ws.setErrorSquaredAt(5, 1.234); + TS_ASSERT_DELTA(ws.getErrorAt(5), sqrt(1.234), 1e-5); std::vector<signal_t> data = ws.getSignalDataVector(); - TS_ASSERT_EQUALS(data.size(), 3*3*3*3*3*3*3); - TS_ASSERT_DELTA( data[5], 2.3456, 1e-5); + TS_ASSERT_EQUALS(data.size(), 3 * 3 * 3 * 3 * 3 * 3 * 3); + TS_ASSERT_DELTA(data[5], 2.3456, 1e-5); } class TestableMDHistoWorkspace : public MDHistoWorkspace { @@ -214,227 +213,211 @@ public: }; //-------------------------------------------------------------------------------------- - void test_copy_constructor() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.234); - a->addExperimentInfo( ExperimentInfo_sptr(new ExperimentInfo()) ); - for (size_t i=0; i<a->getNPoints(); i++) + void test_copy_constructor() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.234); + a->addExperimentInfo(ExperimentInfo_sptr(new ExperimentInfo())); + for (size_t i = 0; i < a->getNPoints(); i++) a->setNumEventsAt(i, 123.); - MDHistoWorkspace_sptr b( new TestableMDHistoWorkspace(*a)); - TS_ASSERT_EQUALS( b->getNumDims(), a->getNumDims() ); - TS_ASSERT_EQUALS( b->getNPoints(), a->getNPoints() ); - TS_ASSERT_EQUALS( b->getNumExperimentInfo(), a->getNumExperimentInfo() ); + MDHistoWorkspace_sptr b(new TestableMDHistoWorkspace(*a)); + TS_ASSERT_EQUALS(b->getNumDims(), a->getNumDims()); + TS_ASSERT_EQUALS(b->getNPoints(), a->getNPoints()); + TS_ASSERT_EQUALS(b->getNumExperimentInfo(), a->getNumExperimentInfo()); + TS_ASSERT_EQUALS(b->displayNormalization(), a->displayNormalization()); checkWorkspace(b, 1.23, 3.234, 123.); } //-------------------------------------------------------------------------------------- - void test_array_operator() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.234); - TS_ASSERT_DELTA( (*a)[0], 1.23, 1e-5 ); - TS_ASSERT_THROWS_ANYTHING( (*a)[25] ); - TS_ASSERT_THROWS_ANYTHING( (*a)[-1] ); + void test_array_operator() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.234); + TS_ASSERT_DELTA((*a)[0], 1.23, 1e-5); + TS_ASSERT_THROWS_ANYTHING((*a)[25]); + TS_ASSERT_THROWS_ANYTHING((*a)[-1]); } //--------------------------------------------------------------------------------------------------- - void test_getVertexesArray_1D() - { + void test_getVertexesArray_1D() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoWorkspace ws(dimX); size_t numVertices; - coord_t *v1 = ws.getVertexesArray(0,numVertices); - TS_ASSERT_EQUALS( numVertices, 2 ); - TS_ASSERT_DELTA( v1[0], -10.0, 1e-5); - TS_ASSERT_DELTA( v1[1], -6.0, 1e-5); - delete [] v1; - - coord_t *v2 = ws.getVertexesArray(4,numVertices); - TS_ASSERT_DELTA( v2[0], 6.0, 1e-5); - TS_ASSERT_DELTA( v2[1], 10.0, 1e-5); - delete [] v2; + coord_t *v1 = ws.getVertexesArray(0, numVertices); + TS_ASSERT_EQUALS(numVertices, 2); + TS_ASSERT_DELTA(v1[0], -10.0, 1e-5); + TS_ASSERT_DELTA(v1[1], -6.0, 1e-5); + delete[] v1; + + coord_t *v2 = ws.getVertexesArray(4, numVertices); + TS_ASSERT_DELTA(v2[0], 6.0, 1e-5); + TS_ASSERT_DELTA(v2[1], 10.0, 1e-5); + delete[] v2; } //--------------------------------------------------------------------------------------------------- - void test_getVertexesArray_2D() - { + void test_getVertexesArray_2D() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 5)); MDHistoWorkspace ws(dimX, dimY); size_t numVertices, i; - boost::scoped_array<coord_t> v1(ws.getVertexesArray(0,numVertices)); - TS_ASSERT_EQUALS( numVertices, 4 ); - i = 0*2; - TS_ASSERT_DELTA( v1[i+0], -10.0, 1e-5); - TS_ASSERT_DELTA( v1[i+1], -10.0, 1e-5); - i = 3*2; - TS_ASSERT_DELTA( v1[i+0], -6.0, 1e-5); - TS_ASSERT_DELTA( v1[i+1], -6.0, 1e-5); + boost::scoped_array<coord_t> v1(ws.getVertexesArray(0, numVertices)); + TS_ASSERT_EQUALS(numVertices, 4); + i = 0 * 2; + TS_ASSERT_DELTA(v1[i + 0], -10.0, 1e-5); + TS_ASSERT_DELTA(v1[i + 1], -10.0, 1e-5); + i = 3 * 2; + TS_ASSERT_DELTA(v1[i + 0], -6.0, 1e-5); + TS_ASSERT_DELTA(v1[i + 1], -6.0, 1e-5); // The opposite corner - boost::scoped_array<coord_t> v2(ws.getVertexesArray(24,numVertices)); - i = 0*2; - TS_ASSERT_DELTA( v2[i+0], 6.0, 1e-5); - TS_ASSERT_DELTA( v2[i+1], 6.0, 1e-5); - i = 3*2; - TS_ASSERT_DELTA( v2[i+0], 10.0, 1e-5); - TS_ASSERT_DELTA( v2[i+1], 10.0, 1e-5); + boost::scoped_array<coord_t> v2(ws.getVertexesArray(24, numVertices)); + i = 0 * 2; + TS_ASSERT_DELTA(v2[i + 0], 6.0, 1e-5); + TS_ASSERT_DELTA(v2[i + 1], 6.0, 1e-5); + i = 3 * 2; + TS_ASSERT_DELTA(v2[i + 0], 10.0, 1e-5); + TS_ASSERT_DELTA(v2[i + 1], 10.0, 1e-5); } //--------------------------------------------------------------------------------------------------- - void test_getVertexesArray_3D() - { + void test_getVertexesArray_3D() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -9, 10, 5)); MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -8, 10, 5)); MDHistoWorkspace ws(dimX, dimY, dimZ); size_t numVertices, i; - boost::scoped_array<coord_t> v(ws.getVertexesArray(0,numVertices)); - TS_ASSERT_EQUALS( numVertices, 8 ); + boost::scoped_array<coord_t> v(ws.getVertexesArray(0, numVertices)); + TS_ASSERT_EQUALS(numVertices, 8); i = 0; - TS_ASSERT_DELTA( v[i+0], -10.0, 1e-5); - TS_ASSERT_DELTA( v[i+1], -9.0, 1e-5); - TS_ASSERT_DELTA( v[i+2], -8.0, 1e-5); + TS_ASSERT_DELTA(v[i + 0], -10.0, 1e-5); + TS_ASSERT_DELTA(v[i + 1], -9.0, 1e-5); + TS_ASSERT_DELTA(v[i + 2], -8.0, 1e-5); } //--------------------------------------------------------------------------------------------------- - void test_getCenter_3D() - { - MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 20)); + void test_getCenter_3D() { + MDHistoDimension_sptr dimX( + new MDHistoDimension("X", "x", "m", -10, 10, 20)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -9, 10, 19)); MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -8, 10, 18)); MDHistoWorkspace ws(dimX, dimY, dimZ); VMD v = ws.getCenter(0); - TS_ASSERT_DELTA( v[0], -9.5, 1e-5); - TS_ASSERT_DELTA( v[1], -8.5, 1e-5); - TS_ASSERT_DELTA( v[2], -7.5, 1e-5); + TS_ASSERT_DELTA(v[0], -9.5, 1e-5); + TS_ASSERT_DELTA(v[1], -8.5, 1e-5); + TS_ASSERT_DELTA(v[2], -7.5, 1e-5); } - //--------------------------------------------------------------------------------------------------- /** Test for a possible seg-fault if nx != ny etc. */ - void test_uneven_numbers_of_bins() - { + void test_uneven_numbers_of_bins() { MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); - MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 10)); - MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -10, 10, 20)); - MDHistoDimension_sptr dimT(new MDHistoDimension("T", "t", "m", -10, 10, 10)); + MDHistoDimension_sptr dimY( + new MDHistoDimension("Y", "y", "m", -10, 10, 10)); + MDHistoDimension_sptr dimZ( + new MDHistoDimension("Z", "z", "m", -10, 10, 20)); + MDHistoDimension_sptr dimT( + new MDHistoDimension("T", "t", "m", -10, 10, 10)); MDHistoWorkspace ws(dimX, dimY, dimZ, dimT); - TS_ASSERT_EQUALS( ws.getNumDims(), 4); - TS_ASSERT_EQUALS( ws.getNPoints(), 5*10*20*10); - TS_ASSERT_EQUALS( ws.getMemorySize(), 5*10*20*10 * sizeOfElement()); + TS_ASSERT_EQUALS(ws.getNumDims(), 4); + TS_ASSERT_EQUALS(ws.getNPoints(), 5 * 10 * 20 * 10); + TS_ASSERT_EQUALS(ws.getMemorySize(), 5 * 10 * 20 * 10 * sizeOfElement()); // Setting and getting - size_t index = 5*10*20*10-1; // The last point - ws.setSignalAt(index,2.3456); - TS_ASSERT_DELTA( ws.getSignalAt(index), 2.3456, 1e-5); + size_t index = 5 * 10 * 20 * 10 - 1; // The last point + ws.setSignalAt(index, 2.3456); + TS_ASSERT_DELTA(ws.getSignalAt(index), 2.3456, 1e-5); // Getter with all indices - TS_ASSERT_DELTA( ws.getSignalAt(4,9,19,9), 2.3456, 1e-5); + TS_ASSERT_DELTA(ws.getSignalAt(4, 9, 19, 9), 2.3456, 1e-5); // check shapes - TS_ASSERT_EQUALS( 5,ws.getDimension(0)->getNBins()); - TS_ASSERT_EQUALS(10,ws.getDimension(1)->getNBins()); - TS_ASSERT_EQUALS(20,ws.getDimension(2)->getNBins()); - TS_ASSERT_EQUALS(10,ws.getDimension(3)->getNBins()); + TS_ASSERT_EQUALS(5, ws.getDimension(0)->getNBins()); + TS_ASSERT_EQUALS(10, ws.getDimension(1)->getNBins()); + TS_ASSERT_EQUALS(20, ws.getDimension(2)->getNBins()); + TS_ASSERT_EQUALS(10, ws.getDimension(3)->getNBins()); auto *binWidth = ws.getBinWidths(); - TS_ASSERT_DELTA(20./5,*(binWidth+0),1.e-5); - TS_ASSERT_DELTA(20./10,*(binWidth+1),1.e-5); - TS_ASSERT_DELTA(20./20,*(binWidth+2),1.e-5); - TS_ASSERT_DELTA(20./10,*(binWidth+3),1.e-5); - + TS_ASSERT_DELTA(20. / 5, *(binWidth + 0), 1.e-5); + TS_ASSERT_DELTA(20. / 10, *(binWidth + 1), 1.e-5); + TS_ASSERT_DELTA(20. / 20, *(binWidth + 2), 1.e-5); + TS_ASSERT_DELTA(20. / 10, *(binWidth + 3), 1.e-5); } //--------------------------------------------------------------------------------------------------- - void test_createIterator() - { - MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 10)); + void test_createIterator() { + MDHistoDimension_sptr dimX( + new MDHistoDimension("X", "x", "m", -10, 10, 10)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -9, 10, 10)); MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -8, 10, 10)); MDHistoWorkspace ws(dimX, dimY, dimZ); - IMDIterator * it = ws.createIterator(); - TS_ASSERT( it ); - MDHistoWorkspaceIterator * hwit = dynamic_cast<MDHistoWorkspaceIterator *>(it); - TS_ASSERT( hwit ); - TS_ASSERT( it->next() ); + IMDIterator *it = ws.createIterator(); + TS_ASSERT(it); + MDHistoWorkspaceIterator *hwit = + dynamic_cast<MDHistoWorkspaceIterator *>(it); + TS_ASSERT(hwit); + TS_ASSERT(it->next()); delete it; boost::scoped_ptr<MDImplicitFunction> mdfunction(new MDImplicitFunction); it = ws.createIterator(mdfunction.get()); - TS_ASSERT( it ); + TS_ASSERT(it); delete it; } //--------------------------------------------------------------------------------------------------- - //Test for the IMDWorkspace aspects of MDWorkspace. - void testGetNonIntegratedDimensions() - { - MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 1)); //Integrated. - MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 10)); - MDHistoDimension_sptr dimZ(new MDHistoDimension("Z", "z", "m", -10, 10, 20)); - MDHistoDimension_sptr dimT(new MDHistoDimension("T", "t", "m", -10, 10, 10)); + // Test for the IMDWorkspace aspects of MDWorkspace. + void testGetNonIntegratedDimensions() { + MDHistoDimension_sptr dimX( + new MDHistoDimension("X", "x", "m", -10, 10, 1)); // Integrated. + MDHistoDimension_sptr dimY( + new MDHistoDimension("Y", "y", "m", -10, 10, 10)); + MDHistoDimension_sptr dimZ( + new MDHistoDimension("Z", "z", "m", -10, 10, 20)); + MDHistoDimension_sptr dimT( + new MDHistoDimension("T", "t", "m", -10, 10, 10)); MDHistoWorkspace ws(dimX, dimY, dimZ, dimT); - Mantid::Geometry::VecIMDDimension_const_sptr vecNonIntegratedDims = ws.getNonIntegratedDimensions(); - TSM_ASSERT_EQUALS("Only 3 of the 4 dimensions should be non-integrated", 3, vecNonIntegratedDims.size()); - TSM_ASSERT_EQUALS("First non-integrated dimension should be Y", "y", vecNonIntegratedDims[0]->getDimensionId()); - TSM_ASSERT_EQUALS("Second non-integrated dimension should be Z", "z", vecNonIntegratedDims[1]->getDimensionId()); - TSM_ASSERT_EQUALS("Third non-integrated dimension should be T", "t", vecNonIntegratedDims[2]->getDimensionId()); + Mantid::Geometry::VecIMDDimension_const_sptr vecNonIntegratedDims = + ws.getNonIntegratedDimensions(); + TSM_ASSERT_EQUALS("Only 3 of the 4 dimensions should be non-integrated", 3, + vecNonIntegratedDims.size()); + TSM_ASSERT_EQUALS("First non-integrated dimension should be Y", "y", + vecNonIntegratedDims[0]->getDimensionId()); + TSM_ASSERT_EQUALS("Second non-integrated dimension should be Z", "z", + vecNonIntegratedDims[1]->getDimensionId()); + TSM_ASSERT_EQUALS("Third non-integrated dimension should be T", "t", + vecNonIntegratedDims[2]->getDimensionId()); } - //--------------------------------------------------------------------------------------------------- - void test_getGeometryXML() - { - //If POCO xml supported schema validation, we wouldn't need to check xml outputs like this. - std::string expectedXML = std::string("<DimensionSet>") + - "<Dimension ID=\"x\">" + - "<Name>X</Name>" + - "<Units>m</Units>" + - "<Frame>Unknown frame</Frame>" + - "<UpperBounds>10.0000</UpperBounds>" + - "<LowerBounds>-10.0000</LowerBounds>" + - "<NumberOfBins>5</NumberOfBins>" + - "</Dimension>" + - "<Dimension ID=\"y\">" + - "<Name>Y</Name>" + - "<Units>m</Units>" + - "<Frame>Unknown frame</Frame>" + - "<UpperBounds>10.0000</UpperBounds>" + - "<LowerBounds>-10.0000</LowerBounds>" + - "<NumberOfBins>5</NumberOfBins>" + - "</Dimension>" + - "<Dimension ID=\"z\">" + - "<Name>Z</Name>" + - "<Units>m</Units>" + - "<Frame>Unknown frame</Frame>" + - "<UpperBounds>10.0000</UpperBounds>" + - "<LowerBounds>-10.0000</LowerBounds>" + - "<NumberOfBins>5</NumberOfBins>" + - "</Dimension>" + - "<Dimension ID=\"t\">" + - "<Name>T</Name>" + - "<Units>m</Units>" + - "<Frame>Unknown frame</Frame>" + - "<UpperBounds>10.0000</UpperBounds>" + - "<LowerBounds>-10.0000</LowerBounds>" + - "<NumberOfBins>5</NumberOfBins>" + - "</Dimension>" + - "<XDimension>" + - "<RefDimensionId>x</RefDimensionId>" + - "</XDimension>" + - "<YDimension>" + - "<RefDimensionId>y</RefDimensionId>" + - "</YDimension>" + - "<ZDimension>" + - "<RefDimensionId>z</RefDimensionId>" + - "</ZDimension>" + - "<TDimension>" + - "<RefDimensionId>t</RefDimensionId>" + - "</TDimension>" + - "</DimensionSet>"; + void test_getGeometryXML() { + // If POCO xml supported schema validation, we wouldn't need to check xml + // outputs like this. + std::string expectedXML = + std::string("<DimensionSet>") + "<Dimension ID=\"x\">" + + "<Name>X</Name>" + "<Units>m</Units>" + "<Frame>Unknown frame</Frame>" + + "<UpperBounds>10.0000</UpperBounds>" + + "<LowerBounds>-10.0000</LowerBounds>" + + "<NumberOfBins>5</NumberOfBins>" + "</Dimension>" + + "<Dimension ID=\"y\">" + "<Name>Y</Name>" + "<Units>m</Units>" + + "<Frame>Unknown frame</Frame>" + "<UpperBounds>10.0000</UpperBounds>" + + "<LowerBounds>-10.0000</LowerBounds>" + + "<NumberOfBins>5</NumberOfBins>" + "</Dimension>" + + "<Dimension ID=\"z\">" + "<Name>Z</Name>" + "<Units>m</Units>" + + "<Frame>Unknown frame</Frame>" + "<UpperBounds>10.0000</UpperBounds>" + + "<LowerBounds>-10.0000</LowerBounds>" + + "<NumberOfBins>5</NumberOfBins>" + "</Dimension>" + + "<Dimension ID=\"t\">" + "<Name>T</Name>" + "<Units>m</Units>" + + "<Frame>Unknown frame</Frame>" + "<UpperBounds>10.0000</UpperBounds>" + + "<LowerBounds>-10.0000</LowerBounds>" + + "<NumberOfBins>5</NumberOfBins>" + "</Dimension>" + "<XDimension>" + + "<RefDimensionId>x</RefDimensionId>" + "</XDimension>" + + "<YDimension>" + "<RefDimensionId>y</RefDimensionId>" + + "</YDimension>" + "<ZDimension>" + + "<RefDimensionId>z</RefDimensionId>" + "</ZDimension>" + + "<TDimension>" + "<RefDimensionId>t</RefDimensionId>" + + "</TDimension>" + "</DimensionSet>"; MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); MDHistoDimension_sptr dimY(new MDHistoDimension("Y", "y", "m", -10, 10, 5)); @@ -448,308 +431,317 @@ public: } //--------------------------------------------------------------------------------------------------- - void test_getNumEvents() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + void test_getNumEvents() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); ws->setNumEventsAt(0, 123); ws->setNumEventsAt(1, 345); - TS_ASSERT_DELTA( ws->getNumEventsAt(0), 123, 1e-6); - TS_ASSERT_DELTA( ws->getNumEventsAt(1), 345, 1e-6); + TS_ASSERT_DELTA(ws->getNumEventsAt(0), 123, 1e-6); + TS_ASSERT_DELTA(ws->getNumEventsAt(1), 345, 1e-6); } //--------------------------------------------------------------------------------------------------- - void test_getSignalAtCoord() - { + void test_getSignalAtCoord() { // 2D workspace with signal[i] = i (linear index) - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); IMDWorkspace_sptr iws(ws); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(0.5, 0.5)), 0.0, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(1.5, 0.5)), 1.0, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(1.5, 1.5)), 11.0, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(9.5, 9.5)), 99.0, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(0.5, 0.5)), 0.0, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(1.5, 0.5)), 1.0, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(1.5, 1.5)), 11.0, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(9.5, 9.5)), 99.0, 1e-6); // Out of range = NaN - TS_ASSERT( boost::math::isnan(iws->getSignalAtVMD(VMD(-0.01, 2.5)) ) ); - TS_ASSERT( boost::math::isnan(iws->getSignalAtVMD(VMD(3.5, -0.02)) ) ); - TS_ASSERT( boost::math::isnan(iws->getSignalAtVMD(VMD(10.01, 2.5)) ) ); - TS_ASSERT( boost::math::isnan(iws->getSignalAtVMD(VMD(3.5, 10.02)) ) ); + TS_ASSERT(boost::math::isnan(iws->getSignalAtVMD(VMD(-0.01, 2.5)))); + TS_ASSERT(boost::math::isnan(iws->getSignalAtVMD(VMD(3.5, -0.02)))); + TS_ASSERT(boost::math::isnan(iws->getSignalAtVMD(VMD(10.01, 2.5)))); + TS_ASSERT(boost::math::isnan(iws->getSignalAtVMD(VMD(3.5, 10.02)))); } //--------------------------------------------------------------------------------------------------- - void test_getSignalAtCoord_withNormalization() - { + void test_getSignalAtCoord_withNormalization() { // 2D workspace with signal[i] = i (linear index) - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10, 20); - for (size_t i=0; i<100; i++) - { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10, 20); + for (size_t i = 0; i < 100; i++) { ws->setSignalAt(i, double(i)); ws->setNumEventsAt(i, 10.0); } IMDWorkspace_sptr iws(ws); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(0.5, 0.5)), 0.0, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(3.5, 0.5), NoNormalization), 1.0, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(3.5, 0.5), VolumeNormalization), 0.25, 1e-6); - TS_ASSERT_DELTA( iws->getSignalAtVMD(VMD(3.5, 0.5), NumEventsNormalization), 0.1, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(0.5, 0.5)), 0.0, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(3.5, 0.5), NoNormalization), 1.0, + 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(3.5, 0.5), VolumeNormalization), + 0.25, 1e-6); + TS_ASSERT_DELTA(iws->getSignalAtVMD(VMD(3.5, 0.5), NumEventsNormalization), + 0.1, 1e-6); } //--------------------------------------------------------------------------------------------------- /** Line along X, going positive */ - void test_getLinePlot_horizontal() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + void test_getLinePlot_horizontal() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); VMD start(0.5, 0.5); VMD end(9.5, 0.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); - TS_ASSERT_EQUALS( x.size(), 11); - TS_ASSERT_DELTA( x[0], 0.0, 1e-5); - TS_ASSERT_DELTA( x[1], 0.5, 1e-5); - TS_ASSERT_DELTA( x[2], 1.5, 1e-5); - TS_ASSERT_DELTA( x[10], 9.0, 1e-5); + ws->getLinePlot(start, end, NoNormalization, x, y, e); + TS_ASSERT_EQUALS(x.size(), 11); + TS_ASSERT_DELTA(x[0], 0.0, 1e-5); + TS_ASSERT_DELTA(x[1], 0.5, 1e-5); + TS_ASSERT_DELTA(x[2], 1.5, 1e-5); + TS_ASSERT_DELTA(x[10], 9.0, 1e-5); - TS_ASSERT_EQUALS( y.size(), 10); - TS_ASSERT_DELTA( y[0], 0.0, 1e-5); - TS_ASSERT_DELTA( y[1], 1.0, 1e-5); - TS_ASSERT_DELTA( y[2], 2.0, 1e-5); + TS_ASSERT_EQUALS(y.size(), 10); + TS_ASSERT_DELTA(y[0], 0.0, 1e-5); + TS_ASSERT_DELTA(y[1], 1.0, 1e-5); + TS_ASSERT_DELTA(y[2], 2.0, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Line along X, going positive */ - void test_getLinePlot_3D() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 3, 10); - for (size_t i=0; i<1000; i++) + void test_getLinePlot_3D() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 3, 10); + for (size_t i = 0; i < 1000; i++) ws->setSignalAt(i, double(i)); VMD start(0.5, 0.5, 0.5); VMD end(9.5, 0.5, 0.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); - TS_ASSERT_EQUALS( x.size(), 11); - TS_ASSERT_DELTA( x[0], 0.0, 1e-5); - TS_ASSERT_DELTA( x[1], 0.5, 1e-5); - TS_ASSERT_DELTA( x[2], 1.5, 1e-5); - TS_ASSERT_DELTA( x[10], 9.0, 1e-5); + ws->getLinePlot(start, end, NoNormalization, x, y, e); + TS_ASSERT_EQUALS(x.size(), 11); + TS_ASSERT_DELTA(x[0], 0.0, 1e-5); + TS_ASSERT_DELTA(x[1], 0.5, 1e-5); + TS_ASSERT_DELTA(x[2], 1.5, 1e-5); + TS_ASSERT_DELTA(x[10], 9.0, 1e-5); - TS_ASSERT_EQUALS( y.size(), 10); - TS_ASSERT_DELTA( y[0], 0.0, 1e-5); - TS_ASSERT_DELTA( y[1], 1.0, 1e-5); - TS_ASSERT_DELTA( y[2], 2.0, 1e-5); + TS_ASSERT_EQUALS(y.size(), 10); + TS_ASSERT_DELTA(y[0], 0.0, 1e-5); + TS_ASSERT_DELTA(y[1], 1.0, 1e-5); + TS_ASSERT_DELTA(y[2], 2.0, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Line along X, going negative */ - void test_getLinePlot_horizontal_backwards() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + void test_getLinePlot_horizontal_backwards() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); VMD start(9.5, 0.5); VMD end(0.5, 0.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); - TS_ASSERT_EQUALS( x.size(), 11); - TS_ASSERT_DELTA( x[0], 0.0, 1e-5); - TS_ASSERT_DELTA( x[1], 0.5, 1e-5); - TS_ASSERT_DELTA( x[2], 1.5, 1e-5); - TS_ASSERT_DELTA( x[10], 9.0, 1e-5); + ws->getLinePlot(start, end, NoNormalization, x, y, e); + TS_ASSERT_EQUALS(x.size(), 11); + TS_ASSERT_DELTA(x[0], 0.0, 1e-5); + TS_ASSERT_DELTA(x[1], 0.5, 1e-5); + TS_ASSERT_DELTA(x[2], 1.5, 1e-5); + TS_ASSERT_DELTA(x[10], 9.0, 1e-5); - TS_ASSERT_EQUALS( y.size(), 10); - TS_ASSERT_DELTA( y[0], 9.0, 1e-5); - TS_ASSERT_DELTA( y[1], 8.0, 1e-5); - TS_ASSERT_DELTA( y[2], 7.0, 1e-5); + TS_ASSERT_EQUALS(y.size(), 10); + TS_ASSERT_DELTA(y[0], 9.0, 1e-5); + TS_ASSERT_DELTA(y[1], 8.0, 1e-5); + TS_ASSERT_DELTA(y[2], 7.0, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Diagonal line at 45 degrees crosses through 3 bins */ - void test_getLinePlot_diagonal() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + void test_getLinePlot_diagonal() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); VMD start(0.9, 0.5); VMD end(1.9, 1.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); + ws->getLinePlot(start, end, NoNormalization, x, y, e); std::cout << "X\n" << Strings::join(x.begin(), x.end(), ",") << std::endl; std::cout << "Y\n" << Strings::join(y.begin(), y.end(), ",") << std::endl; - TS_ASSERT_EQUALS( x.size(), 4); - TS_ASSERT_DELTA( x[0], 0.0, 1e-5); - TS_ASSERT_DELTA( x[1], 0.1 * sqrt(2.0), 1e-5); - TS_ASSERT_DELTA( x[2], 0.5 * sqrt(2.0), 1e-5); - TS_ASSERT_DELTA( x[3], 1.0 * sqrt(2.0), 1e-5); + TS_ASSERT_EQUALS(x.size(), 4); + TS_ASSERT_DELTA(x[0], 0.0, 1e-5); + TS_ASSERT_DELTA(x[1], 0.1 * sqrt(2.0), 1e-5); + TS_ASSERT_DELTA(x[2], 0.5 * sqrt(2.0), 1e-5); + TS_ASSERT_DELTA(x[3], 1.0 * sqrt(2.0), 1e-5); - TS_ASSERT_EQUALS( y.size(), 3); - TS_ASSERT_DELTA( y[0], 0.0, 1e-5); - TS_ASSERT_DELTA( y[1], 1.0, 1e-5); - TS_ASSERT_DELTA( y[2],11.0, 1e-5); + TS_ASSERT_EQUALS(y.size(), 3); + TS_ASSERT_DELTA(y[0], 0.0, 1e-5); + TS_ASSERT_DELTA(y[1], 1.0, 1e-5); + TS_ASSERT_DELTA(y[2], 11.0, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Line along X, going positive, starting before and ending after limits */ - void test_getLinePlot_horizontal_pastEdges() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + void test_getLinePlot_horizontal_pastEdges() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); VMD start(-0.5, 0.5); VMD end(10.5, 0.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); - TS_ASSERT_EQUALS( x.size(), 11); - TS_ASSERT_DELTA( x[0], 0.5, 1e-5); - TS_ASSERT_DELTA( x[1], 1.5, 1e-5); - TS_ASSERT_DELTA( x[2], 2.5, 1e-5); - TS_ASSERT_DELTA( x[10], 10.5, 1e-5); + ws->getLinePlot(start, end, NoNormalization, x, y, e); + TS_ASSERT_EQUALS(x.size(), 11); + TS_ASSERT_DELTA(x[0], 0.5, 1e-5); + TS_ASSERT_DELTA(x[1], 1.5, 1e-5); + TS_ASSERT_DELTA(x[2], 2.5, 1e-5); + TS_ASSERT_DELTA(x[10], 10.5, 1e-5); - TS_ASSERT_EQUALS( y.size(), 10); - TS_ASSERT_DELTA( y[0], 0.0, 1e-5); - TS_ASSERT_DELTA( y[1], 1.0, 1e-5); - TS_ASSERT_DELTA( y[2], 2.0, 1e-5); + TS_ASSERT_EQUALS(y.size(), 10); + TS_ASSERT_DELTA(y[0], 0.0, 1e-5); + TS_ASSERT_DELTA(y[1], 1.0, 1e-5); + TS_ASSERT_DELTA(y[2], 2.0, 1e-5); } //--------------------------------------------------------------------------------------------------- /** Line that completely misses the workspace */ - void test_getLinePlot_totallyOutOfBounds() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); - for (size_t i=0; i<100; i++) + void test_getLinePlot_totallyOutOfBounds() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10); + for (size_t i = 0; i < 100; i++) ws->setSignalAt(i, double(i)); VMD start(-5, 5); VMD end(1, 20.5); std::vector<coord_t> x; std::vector<signal_t> y; std::vector<signal_t> e; - ws->getLinePlot(start, end, NoNormalization, x,y,e); - TS_ASSERT_EQUALS( x.size(), 2); - TS_ASSERT_DELTA( x[0], 0, 1e-5); + ws->getLinePlot(start, end, NoNormalization, x, y, e); + TS_ASSERT_EQUALS(x.size(), 2); + TS_ASSERT_DELTA(x[0], 0, 1e-5); // NAN for Y - TS_ASSERT_EQUALS( y.size(), 1); - TS_ASSERT( y[0] != y[0]); + TS_ASSERT_EQUALS(y.size(), 1); + TS_ASSERT(y[0] != y[0]); } //-------------------------------------------------------------------------------------- - void test_plus_ws() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.5 /*errorSquared*/); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.5 /*errorSquared*/); + void test_plus_ws() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.5 /*errorSquared*/); + MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 3.5 /*errorSquared*/); *a += *b; checkWorkspace(a, 5.0, 6.0, 2.0); } - void test_plus_scalar() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.5 /*errorSquared*/); + void test_plus_scalar() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.5 /*errorSquared*/); a->add(3.0, sqrt(3.5)); checkWorkspace(a, 5.0, 6.0, 1.0); } //-------------------------------------------------------------------------------------- - void test_minus_ws() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 2.5 /*errorSquared*/); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.5 /*errorSquared*/); + void test_minus_ws() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 2.5 /*errorSquared*/); + MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 3.5 /*errorSquared*/); *a -= *b; checkWorkspace(a, 1.0, 6.0, 2.0); } - void test_minus_scalar() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 2.5 /*errorSquared*/); + void test_minus_scalar() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 2.5 /*errorSquared*/); a->subtract(2.0, sqrt(3.5)); checkWorkspace(a, 1.0, 6.0, 1.0); } //-------------------------------------------------------------------------------------- - void test_times_ws() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/, "", 2.0); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/, "", 3.0); + void test_times_ws() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.0 /*errorSquared*/, "", 2.0); + MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 3.0 /*errorSquared*/, "", 3.0); *a *= *b; - checkWorkspace(a, 6.0, 36. * (.5 + 1./3.), 2.0); + checkWorkspace(a, 6.0, 36. * (.5 + 1. / 3.), 2.0); } //-------------------------------------------------------------------------------------- - void test_times_scalar() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); + void test_times_scalar() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); a->multiply(3.0, sqrt(3.0)); - checkWorkspace(a, 6.0, 36. * (.5 + 1./3.), 1.0); + checkWorkspace(a, 6.0, 36. * (.5 + 1. / 3.), 1.0); // Scalar without error - MDHistoWorkspace_sptr d = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); + MDHistoWorkspace_sptr d = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); WorkspaceSingleValue e(3.0, 0); d->multiply(3.0, 0); checkWorkspace(d, 6.0, 9 * 2.0, 1.0); } //-------------------------------------------------------------------------------------- - void test_divide_ws() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); + void test_divide_ws() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 3.0 /*errorSquared*/); + MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.0, 2, 5, 10.0, 2.0 /*errorSquared*/); *a /= *b; - checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1./3.)); + checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1. / 3.)); } //-------------------------------------------------------------------------------------- - void test_divide_scalar() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/); + void test_divide_scalar() { + MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 3.0, 2, 5, 10.0, 3.0 /*errorSquared*/); a->divide(2.0, sqrt(2.0)); - checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1./3.), 1.0); + checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1. / 3.), 1.0); } //-------------------------------------------------------------------------------------- - void test_exp() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.0); + void test_exp() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.0); a->exp(); - checkWorkspace(a, std::exp(2.0), std::exp(2.0)*std::exp(2.0) * 3.0, 1.0); + checkWorkspace(a, std::exp(2.0), std::exp(2.0) * std::exp(2.0) * 3.0, 1.0); } //-------------------------------------------------------------------------------------- - void test_log() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.71828, 2, 5, 10.0, 3.0); + void test_log() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.71828, 2, 5, 10.0, 3.0); a->log(); - checkWorkspace(a, 1.0, 3.0/(2.71828*2.71828), 1.0); + checkWorkspace(a, 1.0, 3.0 / (2.71828 * 2.71828), 1.0); } //-------------------------------------------------------------------------------------- - void test_log10() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(10.0, 2, 5, 10.0, 3.0); + void test_log10() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(10.0, 2, 5, 10.0, 3.0); a->log10(); - checkWorkspace(a, 1.0, 0.1886117 * 3./100., 1.0); + checkWorkspace(a, 1.0, 0.1886117 * 3. / 100., 1.0); } //-------------------------------------------------------------------------------------- - void test_power() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.0); + void test_power() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.0); a->power(2.); - checkWorkspace(a, 4.0, 16*4*3./4., 1.0); + checkWorkspace(a, 4.0, 16 * 4 * 3. / 4., 1.0); } //-------------------------------------------------------------------------------------- - void test_boolean_and() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); - MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); + void test_boolean_and() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); + MDHistoWorkspace_sptr b = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); + MDHistoWorkspace_sptr c = + MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); *a &= *b; checkWorkspace(a, 1.0, 0.0); *b &= *c; @@ -757,11 +749,13 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_or() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); - MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); + void test_boolean_or() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); + MDHistoWorkspace_sptr b = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); + MDHistoWorkspace_sptr c = + MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); *a |= *b; checkWorkspace(a, 1.0, 0.0); *b |= *c; @@ -771,11 +765,13 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_xor() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); - MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); + void test_boolean_xor() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); + MDHistoWorkspace_sptr b = + MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); + MDHistoWorkspace_sptr c = + MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); *a ^= *b; checkWorkspace(a, 0.0, 0.0); *b ^= *c; @@ -785,10 +781,11 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_operatorNot() - { - MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); + void test_boolean_operatorNot() { + MDHistoWorkspace_sptr a = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); + MDHistoWorkspace_sptr b = + MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0); a->operatorNot(); checkWorkspace(a, 0.0, 0.0); b->operatorNot(); @@ -796,8 +793,7 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_lessThan() - { + void test_boolean_lessThan() { MDHistoWorkspace_sptr a, b, c; a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); @@ -816,8 +812,7 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_greaterThan() - { + void test_boolean_greaterThan() { MDHistoWorkspace_sptr a, b, c; a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0); @@ -836,11 +831,11 @@ public: } //-------------------------------------------------------------------------------------- - void test_boolean_equalTo() - { + void test_boolean_equalTo() { MDHistoWorkspace_sptr a, b, c; a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - b = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23000001, 2, 5, 10.0, 2.0); + b = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23000001, 2, 5, 10.0, + 2.0); a->equalTo(*b); checkWorkspace(a, 1.0, 0.0); @@ -861,13 +856,12 @@ public: checkWorkspace(a, 1.0, 0.0); } - //-------------------------------------------------------------------------------------- - void test_setUsingMask() - { + void test_setUsingMask() { MDHistoWorkspace_sptr a, mask, c; a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0); - mask = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 0.0); //mask + mask = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, + 0.0); // mask c = MDEventsTestHelper::makeFakeMDHistoWorkspace(4.56, 2, 5, 10.0, 2.0); a->setUsingMask(*mask, *c); checkWorkspace(a, 1.23, 3.0); @@ -877,45 +871,44 @@ public: checkWorkspace(a, 4.56, 2.0); a->setUsingMask(*mask, 7.89, 11); - checkWorkspace(a, 7.89, 11*11 ); + checkWorkspace(a, 7.89, 11 * 11); mask->setTo(0.0, 0.0, 0.0); a->setUsingMask(*mask, 6.66, 7.77); - checkWorkspace(a, 7.89, 11*11 ); + checkWorkspace(a, 7.89, 11 * 11); // Now a partial mask mask->setSignalAt(0, 1.0); mask->setSignalAt(2, 1.0); a->setTo(1.23, 4.56, 0.0); a->setUsingMask(*mask, 6.78, 7.89); - TS_ASSERT_DELTA( a->getSignalAt(0), 6.78, 1e-5); - TS_ASSERT_DELTA( a->getSignalAt(1), 1.23, 1e-5); - TS_ASSERT_DELTA( a->getSignalAt(2), 6.78, 1e-5); + TS_ASSERT_DELTA(a->getSignalAt(0), 6.78, 1e-5); + TS_ASSERT_DELTA(a->getSignalAt(1), 1.23, 1e-5); + TS_ASSERT_DELTA(a->getSignalAt(2), 6.78, 1e-5); } - - void doTestMasking(MDImplicitFunction* function, size_t expectedNumberMasked) - { + void doTestMasking(MDImplicitFunction *function, + size_t expectedNumberMasked) { // 10x10x10 eventWorkspace - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 3, 10, 10.0); + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 3, 10, 10.0); ws->setMDMasking(function); size_t numberMasked = getNumberMasked(ws); - TSM_ASSERT_EQUALS("Didn't perform the masking as expected", expectedNumberMasked, numberMasked); + TSM_ASSERT_EQUALS("Didn't perform the masking as expected", + expectedNumberMasked, numberMasked); } - void test_maskNULL() - { - doTestMasking(NULL, 0); //1000 out of 1000 bins masked + void test_maskNULL() { + doTestMasking(NULL, 0); // 1000 out of 1000 bins masked } - void test_mask_everything() - { + void test_mask_everything() { std::vector<coord_t> min; std::vector<coord_t> max; - //Make the box that covers half the bins in the workspace. + // Make the box that covers half the bins in the workspace. min.push_back(0); min.push_back(0); min.push_back(0); @@ -923,18 +916,16 @@ public: max.push_back(10); max.push_back(10); - //Create an function that encompases ALL of the total bins. - MDImplicitFunction* function = new MDBoxImplicitFunction(min, max); - doTestMasking(function, 1000); //1000 out of 1000 bins masked + // Create an function that encompases ALL of the total bins. + MDImplicitFunction *function = new MDBoxImplicitFunction(min, max); + doTestMasking(function, 1000); // 1000 out of 1000 bins masked } - - void test_maskHalf() - { + void test_maskHalf() { std::vector<coord_t> min; std::vector<coord_t> max; - //Make the box that covers half the bins in the workspace. + // Make the box that covers half the bins in the workspace. min.push_back(0); min.push_back(0); min.push_back(0); @@ -942,15 +933,13 @@ public: max.push_back(10); max.push_back(4.99f); - //Create an function that encompases 1/2 of the total bins. - MDImplicitFunction* function = new MDBoxImplicitFunction(min, max); - doTestMasking(function, 500); //500 out of 1000 bins masked + // Create an function that encompases 1/2 of the total bins. + MDImplicitFunction *function = new MDBoxImplicitFunction(min, max); + doTestMasking(function, 500); // 500 out of 1000 bins masked } - - void test_clearMasking() - { - //Create a function that masks everything. + void test_clearMasking() { + // Create a function that masks everything. std::vector<coord_t> min; std::vector<coord_t> max; min.push_back(0); @@ -959,34 +948,76 @@ public: max.push_back(10); max.push_back(10); max.push_back(10); - MDImplicitFunction* function = new MDBoxImplicitFunction(min, max); + MDImplicitFunction *function = new MDBoxImplicitFunction(min, max); - MDEventWorkspace3Lean::sptr ws = MDEventsTestHelper::makeMDEW<3>(10, 0.0, 10.0, 1 /*event per box*/); + MDEventWorkspace3Lean::sptr ws = + MDEventsTestHelper::makeMDEW<3>(10, 0.0, 10.0, 1 /*event per box*/); ws->setMDMasking(function); - TSM_ASSERT_EQUALS("Everything should be masked.", 1000, getNumberMasked(ws)); + TSM_ASSERT_EQUALS("Everything should be masked.", 1000, + getNumberMasked(ws)); TS_ASSERT_THROWS_NOTHING(ws->clearMDMasking()); TSM_ASSERT_EQUALS("Nothing should be masked.", 0, getNumberMasked(ws)); } - void test_getSpecialCoordinateSystem_default() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1); - TSM_ASSERT_EQUALS("Should default to no special coordinate system.", Mantid::Kernel::None, ws->getSpecialCoordinateSystem()); + void test_getSpecialCoordinateSystem_default() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1); + TSM_ASSERT_EQUALS("Should default to no special coordinate system.", + Mantid::Kernel::None, ws->getSpecialCoordinateSystem()); } - void test_setSpecialCoordinateSystem_default() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1); + void test_setSpecialCoordinateSystem_default() { + MDHistoWorkspace_sptr ws = + MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1); TS_ASSERT_EQUALS(Mantid::Kernel::None, ws->getSpecialCoordinateSystem()); ws->setCoordinateSystem(Mantid::Kernel::QLab); TS_ASSERT_EQUALS(Mantid::Kernel::QLab, ws->getSpecialCoordinateSystem()); } + void test_displayNormalizationDefault() { + MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); + // Constructor variant 1. + MDHistoWorkspace ws1(dimX); + TS_ASSERT_EQUALS(Mantid::API::NoNormalization, ws1.displayNormalization()); -}; + auto geometry2 = std::vector<IMDDimension_sptr>(1, dimX); + // Constructor variant 2. + MDHistoWorkspace ws2(geometry2); + TS_ASSERT_EQUALS(Mantid::API::NoNormalization, ws2.displayNormalization()); + auto geometry3 = std::vector<MDHistoDimension_sptr>(1, dimX); + // Constructor variant 3. + MDHistoWorkspace ws3(geometry3); + TS_ASSERT_EQUALS(Mantid::API::NoNormalization, ws3.displayNormalization()); + } -#endif /* MANTID_DATAOBJECTS_MDHISTOWORKSPACETEST_H_ */ + void test_setDisplayNormalization() { + + auto targetDisplayNormalization = Mantid::API::VolumeNormalization; + + MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5)); + // Constructor variant 1. + MDHistoWorkspace ws1(dimX, dimX, dimX, dimX, targetDisplayNormalization); + TS_ASSERT_EQUALS(targetDisplayNormalization, ws1.displayNormalization()); + + auto geometry2 = std::vector<IMDDimension_sptr>(1, dimX); + // Constructor variant 2. + MDHistoWorkspace ws2(geometry2, targetDisplayNormalization); + TS_ASSERT_EQUALS(targetDisplayNormalization, ws2.displayNormalization()); + + auto geometry3 = std::vector<MDHistoDimension_sptr>(1, dimX); + // Constructor variant 3. + MDHistoWorkspace ws3(geometry3, targetDisplayNormalization); + TS_ASSERT_EQUALS(targetDisplayNormalization, ws3.displayNormalization()); + // Quick check of clone + auto clone = ws3.clone(); + TS_ASSERT_EQUALS(targetDisplayNormalization, clone->displayNormalization()); + + + } +}; + +#endif /* MANTID_DATAOBJECTS_MDHISTOWORKSPACETEST_H_ */ diff --git a/Code/Mantid/Framework/Kernel/test/HermitePolynomialsTest.h b/Code/Mantid/Framework/Kernel/test/HermitePolynomialsTest.h index ed10a2491af52cc72d63c6a6807bbacb994688f5..d9cd19c1c526ef81c15859a60494f1280f20b244 100644 --- a/Code/Mantid/Framework/Kernel/test/HermitePolynomialsTest.h +++ b/Code/Mantid/Framework/Kernel/test/HermitePolynomialsTest.h @@ -13,9 +13,7 @@ public: static HermitePolynomialsTest *createSuite() { return new HermitePolynomialsTest(); } static void destroySuite( HermitePolynomialsTest *suite ) { delete suite; } - // clang-format off void test_hermitePoly_With_SingleValue_Returns_Expected_Values_For_First_Few_Terms() - // clang-format on { using namespace Mantid::Kernel; static const unsigned int npoly(6); @@ -30,9 +28,7 @@ public: } } - // clang-format off void test_hermitePoly_With_Array_Values_Returns_Expected_Values_For_First_Few_Terms() - // clang-format on { using namespace Mantid::Kernel; diff --git a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt index 300e71cf835146346548f21c5a1e1712cbfcd6b0..d52d54087d1ee9ad8e3c019dbc931d490c2f9416 100644 --- a/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/MDAlgorithms/CMakeLists.txt @@ -32,6 +32,7 @@ set ( SRC_FILES src/CreateMDHistoWorkspace.cpp src/CreateMDWorkspace.cpp src/CutMD.cpp + src/DisplayNormalizationSetter.cpp src/DivideMD.cpp src/EqualToMD.cpp src/EvaluateMDFunction.cpp @@ -150,6 +151,7 @@ set ( INC_FILES inc/MantidMDAlgorithms/CreateMDHistoWorkspace.h inc/MantidMDAlgorithms/CreateMDWorkspace.h inc/MantidMDAlgorithms/CutMD.h + inc/MantidMDAlgorithms/DisplayNormalizationSetter.h inc/MantidMDAlgorithms/DivideMD.h inc/MantidMDAlgorithms/DllConfig.h inc/MantidMDAlgorithms/EqualToMD.h @@ -270,6 +272,7 @@ set ( TEST_FILES CreateMDHistoWorkspaceTest.h CreateMDWorkspaceTest.h CutMDTest.h + DisplayNormalizationSetterTest.h DivideMDTest.h EqualToMDTest.h EvaluateMDFunctionTest.h diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvToMDBase.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvToMDBase.h index 531a857eef5444cbbabbb67253792c3f7995206f..96e8752e42236c313a88bfc907c208c486f0cc48 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvToMDBase.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvToMDBase.h @@ -61,6 +61,10 @@ public: virtual void runConversion(API::Progress *) = 0; /// virtual destructor virtual ~ConvToMDBase(){} + /// Set the normalization options + virtual void setDisplayNormalization( + Mantid::API::IMDEventWorkspace_sptr mdWorkspace, + const Mantid::API::MatrixWorkspace_sptr& underlyingWorkspace); /** method returns unit conversion helper, used to convert input workspace units to the units, used by appropriate MD transformation diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h index e64581677f0ea3ee1e0f444a814cba7efd9d7161..e4b799f2f49c6336b4ed4165e64c870d5e219a6d 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h @@ -59,9 +59,10 @@ private: void init(); void exec(); - void addMDEvents(); + void addMDEvents(bool usevirtual); void convertSpiceMatrixToMomentumMDEvents(API::MatrixWorkspace_sptr dataws, + bool usevirtual, const detid_t &startdetid, const int runnumber); @@ -74,7 +75,7 @@ private: API::IMDEventWorkspace_sptr createExperimentMDWorkspace(); - bool getInputs(std::string &errmsg); + bool getInputs(bool virtualinstrument, std::string &errmsg); API::MatrixWorkspace_sptr loadSpiceData(const std::string &filename, bool &loaded, std::string &errmsg); @@ -85,6 +86,10 @@ private: void setupTransferMatrix(API::MatrixWorkspace_sptr dataws, Kernel::DblMatrix &rotationMatrix); + void createVirtualInstrument(); + + void updateQRange(const std::vector<Mantid::coord_t> &vec_q); + API::ITableWorkspace_sptr m_expDataTableWS; API::ITableWorkspace_sptr m_detectorListTableWS; API::IMDEventWorkspace_sptr m_outputWS; @@ -100,6 +105,10 @@ private: std::vector<double> m_extentMaxs; std::vector<size_t> m_numBins; + std::vector<coord_t> m_minQVec; + std::vector<coord_t> m_maxQVec; + bool m_setQRange; + /// Data directory std::string m_dataDir; /// Flag to use m_dataDir diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/DisplayNormalizationSetter.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/DisplayNormalizationSetter.h new file mode 100644 index 0000000000000000000000000000000000000000..53ffa75a484435e8fb41bbd6423a3d347c72856e --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/DisplayNormalizationSetter.h @@ -0,0 +1,55 @@ +#ifndef _MANTID_MDALGORITHMS_DISPLAYNORMALIZATION_SETTER_H +#define _MANTID_MDALGORITHMS_DISPLAYNORMALIZATION_SETTER_H +#include "MantidKernel/System.h" +#include "MantidKernel/DeltaEMode.h" +#include "MantidAPI/MatrixWorkspace_fwd.h" +#include "MantidAPI/IMDWorkspace.h" + +namespace Mantid { +namespace MDAlgorithms { +/** DisplayNormalizationSetter: Sets the displaynormalization on a + workspace based on several parameters such as workspace-type, +energy-transfer-mode + and if we are dealing with Q3D. + +Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge +National Laboratory & European Spallation Source + +This file is part of Mantid. + +Mantid is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +Mantid is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +File change history is stored at: <https://github.com/mantidproject/mantid> +Code Documentation is available at: <http://doxygen.mantidproject.org> +*/ +class DLLExport DisplayNormalizationSetter { +public: + void operator()(Mantid::API::IMDWorkspace_sptr workspace, + const Mantid::API::MatrixWorkspace_sptr &workspaceToCheck, bool isQ = false, + const Mantid::Kernel::DeltaEMode::Type &mode = Mantid::Kernel::DeltaEMode::Elastic); + +private: + void setNormalizationMDEvent( + Mantid::API::IMDWorkspace_sptr workspace, + const Mantid::API::MatrixWorkspace_sptr &underlyingWorkspace, bool isQ = false, + const Mantid::Kernel::DeltaEMode::Type &mode = Mantid::Kernel::DeltaEMode::Elastic); + + void applyNormalizationMDEvent( + Mantid::API::IMDWorkspace_sptr workspace, + Mantid::API::MDNormalization displayNormalization, + Mantid::API::MDNormalization displayNormalizationHisto); +}; +} +} +#endif \ No newline at end of file diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h index 67b0fe24edc4d639121d17b7b0108754a6e4be19..8bec827d8651454f725382288482bbf8e0b6918e 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h @@ -6,6 +6,7 @@ #include "MantidKernel/System.h" #include "MantidDataObjects/MDEventWorkspace.h" #include <boost/scoped_ptr.hpp> +#include <boost/optional.hpp> namespace Mantid { namespace MDAlgorithms { @@ -79,6 +80,9 @@ private: void loadCoordinateSystem(); + void loadVisualNormalization(const std::string &key, + boost::optional<Mantid::API::MDNormalization> &normalization); + /// Load all the affine matricies void loadAffineMatricies(API::IMDWorkspace_sptr ws); /// Load a given affine matrix @@ -104,6 +108,14 @@ private: /// Version of SaveMD used to save the file int m_saveMDVersion ; + + /// Visual normalization + boost::optional<Mantid::API::MDNormalization> m_visualNormalization; + boost::optional<Mantid::API::MDNormalization> m_visualNormalizationHisto; + + /// Named entry + static const std::string VISUAL_NORMALIZATION_KEY; + static const std::string VISUAL_NORMALIZATION_KEY_HISTO; }; } // namespace DataObjects diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfInterface.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfInterface.h index e06c8936695df7b024d4e52c5c9dfcbbc178d7d4..37eb09c456e6598adf432242f9ea10bb9e96bebb 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfInterface.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfInterface.h @@ -223,6 +223,16 @@ public: virtual unsigned int getNMatrixDimensions(Kernel::DeltaEMode::Type mode, API::MatrixWorkspace_const_sptr inWS) const = 0; + + /** + * Sets the display normalization + * @param mdWorkspace: the workspace on which the display normalizations should + * @param underlyingWorkspace: the original workspace + * be set + */ + virtual void setDisplayNormalization( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const = 0; }; typedef boost::shared_ptr<MDTransfInterface> MDTransf_sptr; diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfModQ.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfModQ.h index 773dc55455398705bd37f6479898403cd72e3d55..e71adfecd893118effd707645b49ee7a2b3617e0 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfModQ.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfModQ.h @@ -94,7 +94,9 @@ public: const std::string inputUnitID(Kernel::DeltaEMode::Type dEmode, API::MatrixWorkspace_const_sptr Sptr = API::MatrixWorkspace_const_sptr()) const; - + virtual void setDisplayNormalization( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const; protected: // directions to the detectors double m_ex, m_ey, m_ez; diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfNoQ.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfNoQ.h index bb9ef259251f1f1a22eb7c71d27e3f2dbe9e5675..8b8408049e6feab3c6c85eb2504293bec82b290c 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfNoQ.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDTransfNoQ.h @@ -86,6 +86,9 @@ public: const std::string inputUnitID(Kernel::DeltaEMode::Type mode, API::MatrixWorkspace_const_sptr inWS) const; + virtual void setDisplayNormalization( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const; private: unsigned int m_NMatrixDim; // the variables used for exchange data between different specific parts of diff --git a/Code/Mantid/Framework/MDAlgorithms/src/BinMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/BinMD.cpp index 233f9969e462ece5f60fa6e72cf4727e97cbad83..f914d8e5b0c3d939ef2a99dc1803fbf3ad8a9fac 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/BinMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/BinMD.cpp @@ -437,6 +437,9 @@ void BinMD::exec() { outWS->copyExperimentInfos(*inEWS); } + // Pass on the display normalization from the input workspace + outWS->setDisplayNormalization(m_inWS->displayNormalizationHisto()); + outWS->updateSum(); // Save the output setProperty("OutputWorkspace", boost::dynamic_pointer_cast<Workspace>(outWS)); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvToMDBase.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvToMDBase.cpp index 5f4ac5f5cab5109906328dc1b8673b79b2303e81..b629a0da1c0e408bbd429911ef24cdf4a6575fef 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/ConvToMDBase.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvToMDBase.cpp @@ -106,5 +106,16 @@ ConvToMDBase::ConvToMDBase() m_ignoreZeros(false), // 0-s added to workspace m_coordinateSystem(Mantid::Kernel::None) {} +/** + * Set the normalization options + */ +void ConvToMDBase::setDisplayNormalization( + Mantid::API::IMDEventWorkspace_sptr mdWorkspace, + const Mantid::API::MatrixWorkspace_sptr& underlyingWorkspace) { + if (m_QConverter) { + m_QConverter->setDisplayNormalization(mdWorkspace, underlyingWorkspace); + } +} + } // endNamespace MDAlgorithms } diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp index d6118cbd3af838a0d4ab365ae832078b7b720c60..7c7ea3e92cf05e9436af29d6e09b826b939b5ff4 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp @@ -24,7 +24,7 @@ DECLARE_ALGORITHM(ConvertCWSDExpToMomentum) /** Constructor */ ConvertCWSDExpToMomentum::ConvertCWSDExpToMomentum() - : m_iColFilename(2), m_iColStartDetID(3) {} + : m_iColFilename(2), m_iColStartDetID(3), m_setQRange(true) {} //---------------------------------------------------------------------------------------------- /** Destructor @@ -40,8 +40,10 @@ void ConvertCWSDExpToMomentum::init() { Direction::Input), "Name of table workspace for data file names in the experiment."); + declareProperty("CreateVirtualInstrument", false, "Flag to create virtual instrument."); + declareProperty(new WorkspaceProperty<ITableWorkspace>( - "DetectorTableWorkspace", "", Direction::Input), + "DetectorTableWorkspace", "", Direction::Input, PropertyMode::Optional), "Name of table workspace containing all the detectors."); declareProperty(new WorkspaceProperty<IMDEventWorkspace>( @@ -74,30 +76,38 @@ void ConvertCWSDExpToMomentum::init() { void ConvertCWSDExpToMomentum::exec() { // Parse inputs std::string errmsg(""); - bool inputvalid = getInputs(errmsg); - if (!inputvalid) + bool createvirtual = getProperty("CreateVirtualInstrument"); + bool inputvalid = getInputs(createvirtual, errmsg); + if (!inputvalid) { + g_log.error() << "Importing error: " << errmsg << "\n"; throw std::runtime_error(errmsg); - - g_log.notice("[DB] Inputs are examined."); + } // Create output MDEventWorkspace m_outputWS = createExperimentMDWorkspace(); + if (createvirtual) + createVirtualInstrument(); + // Add MDEventWorkspace - addMDEvents(); + addMDEvents(createvirtual); setProperty("OutputWorkspace", m_outputWS); + // Output + for (size_t i = 0; i < 3; ++i) { + g_log.notice() << "Q-sample at dimension " << i << ": " << m_minQVec[i] + << ", " << m_maxQVec[i] << "\n"; + } + return; } //---------------------------------------------------------------------------------------------- -/** Create output workspace - * @brief ConvertCWSDExpToMomentum::createExperimentMDWorkspace +/** Create virtual instrument * @return */ -API::IMDEventWorkspace_sptr -ConvertCWSDExpToMomentum::createExperimentMDWorkspace() { +void ConvertCWSDExpToMomentum::createVirtualInstrument() { // Get detector list from input table workspace std::vector<Kernel::V3D> vec_detpos; std::vector<detid_t> vec_detid; @@ -114,6 +124,17 @@ ConvertCWSDExpToMomentum::createExperimentMDWorkspace() { << m_virtualInstrument->getDetectorIDs().size() << "Detectors\n"; + return; +} + +//---------------------------------------------------------------------------------------------- +/** Create output workspace + * @brief ConvertCWSDExpToMomentum::createExperimentMDWorkspace + * @return + */ +API::IMDEventWorkspace_sptr +ConvertCWSDExpToMomentum::createExperimentMDWorkspace() { + // Create workspace in Q_sample with dimenion as 3 size_t nDimension = 3; IMDEventWorkspace_sptr mdws = @@ -142,6 +163,10 @@ ConvertCWSDExpToMomentum::createExperimentMDWorkspace() { m_extentMaxs.resize(3, 10.0); m_numBins.resize(3, 100); } + // Sample-Q range + m_minQVec.resize(3); + m_maxQVec.resize(3); + for (size_t d = 0; d < 3; ++d) g_log.debug() << "Direction " << d << ", Range = " << m_extentMins[d] << ", " << m_extentMaxs[d] << "\n"; @@ -166,8 +191,9 @@ ConvertCWSDExpToMomentum::createExperimentMDWorkspace() { /** Add MDEvents to MDEventWorkspace from data set in the experiment * Run number is determined by the row of the file in the input table workspace * @brief ConvertCWSDExpToMomentum::addMDEvents + * @param usevirtual :: flag to use virtual instrument */ -void ConvertCWSDExpToMomentum::addMDEvents() { +void ConvertCWSDExpToMomentum::addMDEvents(bool usevirtual) { MatrixWorkspace_sptr spicews; // Check whether to add / or \ to m_dataDir @@ -188,13 +214,19 @@ void ConvertCWSDExpToMomentum::addMDEvents() { // Init some variables size_t numrows = m_expDataTableWS->rowCount(); + if (numrows > 1 && !usevirtual) { + g_log.warning("There are more than 1 experiment to import. " + "Make sure that all of them have the same instrument."); + } size_t numFileNotLoaded(0); // Loop through all data files in the experiment for (size_t ir = 0; ir < numrows; ++ir) { std::string rawfilename = m_expDataTableWS->cell<std::string>(ir, m_iColFilename); - detid_t start_detid = m_expDataTableWS->cell<detid_t>(ir, m_iColStartDetID); + detid_t start_detid = 0; + if (usevirtual) + start_detid = m_expDataTableWS->cell<detid_t>(ir, m_iColStartDetID); // Load data bool loaded; @@ -216,7 +248,10 @@ void ConvertCWSDExpToMomentum::addMDEvents() { // Convert from MatrixWorkspace to MDEvents and add events to int runid = static_cast<int>(ir) + 1; - convertSpiceMatrixToMomentumMDEvents(spicews, start_detid, runid); + if (!usevirtual) + start_detid = 0; + convertSpiceMatrixToMomentumMDEvents(spicews, usevirtual, start_detid, + runid); } // Set box extentes @@ -285,15 +320,17 @@ void ConvertCWSDExpToMomentum::setupTransferMatrix( //---------------------------------------------------------------------------------------------- /** Convert a SPICE 2D Det MatrixWorkspace to MDEvents and append to an * MDEventWorkspace + * It is optional to use a virtual instrument or copy from input data workspace * @brief ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents * @param dataws :: data matrix workspace + * @param usevirtual :: boolean flag to use virtual instrument * @param startdetid :: starting detid for detectors from this workspace mapping * to virtual instrument in MDEventWorkspace * @param runnumber :: run number for all MDEvents created from this matrix * workspace */ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( - MatrixWorkspace_sptr dataws, const detid_t &startdetid, + MatrixWorkspace_sptr dataws, bool usevirtual, const detid_t &startdetid, const int runnumber) { // Create transformation matrix from which the transformation is Kernel::DblMatrix rotationMatrix; @@ -346,6 +383,7 @@ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( inserter.insertMDEvent( static_cast<float>(signal), static_cast<float>(error * error), static_cast<uint16_t>(runnumber), detid, q_sample.data()); + updateQRange(q_sample); g_log.debug() << "Q-lab = " << qlab.toString() << "\n"; g_log.debug() << "Insert DetID " << detid << ", signal = " << signal @@ -358,13 +396,18 @@ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( ++nummdevents; } - g_log.notice() << "[DB] New Matrixworkspace: Max. Signal = " << maxsignal - << ", Add " << nummdevents << " MDEvents " - << "\n"; + g_log.information() << "Imported Matrixworkspace: Max. Signal = " << maxsignal + << ", Add " << nummdevents << " MDEvents " + << "\n"; // Add experiment info including instrument, goniometer and run number ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>(); - expinfo->setInstrument(m_virtualInstrument); + if (usevirtual) + expinfo->setInstrument(m_virtualInstrument); + else { + Geometry::Instrument_const_sptr tmp_inst = dataws->getInstrument(); + expinfo->setInstrument(tmp_inst); + } expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false); expinfo->mutableRun().addProperty("run_number", runnumber); m_outputWS->addExperimentInfo(expinfo); @@ -375,10 +418,12 @@ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( //---------------------------------------------------------------------------------------------- /** Examine input * @brief ConvertCWSDExpToMomentum::getInputs + * @param virtualinstrument :: boolean flag to use virtual instrument * @param errmsg * @return */ -bool ConvertCWSDExpToMomentum::getInputs(std::string &errmsg) { +bool ConvertCWSDExpToMomentum::getInputs(bool virtualinstrument, + std::string &errmsg) { std::stringstream errss; // Table workspace for data file names and starting detector IDs (for virtual @@ -390,44 +435,55 @@ bool ConvertCWSDExpToMomentum::getInputs(std::string &errmsg) { errss << "InputWorkspace must have 4 columns. But now it has " << datacolnames.size() << " columns. \n"; } else { - if (datacolnames[m_iColFilename].compare("File Name") != 0) + if (datacolnames[m_iColFilename].compare("File Name") != 0 && + datacolnames[m_iColFilename].compare("Filename") != 0) errss << "Data file name Table (InputWorkspace)'s Column " - << m_iColFilename << " must be 'File Name'" + << m_iColFilename << " must be 'File Name' or 'Filename' but not " + << datacolnames[m_iColFilename] << ". " << "\n"; - if (datacolnames[m_iColStartDetID].compare("Starting DetID") != 0) + if (datacolnames[m_iColStartDetID].compare("Starting DetID") != 0 && + datacolnames[m_iColStartDetID].compare("StartDetID") != 0) errss << "Data file name Table (InputWorkspace)'s Column " - << m_iColStartDetID << " must be 'Staring DetID'" + << m_iColStartDetID + << " must be 'Staring DetID' or 'StartDetID' but not " + << datacolnames[m_iColStartDetID] << ". " << "\n"; } + g_log.warning("Finished parsing Data Table"); + + // Set up parameters for creating virtual instrument + g_log.warning() << "About to deal with virtual instrument" + << virtualinstrument << "\n"; + if (virtualinstrument) { + // Table workspace for detector positions + m_detectorListTableWS = getProperty("DetectorTableWorkspace"); + const std::vector<std::string> detcolnames = + m_detectorListTableWS->getColumnNames(); + if (detcolnames.size() != 5) { + errss << "Detector table (DetectorTableWorkspace) must have 5 columns" + << "\n"; + } - // Table workspace for detector positions - m_detectorListTableWS = getProperty("DetectorTableWorkspace"); - const std::vector<std::string> detcolnames = - m_detectorListTableWS->getColumnNames(); - if (detcolnames.size() != 5) { - errss << "Detector table (DetectorTableWorkspace) must have 5 columns" - << "\n"; - } - - // Sample and source position - std::vector<double> sourcepos = getProperty("SourcePosition"); - if (sourcepos.size() != 3) - errss << "SourcePosition must have 3 items. Input has " << sourcepos.size() - << " instead.\n"; - else { - m_sourcePos.setX(sourcepos[0]); - m_sourcePos.setY(sourcepos[1]); - m_sourcePos.setZ(sourcepos[2]); - } + // Sample and source position + std::vector<double> sourcepos = getProperty("SourcePosition"); + if (sourcepos.size() != 3) + errss << "SourcePosition must have 3 items. Input has " + << sourcepos.size() << " instead.\n"; + else { + m_sourcePos.setX(sourcepos[0]); + m_sourcePos.setY(sourcepos[1]); + m_sourcePos.setZ(sourcepos[2]); + } - std::vector<double> samplepos = getProperty("SamplePosition"); - if (samplepos.size() != 3) { - errss << "SamplePosition must have 3 items. Input has " << samplepos.size() - << " instead.\n"; - } else { - m_samplePos.setX(samplepos[0]); - m_samplePos.setY(samplepos[1]); - m_samplePos.setZ(samplepos[2]); + std::vector<double> samplepos = getProperty("SamplePosition"); + if (samplepos.size() != 3) { + errss << "SamplePosition must have 3 items. Input has " + << samplepos.size() << " instead.\n"; + } else { + m_samplePos.setX(samplepos[0]); + m_samplePos.setY(samplepos[1]); + m_samplePos.setZ(samplepos[2]); + } } m_isBaseName = getProperty("IsBaseName"); @@ -435,7 +491,8 @@ bool ConvertCWSDExpToMomentum::getInputs(std::string &errmsg) { m_dataDir = getPropertyValue("Directory"); errmsg = errss.str(); - return (errmsg.size() > 0); + + return (errmsg.size() == 0); } //---------------------------------------------------------------------------------------------- @@ -539,5 +596,26 @@ void ConvertCWSDExpToMomentum::parseDetectorTable( return; } +//---------------------------------------------------------------------------------------------- +/** Update (sample) Q range + * @brief ConvertCWSDExpToMomentum::updateQRange + * @param vec_q + */ +void ConvertCWSDExpToMomentum::updateQRange( + const std::vector<Mantid::coord_t> &vec_q) { + for (size_t i = 0; i < vec_q.size(); ++i) { + if (m_setQRange) { + m_minQVec[i] = vec_q[i]; + m_maxQVec[i] = vec_q[i]; + m_setQRange = false; + } else if (vec_q[i] < m_minQVec[i]) + m_minQVec[i] = vec_q[i]; + else if (vec_q[i] > m_maxQVec[i]) + m_maxQVec[i] = vec_q[i]; + } + + return; +} + } // namespace MDAlgorithms } // namespace Mantid diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMD.cpp index 0226204f7e277415cc9fbbfaa76e2679ef54193d..d8422e2976a6caaaed74239e6ee6297afb882062 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMD.cpp @@ -201,6 +201,7 @@ void ConvertToMD::exec() { // initiate conversion and estimate amount of job to do size_t n_steps = this->m_Convertor->initialize(targWSDescr, m_OutWSWrapper, ignoreZeros); + // copy the metadata, necessary for resolution corrections copyMetaData(spws); @@ -211,6 +212,9 @@ void ConvertToMD::exec() { // DO THE JOB: this->m_Convertor->runConversion(m_Progress.get()); + // Set the normalization of the event workspace + m_Convertor->setDisplayNormalization(spws, m_InWS2D); + // JOB COMPLETED: setProperty("OutputWorkspace", boost::dynamic_pointer_cast<IMDEventWorkspace>(spws)); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/DisplayNormalizationSetter.cpp b/Code/Mantid/Framework/MDAlgorithms/src/DisplayNormalizationSetter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f37defafba617216c6e343c70641a639ce9fa35 --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/src/DisplayNormalizationSetter.cpp @@ -0,0 +1,96 @@ +#include "MantidMDAlgorithms/DisplayNormalizationSetter.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidDataObjects/EventWorkspace.h" +#include "MantidAPI/IMDEventWorkspace.h" + +namespace Mantid { +namespace MDAlgorithms { + +/** + * Sets the display normalization + * @param mdWorkspace: the MDWorkspace which needs its normalizations flags set + * @param underlyingWorkspace: the underlying workspace, ie EventWorkspace or + * Workspace2D + * @param isQ: if the transform is Q or not + * @param mode: the energy transfer mode + */ +void DisplayNormalizationSetter:: +operator()(Mantid::API::IMDWorkspace_sptr mdWorkspace, + const Mantid::API::MatrixWorkspace_sptr &underlyingWorkspace, + bool isQ, const Mantid::Kernel::DeltaEMode::Type &mode) { + if (boost::dynamic_pointer_cast<Mantid::API::IMDEventWorkspace>( + mdWorkspace)) { + setNormalizationMDEvent(mdWorkspace, underlyingWorkspace, isQ, mode); + } else { + throw std::runtime_error("Setting the display normaliztion is currently " + "only implemented for MDEvent Workspaces"); + } +} + +/** + * Sets the display normalization for MDEventWorkspaces + * @param mdWorkspace: the MDWorkspace which needs its normalizations flags set + * @param underlyingWorkspace: the underlying workspace, ie EventWorkspace or + * Workspace2D + * @param isQ: if the transform is Q or not + * @param mode: the energy transfer mode + */ +void DisplayNormalizationSetter::setNormalizationMDEvent( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + const Mantid::API::MatrixWorkspace_sptr &underlyingWorkspace, bool isQ, + const Mantid::Kernel::DeltaEMode::Type &mode) { + auto isEventWorkspace = true; + if (boost::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>( + underlyingWorkspace)) { + isEventWorkspace = true; + } else { + isEventWorkspace = false; + } + + Mantid::API::MDNormalization displayNormalization( + Mantid::API::MDNormalization::VolumeNormalization); + Mantid::API::MDNormalization displayNormalizationHisto( + Mantid::API::MDNormalization::VolumeNormalization); + + // If is not Q + if (!isQ) { + displayNormalizationHisto = + Mantid::API::MDNormalization::VolumeNormalization; + // 2. If Energy mode is elastic --> Volume Normalization + } else if (mode == Mantid::Kernel::DeltaEMode::Elastic) { + displayNormalizationHisto = + Mantid::API::MDNormalization::VolumeNormalization; + // 3. If Energy is inelastic and underlying workspace is event workspace --> + // use no normalization + } else if (isEventWorkspace) { + displayNormalizationHisto = Mantid::API::MDNormalization::NoNormalization; + // 4. If Eneregy is inelastic and underlying workspace is other workspace + // --> use num event normalization + } else { + displayNormalizationHisto = + Mantid::API::MDNormalization::NumEventsNormalization; + } + + applyNormalizationMDEvent(mdWorkspace, displayNormalization, + displayNormalizationHisto); +} + +/** + * Apply the normalization to an MDEvent Workspace + * @param mdWorkspace: the workspace which gets its normalization tags set + * @param displayNormalization: the display normalization for the MDEvent + * workspace + * @param displayNormalizationHisto: the display normalization for derived + * MDHisto workspaces + */ +void DisplayNormalizationSetter::applyNormalizationMDEvent( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MDNormalization displayNormalization, + Mantid::API::MDNormalization displayNormalizationHisto) { + auto ws = + boost::dynamic_pointer_cast<Mantid::API::IMDEventWorkspace>(mdWorkspace); + ws->setDisplayNormalization(displayNormalization); + ws->setDisplayNormalizationHisto(displayNormalizationHisto); +} +} +} diff --git a/Code/Mantid/Framework/MDAlgorithms/src/FindPeaksMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/FindPeaksMD.cpp index 3b9f23511d2ca3f07f4579af06dccdc0530223cb..8752d9bbf4cf0659b2d62e2827a6dde7f21450f5 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/FindPeaksMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/FindPeaksMD.cpp @@ -412,7 +412,11 @@ void FindPeaksMD::findPeaks(typename MDEventWorkspace<MDE, nd>::sptr ws) { } addDetectors(*p, *mdBox); } - if (p->getDetectorID() != -1) peakWS->addPeak(*p); + if (p->getDetectorID() != -1) { + peakWS->addPeak(*p); + g_log.information() << "Add new peak with Q-center = " << Q[0] << ", " + << Q[1] << ", " << Q[2] << "\n"; + } } catch (std::exception &e) { g_log.notice() << "Error creating peak at " << Q << " because of '" << e.what() << "'. Peak will be skipped." << std::endl; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/IntegrateMDHistoWorkspace.cpp b/Code/Mantid/Framework/MDAlgorithms/src/IntegrateMDHistoWorkspace.cpp index d8b7faabba3636648d640aa24fbca08801e4e0fa..ef8bef02e8ffdc6768bc5dfcc5d20422b00eb6b5 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/IntegrateMDHistoWorkspace.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/IntegrateMDHistoWorkspace.cpp @@ -88,6 +88,84 @@ std::string checkBinning(const std::vector<double> &binning) { return error; } + +/** + * Provide a precision correction for Mantid coordinates + * @param position: a position + * @returns: a precision corrected position or the original position + */ +Mantid::coord_t getPrecisionCorrectedCoordinate(Mantid::coord_t position, Mantid::coord_t binWidth) { + // Find the closest integer value + const auto up = std::ceil(position); + const auto down = std::floor(position); + const auto diffUp = fabs(up - position); + const auto diffDown = fabs(down - position); + const auto nearest = diffUp < diffDown ? up : down; + + // Check if the relative deviation is larger than 1e-6 + const auto deviation = fabs((nearest - position)/binWidth); + const auto tolerance = 1e-6; + Mantid::coord_t coordinate(position); + if (deviation < tolerance) { + coordinate = nearest; + } + return coordinate; +} + +/** + * Sets the min, max and number of bins + * @param pMin: set minimum value passed by reference + * @param pMax: set maximum value passed by reference + * @param numberOfBins: the number of bins passed by reference + * @param dimension: the dimension information + * @param logger: a logger object + */ +void setMinMaxBins(Mantid::coord_t &pMin, Mantid::coord_t &pMax, + size_t &numberOfBins, + const IMDDimension_const_sptr &dimension,Logger& logger) { + // Get workspace extents + const Mantid::coord_t width = dimension->getBinWidth(); + const Mantid::coord_t max = dimension->getMaximum(); + + // Get offset between origin and next bin boundary towards the max value + // NOTE: GCC shows a conversion warning from double to float here. This + // is incorrect. Silence warning with explicit cast. + const Mantid::coord_t offset = static_cast<Mantid::coord_t>(fmod(max,width)); + + // Create the shifted pMax and pMin + auto minBin = (pMin - offset) / width; + auto maxBin = (pMax - offset) / width; + + // Make sure that we don't snap to the wrong value + // because of the precision of floats (which coord_t is) + minBin = getPrecisionCorrectedCoordinate(minBin, width); + maxBin = getPrecisionCorrectedCoordinate(maxBin, width); + auto snappedPMin = width * std::floor(minBin); + auto snappedPMax = width * std::ceil(maxBin); + + // Shift the snappedPMax/snappedPMin values back + snappedPMax += offset; + snappedPMin += offset; + + if(pMin != snappedPMin) { + std::stringstream buffer; + buffer << "Rounding min from: " << pMin << " to the nearest whole width at: " << snappedPMin; + logger.warning(buffer.str()); + } + if(pMax != snappedPMax) { + std::stringstream buffer; + buffer << "Rounding max from: " << pMax << " to the nearest whole width at: " << snappedPMax; + logger.warning(buffer.str()); + } + + pMin = snappedPMin; + pMax = snappedPMax; + + // Bins + numberOfBins = static_cast<size_t>((pMax-pMin)/width+0.5); // round up to a whole number of bins. +} +} + /** * Create the output workspace in the right shape. * @param inWS : Input workspace for dimensionality @@ -114,29 +192,16 @@ createShapedOutput(IMDHistoWorkspace const *const inWS, binning.back()) /*max*/); // Set custom min, max and nbins. } else if( i < pbins.size() && similarBinning(pbins[i]) ) { auto binning = pbins[i]; - const double width = inDim->getBinWidth(); // Take the width from the input dimension - double min = binning.front(); - double max = binning.back(); - - // Correct users, input, output and rounded to the nearest whole width. - min = width * std::floor(min/width); // Rounded down - max = width * std::ceil(max/width); // Rounded up - - if(min != binning.front()) { - std::stringstream buffer; - buffer << "Rounding min from: " << binning.front() << " to the nearest whole width at: " << min; - logger.warning(buffer.str()); - } - if(max != binning.back()) { - std::stringstream buffer; - buffer << "Rounding max from: " << binning.back() << " to the nearest whole width at: " << max; - logger.warning(buffer.str()); - } - const size_t roundedNBins = static_cast<size_t>((max-min)/width+0.5); // round up to a whole number of bins. + Mantid::coord_t pMin = static_cast<Mantid::coord_t>(binning.front()); + Mantid::coord_t pMax = static_cast<Mantid::coord_t>(binning.back()); + size_t numberOfBins; + + setMinMaxBins(pMin, pMax, numberOfBins, inDim, logger); + outDim->setRange( - roundedNBins, - static_cast<Mantid::coord_t>(min) /*min*/, - static_cast<Mantid::coord_t>(max) /*max*/); // Set custom min, max and nbins. + numberOfBins, + static_cast<Mantid::coord_t>(pMin) /*min*/, + static_cast<Mantid::coord_t>(pMax) /*max*/); // Set custom min, max and nbins. } dimensions[i] = outDim; } @@ -161,7 +226,7 @@ void performWeightedSum(MDHistoWorkspaceIterator const *const iterator, sumSQErrors += weight * (error * error); sumNEvents += weight * double(iterator->getNumEventsFraction()); } -} + namespace Mantid { namespace MDAlgorithms { @@ -329,7 +394,6 @@ void IntegrateMDHistoWorkspace::exec() { rather than iterating over the full set of boxes of the input workspace. */ inIterator->jumpToNearest(outIteratorCenter); - performWeightedSum(inIterator.get(), box, sumSignal, sumSQErrors, sumNEvents); // Use the present position. neighbours // below exclude the current position. @@ -353,6 +417,7 @@ void IntegrateMDHistoWorkspace::exec() { PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION + outWS->setDisplayNormalization(inWS->displayNormalizationHisto()); this->setProperty("OutputWorkspace", outWS); } } diff --git a/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp index 0964094126fe42e732b40326338a18df155ba529..ab06f177b58d87733d622f01f449d060f5399ed2 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp @@ -162,6 +162,7 @@ void LoadMD::exec() { // Open the entry m_file->openGroup(entryName, "NXentry"); + const std::map<std::string, std::string> levelEntries = m_file->getEntries(); // Check is SaveMD version 2 was used m_saveMDVersion = 0; @@ -187,14 +188,29 @@ void LoadMD::exec() { // Coordinate system this->loadCoordinateSystem(); + // Display normalization settting + if(levelEntries.find(VISUAL_NORMALIZATION_KEY) != levelEntries.end()){ + this->loadVisualNormalization(VISUAL_NORMALIZATION_KEY, m_visualNormalization); + } + if (entryName == "MDEventWorkspace") { // The type of event std::string eventType; m_file->getAttr("event_type", eventType); + if(levelEntries.find(VISUAL_NORMALIZATION_KEY_HISTO) != levelEntries.end()){ + this->loadVisualNormalization(VISUAL_NORMALIZATION_KEY_HISTO, m_visualNormalizationHisto); + } + // Use the factory to make the workspace of the right type - IMDEventWorkspace_sptr ws = - MDEventFactory::CreateMDWorkspace(m_numDims, eventType); + IMDEventWorkspace_sptr ws; + if (m_visualNormalizationHisto && m_visualNormalization) { + ws = MDEventFactory::CreateMDWorkspace(m_numDims, eventType, + m_visualNormalization.get(), + m_visualNormalizationHisto.get()); + } else { + ws = MDEventFactory::CreateMDWorkspace(m_numDims, eventType); + } // Now the ExperimentInfo bool lazyLoadExpt = fileBacked; @@ -253,7 +269,13 @@ void LoadMD::loadSlab(std::string name, void *data, MDHistoWorkspace_sptr ws, */ void LoadMD::loadHisto() { // Create the initial MDHisto. - MDHistoWorkspace_sptr ws(new MDHistoWorkspace(m_dims)); + MDHistoWorkspace_sptr ws; + // If display normalization has been provided. Use that. + if(m_visualNormalization){ + ws = boost::make_shared<MDHistoWorkspace>(m_dims, m_visualNormalization.get()); + } else { + ws = boost::make_shared<MDHistoWorkspace>(m_dims); // Whatever MDHistoWorkspace defaults to. + } // Now the ExperimentInfo MDBoxFlatTree::loadExperimentInfos(m_file.get(), m_filename, ws); @@ -339,6 +361,19 @@ void LoadMD::loadDimensions2() { m_file->closeGroup(); } +void LoadMD::loadVisualNormalization(const std::string& key, boost::optional<Mantid::API::MDNormalization>& normalization) { + try { + uint32_t readVisualNormalization(0); + m_file->readData(key, readVisualNormalization); + normalization = + static_cast<Mantid::API::MDNormalization>(readVisualNormalization); + } catch (::NeXus::Exception &) { + + } catch (std::exception &) { + } +} + + /** Load the coordinate system **/ void LoadMD::loadCoordinateSystem() { // Current version stores the coordinate system @@ -559,5 +594,8 @@ CoordTransform *LoadMD::loadAffineMatrix(std::string entry_name) { return transform; } +const std::string LoadMD::VISUAL_NORMALIZATION_KEY="visual_normalization"; +const std::string LoadMD::VISUAL_NORMALIZATION_KEY_HISTO="visual_normalization_histo"; + } // namespace Mantid } // namespace DataObjects diff --git a/Code/Mantid/Framework/MDAlgorithms/src/MDNormDirectSC.cpp b/Code/Mantid/Framework/MDAlgorithms/src/MDNormDirectSC.cpp index df1dcf13a34e8cef3773929f16f3cb0eeac7ef88..d4cab12b4a2f41081b5dbe6d3bd143d2608f0fa1 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/MDNormDirectSC.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/MDNormDirectSC.cpp @@ -122,6 +122,9 @@ void MDNormDirectSC::exec() { g_log.warning("Binning limits are outside the limits of the MDWorkspace. " "Not applying normalization."); } + + // Set the display normalization based on the input workspace + outputWS->setDisplayNormalization(m_inputWS->displayNormalizationHisto()); } /** diff --git a/Code/Mantid/Framework/MDAlgorithms/src/MDTransfModQ.cpp b/Code/Mantid/Framework/MDAlgorithms/src/MDTransfModQ.cpp index b140044fa9f7a92922187699f81f947d5c557a10..e6d03e9f8a2200b91e3e6616f8afa04a47149a8f 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/MDTransfModQ.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/MDTransfModQ.cpp @@ -1,6 +1,6 @@ #include "MantidMDAlgorithms/MDTransfModQ.h" #include "MantidKernel/RegistrationHelper.h" - +#include "MantidMDAlgorithms/DisplayNormalizationSetter.h" namespace Mantid { namespace MDAlgorithms { // register the class, whith conversion factory under ModQ name @@ -410,5 +410,19 @@ MDTransfModQ::MDTransfModQ() std::vector<std::string> MDTransfModQ::getEmodes() const { return Kernel::DeltaEMode::availableTypes(); } + +/** + * Set the display normalization for Q + * @param mdWorkspace: the md workspace + * @param underlyingWorkspace: the underlying workspace + */ +void MDTransfModQ::setDisplayNormalization( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const { + DisplayNormalizationSetter setter; + auto isQ = true; + setter(mdWorkspace, underlyingWorkspace, isQ, m_Emode); +} + } // End MDAlgorighms namespace } // End Mantid namespace diff --git a/Code/Mantid/Framework/MDAlgorithms/src/MDTransfNoQ.cpp b/Code/Mantid/Framework/MDAlgorithms/src/MDTransfNoQ.cpp index 930554319a853105e478d676e5497517e52b2e4e..95bd1de3ccd01171f8c53126ed6fe1b08d333feb 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/MDTransfNoQ.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/MDTransfNoQ.cpp @@ -1,4 +1,5 @@ #include "MantidMDAlgorithms/MDTransfNoQ.h" +#include "MantidMDAlgorithms/DisplayNormalizationSetter.h" // namespace Mantid { namespace MDAlgorithms { @@ -181,5 +182,18 @@ MDTransfNoQ::inputUnitID(Kernel::DeltaEMode::Type mode, MDTransfNoQ::MDTransfNoQ() : m_NMatrixDim(0), m_YAxis(NULL), m_Det(NULL){} +/** + * Set the display normalization for no Q + * @param mdWorkspace: the md workspace + * @param underlyingWorkspace: the underlying workspace + */ +void MDTransfNoQ::setDisplayNormalization( + Mantid::API::IMDWorkspace_sptr mdWorkspace, + Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const { + DisplayNormalizationSetter setter; + auto isQ = false; + setter(mdWorkspace, underlyingWorkspace, isQ); +} + } // End MDAlgorighms namespace } // End Mantid namespace diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SaveMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SaveMD.cpp index 2a16afdc07de8a922d624643050d3846e03ada08..18c6cd62bf20adbd2555aaf8e13e5032c4853a49 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SaveMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SaveMD.cpp @@ -241,6 +241,10 @@ void SaveMD::doSaveHisto(Mantid::DataObjects::MDHistoWorkspace_sptr ws) { file->writeData("coordinate_system", static_cast<uint32_t>(ws->getSpecialCoordinateSystem())); + // Write out the set display normalization + file->writeData("visual_normalization", + static_cast<uint32_t>(ws->displayNormalization())); + // Save the algorithm history under "process" ws->getHistory().saveNexus(file); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SaveMD2.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SaveMD2.cpp index 52dc7428df7aa47662828c563267a511999ec936..51a408bcc53d858d9c9c7ab12db2a46c7a3fc708 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SaveMD2.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SaveMD2.cpp @@ -107,6 +107,10 @@ void SaveMD2::doSaveHisto(Mantid::DataObjects::MDHistoWorkspace_sptr ws) { file->writeData("coordinate_system", static_cast<uint32_t>(ws->getSpecialCoordinateSystem())); + // Write out the visual normalization + file->writeData("visual_normalization", + static_cast<uint32_t>(ws->displayNormalization())); + // Save the algorithm history under "process" ws->getHistory().saveNexus(file); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SliceMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SliceMD.cpp index ba99b4778f9be5073d0c9c815e38566392df9de9..04cce85346c22cdbb41114dd83013bda81cc98fd 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SliceMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SliceMD.cpp @@ -280,10 +280,15 @@ void SliceMD::slice(typename MDEventWorkspace<MDE, nd>::sptr ws) { alg->setProperty("InputWorkspace", outWS); alg->executeAsChildAlg(); } + + // Pass on the display normalization from the input event workspace to the output event workspace + IMDEventWorkspace_sptr outEvent = boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS); + outEvent->setDisplayNormalization(ws->displayNormalization()); + outEvent->setDisplayNormalizationHisto(ws->displayNormalizationHisto()); // return the size of the input workspace write buffer to its initial value // bc->setCacheParameters(sizeof(MDE),writeBufSize); this->setProperty("OutputWorkspace", - boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS)); + outEvent); delete prog; } diff --git a/Code/Mantid/Framework/MDAlgorithms/test/BinMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/BinMDTest.h index 68385b6595606a0f28832fda6abc7632189186a6..9ef2827472803f9c68511b4bf255f7cdb53f087c 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/BinMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/BinMDTest.h @@ -128,6 +128,10 @@ public: IMDEventWorkspace_sptr in_ws = MDEventsTestHelper::makeMDEW<3>(10, 0.0, 10.0, numEventsPerBox); Mantid::Kernel::SpecialCoordinateSystem appliedCoord = Mantid::Kernel::QSample; in_ws->setCoordinateSystem(appliedCoord); + auto eventNorm = Mantid::API::MDNormalization::VolumeNormalization; + auto histoNorm = Mantid::API::MDNormalization::NumEventsNormalization; + in_ws->setDisplayNormalization(eventNorm); + in_ws->setDisplayNormalizationHisto(histoNorm); AnalysisDataService::Instance().addOrReplace("BinMDTest_ws", in_ws); // 1000 boxes with 1 event each @@ -179,7 +183,7 @@ public: TS_ASSERT(ctFrom); // Experiment Infos were copied TS_ASSERT_EQUALS( out->getNumExperimentInfo(), in_ws->getNumExperimentInfo()); - + TSM_ASSERT_EQUALS("Should have num events normalization", out->displayNormalization(), histoNorm); AnalysisDataService::Instance().remove("BinMDTest_ws"); } diff --git a/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h b/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h index 3a574ae1b35d53d3c43e1ff0a73d5865790b585c..549ce6506f667b17ab1decf915d5668d597c222f 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/ConvertCWSDExpToMomentumTest.h @@ -8,6 +8,7 @@ #include "MantidAPI/TableRow.h" #include "MantidDataObjects/TableWorkspace.h" #include "MantidAPI/IMDIterator.h" +#include "MantidGeometry/Instrument/ComponentHelper.h" using Mantid::MDAlgorithms::ConvertCWSDExpToMomentum; using namespace Mantid; @@ -40,6 +41,7 @@ public: testalg.initialize(); testalg.setProperty("InputWorkspace", "DataFileTable"); + testalg.setProperty("CreateVirtualInstrument", true); testalg.setProperty("DetectorTableWorkspace", "DetectorTable"); testalg.setProperty("SourcePosition", m_sourcePos); testalg.setProperty("SamplePosition", m_samplePos); @@ -68,7 +70,37 @@ public: return; } + void test_CopyInstrument() { + // Init and set up + ConvertCWSDExpToMomentum testalg; + testalg.initialize(); + testalg.setProperty("InputWorkspace", "DataFileTable"); + testalg.setProperty("CreateVirtualInstrument", false); + testalg.setProperty("OutputWorkspace", "QSampleMDEvents"); + testalg.setProperty("IsBaseName", false); + testalg.setProperty("Directory", "."); + + testalg.execute(); + TS_ASSERT(testalg.isExecuted()); + + API::IMDEventWorkspace_sptr outws = + boost::dynamic_pointer_cast<IMDEventWorkspace>( + AnalysisDataService::Instance().retrieve("QSampleMDEvents")); + TS_ASSERT(outws); + + IMDIterator *mditer = outws->createIterator(); + TS_ASSERT_EQUALS(mditer->getNumEvents(), 7400); + + size_t numexpinfo = outws->getNumExperimentInfo(); + TS_ASSERT_EQUALS(numexpinfo, 1); + + ExperimentInfo_const_sptr expinfo0 = outws->getExperimentInfo(0); + Geometry::Instrument_const_sptr instrument = expinfo0->getInstrument(); + TS_ASSERT_EQUALS(instrument->getNumberDetectors(), 256 * 256); + + return; + } private: API::ITableWorkspace_sptr m_dataTableWS; @@ -77,6 +109,32 @@ private: std::vector<double> m_samplePos; std::vector<double> m_pixelDimension; + Geometry::Instrument_sptr createInstrument() { + // Create a virtual instrument + std::vector<Kernel::V3D> vec_detpos; + std::vector<detid_t> vec_detid; + Kernel::V3D sourcePos(0., 0., -2.); + Kernel::V3D samplePos(0., 0., 0.); + + for (size_t i = 0; i < 256; ++i) { + double x = 0.38 + static_cast<double>(i - 128) * 0.001; + double y = 0; + double z = 0.38 + static_cast<double>(i - 128) * 0.001; + Kernel::V3D pos(x, y, z); + detid_t detid = static_cast<detid_t>(i) + 1; + + vec_detid.push_back(detid); + vec_detpos.push_back(pos); + } + + Geometry::Instrument_sptr virtualInstrument = + Geometry::ComponentHelper::createVirtualInstrument( + sourcePos, samplePos, vec_detpos, vec_detid); + TS_ASSERT(virtualInstrument); + + return virtualInstrument; + } + void generateTestInputs() { // Create data table @@ -90,20 +148,21 @@ private: m_dataTableWS = boost::dynamic_pointer_cast<ITableWorkspace>(datatable); TS_ASSERT(m_dataTableWS); - // Create detector table DataObjects::TableWorkspace_sptr dettable = boost::make_shared<DataObjects::TableWorkspace>(); dettable->addColumn("int", "DetID"); dettable->addColumn("double", "X"); dettable->addColumn("double", "Y"); dettable->addColumn("double", "Z"); + dettable->addColumn("int", "OriginalDetID"); for (size_t i = 0; i < 256; ++i) { TableRow detrow = dettable->appendRow(); double x = 0.38+static_cast<double>(i-128)*0.001; double y = 0; double z = 0.38+static_cast<double>(i-128)*0.001; - detrow << static_cast<int>(i) + 1 << x << y << z; + int detid = static_cast<int>(i) + 1; + detrow << detid << x << y << z << detid; } m_detectorTableWS = boost::dynamic_pointer_cast<ITableWorkspace>(dettable); diff --git a/Code/Mantid/Framework/MDAlgorithms/test/ConvertToMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/ConvertToMDTest.h index 77dbf2f7b62f04fab92957fe92c6d988d363585c..74334b44404f13306e7741f57f95879f80849e66 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/ConvertToMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/ConvertToMDTest.h @@ -30,7 +30,6 @@ public: { m_InWS2D = InWS2D; } - }; // helper function to provide list of names to test: std::vector<std::string> dim_availible() @@ -106,6 +105,10 @@ void testExecNoQ() auto outWS = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>("WS3DNoQ"); TS_ASSERT_EQUALS(Mantid::Kernel::None, outWS->getSpecialCoordinateSystem()); + // Check that the display normalization is set correctly -- NoQ + TSM_ASSERT_EQUALS("Should be set to volume normalization", outWS->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to volume normalization", outWS->displayNormalizationHisto(), Mantid::API::VolumeNormalization); + AnalysisDataService::Instance().remove("WS3DNoQ"); } @@ -134,6 +137,10 @@ void testExecModQ() auto outWS = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>("WS3DmodQ"); TS_ASSERT_EQUALS(Mantid::Kernel::None, outWS->getSpecialCoordinateSystem()); + // Check that the display normalization is set correctly -- Q with Elasticevent + TSM_ASSERT_EQUALS("Should be set to volume normalization", outWS->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to volume normalization", outWS->displayNormalizationHisto(), Mantid::API::VolumeNormalization); + AnalysisDataService::Instance().remove("WS3DmodQ"); } @@ -154,7 +161,6 @@ void testExecQ3D() TS_ASSERT_THROWS_NOTHING(pAlg->setPropertyValue("dEAnalysisMode", "Direct")); pAlg->setPropertyValue("MinValues","-10,-10,-10, 0,-10,-10"); pAlg->setPropertyValue("MaxValues"," 10, 10, 10, 20, 40, 20"); - pAlg->setRethrows(false); pAlg->execute(); TSM_ASSERT("Should finish successfully",pAlg->isExecuted()); @@ -172,6 +178,9 @@ void testExecQ3D() TS_ASSERT_EQUALS(true, outWS->getDimension(2)->getMDUnits().isQUnit()); TS_ASSERT_EQUALS(false, outWS->getDimension(3)->getMDUnits().isQUnit()); + // Check that the display normalization is set correctly -- WS2D with inelastic and Q + TSM_ASSERT_EQUALS("Should be set to num events normalization", outWS->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to num events normalization", outWS->displayNormalizationHisto(), Mantid::API::NumEventsNormalization); AnalysisDataService::Instance().remove("WS5DQ3D"); } @@ -221,6 +230,10 @@ void testInitialSplittingEnabled() TSM_ASSERT_EQUALS("Should be set to 5", 5, boxController->getSplitInto(1)); TSM_ASSERT_EQUALS("Should be set to 5", 5, boxController->getSplitInto(2)); TSM_ASSERT_EQUALS("Should be set to 5", 5, boxController->getSplitInto(3)); + + // Check that the display normalization is set correctly -- EventWS with inelastic and Q + TSM_ASSERT_EQUALS("Should be set to num events normalization", outEventWS->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to num events normalization", outEventWS->displayNormalizationHisto(), Mantid::API::NoNormalization); } void testInitialSplittingDisabled() diff --git a/Code/Mantid/Framework/MDAlgorithms/test/CutMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/CutMDTest.h index ac87a7dba8fc07a436374030e4fb46d3950c957e..1f2b761e5ff76085f480859b03fa30766bfa1726 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/CutMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/CutMDTest.h @@ -20,12 +20,26 @@ using namespace Mantid::Kernel; namespace { const std::string sharedWSName = "__CutMDTest_dataWS"; +const Mantid::API::MDNormalization eventNorm = Mantid::API::MDNormalization::VolumeNormalization; +const Mantid::API::MDNormalization histoNorm = Mantid::API::MDNormalization::NumEventsNormalization; } class CutMDTest : public CxxTest::TestSuite { private: IMDWorkspace_sptr m_inWS; + void addNormalization(std::string wsName) { + auto ws = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>(wsName); + auto eventWS = boost::dynamic_pointer_cast<IMDEventWorkspace>(ws); + auto histoWS = boost::dynamic_pointer_cast<IMDHistoWorkspace>(ws); + if (eventWS) { + eventWS->setDisplayNormalization(eventNorm); + eventWS->setDisplayNormalizationHisto(histoNorm); + } else { + eventWS->setDisplayNormalization(histoNorm); + } + } + public: CutMDTest() { FrameworkManager::Instance().exec("CreateMDWorkspace", 10, @@ -54,6 +68,9 @@ public: m_inWS = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>(sharedWSName); + auto eventWS = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_inWS); + eventWS->setDisplayNormalization(eventNorm); + eventWS->setDisplayNormalizationHisto(histoNorm); } virtual ~CutMDTest() { AnalysisDataService::Instance().remove(sharedWSName); } @@ -82,7 +99,6 @@ public: FrameworkManager::Instance().exec("SetSpecialCoordinates", 4, "InputWorkspace", wsName.c_str(), "SpecialCoordinates", "HKL"); - auto algCutMD = FrameworkManager::Instance().createAlgorithm("CutMD"); algCutMD->initialize(); algCutMD->setRethrows(true); @@ -138,6 +154,9 @@ public: TS_ASSERT_EQUALS("[0, 'eta', 0]", outWS->getDimension(1)->getName()); TS_ASSERT_EQUALS("[0, 0, 'xi']", outWS->getDimension(2)->getName()); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); + AnalysisDataService::Instance().remove(wsName); } @@ -164,6 +183,9 @@ public: TS_ASSERT_DELTA(outWS->getDimension(0)->getMaximum(), 0.6, 1E-6); TS_ASSERT_EQUALS(outWS->getDimension(0)->getNBins(), 2); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); + AnalysisDataService::Instance().remove(wsName); } @@ -189,6 +211,9 @@ public: TS_ASSERT_EQUALS(outWS->getDimension(0)->getNBins(), 1); TS_ASSERT_EQUALS(outWS->getDimension(1)->getNBins(), 1); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); + AnalysisDataService::Instance().remove(wsName); } @@ -224,6 +249,8 @@ public: vRow << "v" << V3D(0,1,0) << 0.0 << "r"; wRow << "w" << V3D(0,0,1) << 0.0 << "r"; + addNormalization(wsName); + auto algCutMD = FrameworkManager::Instance().createAlgorithm("CutMD"); algCutMD->initialize(); algCutMD->setRethrows(true); @@ -251,6 +278,9 @@ public: TS_ASSERT_EQUALS("[0, 'eta', 0]", outWS->getDimension(1)->getName()); TS_ASSERT_EQUALS("[0, 0, 'xi']", outWS->getDimension(2)->getName()); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); + AnalysisDataService::Instance().remove(wsName); } @@ -286,6 +316,8 @@ public: vRow << "v" << V3D(-1,1,0) << 0.0 << "r"; wRow << "w" << V3D(0,0,1) << 0.0 << "r"; + addNormalization(wsName); + auto algCutMD = FrameworkManager::Instance().createAlgorithm("CutMD"); algCutMD->initialize(); algCutMD->setRethrows(true); @@ -313,6 +345,9 @@ public: TS_ASSERT_EQUALS("['-eta', 'eta', 0]", outWS->getDimension(1)->getName()); TS_ASSERT_EQUALS("[0, 0, 'xi']", outWS->getDimension(2)->getName()); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); + AnalysisDataService::Instance().remove(wsName); } @@ -348,6 +383,8 @@ public: vRow << "v" << V3D(0,1,0) << 0.0 << "r"; wRow << "w" << V3D(0,0,1) << 0.0 << "r"; + addNormalization(wsName); + auto algCutMD = FrameworkManager::Instance().createAlgorithm("CutMD"); algCutMD->initialize(); algCutMD->setRethrows(true); @@ -375,6 +412,8 @@ public: TS_ASSERT_EQUALS("[0, 'eta', 0]", outWS->getDimension(1)->getName()); TS_ASSERT_EQUALS("[0, 0, 'xi']", outWS->getDimension(2)->getName()); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); AnalysisDataService::Instance().remove(wsName); } @@ -398,6 +437,8 @@ public: "InputWorkspace", wsName.c_str(), "SpecialCoordinates", "HKL"); + addNormalization(wsName); + auto algCutMD = FrameworkManager::Instance().createAlgorithm("CutMD"); algCutMD->initialize(); algCutMD->setRethrows(true); @@ -439,6 +480,8 @@ public: AnalysisDataService::Instance().retrieveWS<IMDHistoWorkspace>(wsOutName); TS_ASSERT_EQUALS(16, outWS->getDimension(3)->getNBins()); + TSM_ASSERT_EQUALS("Should have num events normalization", + outWS->displayNormalizationHisto(), histoNorm); AnalysisDataService::Instance().remove(wsName); AnalysisDataService::Instance().remove(wsOutName); } diff --git a/Code/Mantid/Framework/MDAlgorithms/test/DisplayNormalizationSetterTest.h b/Code/Mantid/Framework/MDAlgorithms/test/DisplayNormalizationSetterTest.h new file mode 100644 index 0000000000000000000000000000000000000000..7f32e0bd7ab2aa8a9260d08640d1f83b1490ed26 --- /dev/null +++ b/Code/Mantid/Framework/MDAlgorithms/test/DisplayNormalizationSetterTest.h @@ -0,0 +1,88 @@ +#ifndef MANTID_MDALGORITHMS_DISPLAYNORMALIZATIONSETTERTEST_H_ +#define MANTID_MDALGORITHMS_DISPLAYNORMALIZATIONSETTERTEST_H_ + +#include <cxxtest/TestSuite.h> +#include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidTestHelpers/MDEventsTestHelper.h" +#include "MantidKernel/DeltaEMode.h" +#include "MantidMDAlgorithms/DisplayNormalizationSetter.h" +#include "boost/pointer_cast.hpp" +using namespace Mantid::MDAlgorithms; + +class DisplayNormalizationSetterTest : public CxxTest::TestSuite { +public: + void test_that_MDHistoWorkspace_throws_exception() { + // Arrange + auto isQ = true; + auto eventWorkspace = + WorkspaceCreationHelper::CreateEventWorkspace2(10, 10); + auto mdHistoWorkspace = + Mantid::DataObjects::MDEventsTestHelper::makeFakeMDHistoWorkspace( + 1.0, 1, 10); + auto emode = Mantid::Kernel::DeltaEMode::Direct; + Mantid::MDAlgorithms::DisplayNormalizationSetter setter; + // Act + Assert + TSM_ASSERT_THROWS("Should throw for MDHistoWorkspace", + setter(mdHistoWorkspace, eventWorkspace, isQ, emode), + std::runtime_error &); + } + + void test_that_direct_energy_mode_creates_a_volume_normalization() { + // Arrange + auto isQ = true; + auto eventWorkspace = + WorkspaceCreationHelper::CreateEventWorkspace2(10, 10); + auto mdEventWorkspace = Mantid::DataObjects::MDEventsTestHelper::makeMDEW<3>(4, 0.0, 4.0, 1); + auto emode = Mantid::Kernel::DeltaEMode::Elastic; + Mantid::MDAlgorithms::DisplayNormalizationSetter setter; + // Act + setter(mdEventWorkspace, eventWorkspace, isQ, emode); + // Assert + TSM_ASSERT_EQUALS("Should be set to volume normalization", mdEventWorkspace->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to volume normalization", mdEventWorkspace->displayNormalizationHisto(), Mantid::API::VolumeNormalization); + } + + void test_that_indirect_energy_mode_with_an_input_event_workspace_creates_no_normalization() { + // Arrange + auto isQ = true; + auto eventWorkspace = WorkspaceCreationHelper::CreateEventWorkspace2(10, 10); + auto mdEventWorkspace = Mantid::DataObjects::MDEventsTestHelper::makeMDEW<3>(4, 0.0, 4.0, 1); + auto emode = Mantid::Kernel::DeltaEMode::Direct; + Mantid::MDAlgorithms::DisplayNormalizationSetter setter; + // Act + setter(mdEventWorkspace, eventWorkspace, isQ, emode); + // Assert + TSM_ASSERT_EQUALS("Should be set to no normalization", mdEventWorkspace->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to no normalization", mdEventWorkspace->displayNormalizationHisto(), Mantid::API::NoNormalization); + } + + void test_that_indirect_energy_mode_with_input_workspace2D_creates_num_event_normalization() { + // Arrange + auto isQ = true; + auto histoWorkspace = WorkspaceCreationHelper::Create2DWorkspace123(2,2); + auto mdEventWorkspace = Mantid::DataObjects::MDEventsTestHelper::makeMDEW<3>(4, 0.0, 4.0, 1); + auto emode = Mantid::Kernel::DeltaEMode::Direct; + Mantid::MDAlgorithms::DisplayNormalizationSetter setter; + // Act + setter(mdEventWorkspace, histoWorkspace, isQ, emode); + // Assert + TSM_ASSERT_EQUALS("Should be set to number events normalization", mdEventWorkspace->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to number events normalization", mdEventWorkspace->displayNormalizationHisto(), Mantid::API::NumEventsNormalization); + } + + void test_that_non_Q_creates_volume_normalization() { + // Arrange + auto isQ = false; + auto histoWorkspace = WorkspaceCreationHelper::Create2DWorkspace123(2,2); + auto mdEventWorkspace = Mantid::DataObjects::MDEventsTestHelper::makeMDEW<3>(4, 0.0, 4.0, 1); + auto emode = Mantid::Kernel::DeltaEMode::Direct; + Mantid::MDAlgorithms::DisplayNormalizationSetter setter; + // Act + setter(mdEventWorkspace, histoWorkspace, isQ, emode); + // Assert + TSM_ASSERT_EQUALS("Should be set to number volume normalization", mdEventWorkspace->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to number volume normalization", mdEventWorkspace->displayNormalizationHisto(), Mantid::API::VolumeNormalization); + } +}; + +#endif \ No newline at end of file diff --git a/Code/Mantid/Framework/MDAlgorithms/test/IntegrateMDHistoWorkspaceTest.h b/Code/Mantid/Framework/MDAlgorithms/test/IntegrateMDHistoWorkspaceTest.h index 54ad6af8eea1365dde91df51054c36150082432f..d085a291d65c57e00308d84ebcd4e56f0b57c466 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/IntegrateMDHistoWorkspaceTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/IntegrateMDHistoWorkspaceTest.h @@ -7,10 +7,22 @@ #include "MantidMDAlgorithms/IntegrateMDHistoWorkspace.h" #include "MantidDataObjects/MDEventWorkspace.h" #include "MantidTestHelpers/MDEventsTestHelper.h" - using Mantid::MDAlgorithms::IntegrateMDHistoWorkspace; using namespace Mantid::API; +namespace { + +// This helper sets the signal values to the linear index to have some +// variety +void resetSignalsToLinearIndexValue(IMDHistoWorkspace_sptr ws) { + auto numberOfIndices = static_cast<size_t>(ws->getNPoints()); + for (size_t i = 0; i < numberOfIndices; ++i) { + auto& signal = ws->signalAt(i); + signal = static_cast<Mantid::signal_t>(i); + } +} +} + //===================================================================================== // Functional Tests //===================================================================================== @@ -107,12 +119,14 @@ public: TSM_ASSERT_THROWS("Step has been specified", alg.execute(), std::runtime_error&); } + // Users may set all binning parameter to [] i.e. direct copy, no integration. void test_exec_do_nothing_but_clone() { using namespace Mantid::DataObjects; MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 1 /*nd*/, 10); - + auto histNorm = Mantid::API::MDNormalization::NumEventsNormalization; + ws->setDisplayNormalization(histNorm); IntegrateMDHistoWorkspace alg; alg.setChild(true); alg.setRethrows(true); @@ -127,6 +141,7 @@ public: TS_ASSERT_EQUALS(outWS->getNumDims(), ws->getNumDims()); TS_ASSERT_EQUALS(outWS->getSignalAt(0), ws->getSignalAt(0)); TS_ASSERT_EQUALS(outWS->getSignalAt(1), ws->getSignalAt(1)); + TSM_ASSERT_EQUALS("Should have a num events normalization", outWS->displayNormalization(), histNorm); } void test_1D_integration_exact_binning() @@ -147,6 +162,8 @@ public: using namespace Mantid::DataObjects; MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0 /*signal*/, 1 /*nd*/, 10 /*nbins*/, 10 /*max*/, 1.0 /*error sq*/); + auto histNorm = Mantid::API::MDNormalization::NumEventsNormalization; + ws->setDisplayNormalization(histNorm); IntegrateMDHistoWorkspace alg; alg.setChild(true); @@ -169,6 +186,7 @@ public: // Check the data. TSM_ASSERT_DELTA("Wrong integrated value", 5.0, outWS->getSignalAt(0), 1e-4); TSM_ASSERT_DELTA("Wrong error value", std::sqrt(5 * (ws->getErrorAt(0) * ws->getErrorAt(0))), outWS->getErrorAt(0), 1e-4); + TSM_ASSERT_EQUALS("Should have a num events normalization", outWS->displayNormalization(), histNorm); } @@ -392,6 +410,225 @@ public: } + //----------------------------------------------- + //Snapping Tests + //------------------------------------------------ + void test_that_PBin_on_boundaries_are_detected_for_asymmetric_workspace_with_no_bin_boundary_at_origin() { + /** + Input workspace: Is asymmetric about the origina and the origin does not lie on a bin boundary, but + the PMIN and PMAX boundaries lie on bin boundaries. + Bins: 6 + XMin: -2.4359 + XMAX: 2.1001 + + XMIN XMAX + | | + | | | | | | | + | | | + PMIN 0 PMAX + **/ + // Arrange + using namespace Mantid::DataObjects; + const size_t numDims = 1; + const double signal = 3.4; + const double errorSquared = 1.3; + size_t numBins[static_cast<int>(numDims)] = {6}; + Mantid::coord_t min[static_cast<int>(numDims)] = {-2.4359f}; + Mantid::coord_t max[static_cast<int>(numDims)] = {2.1001f}; + const std::string name("test"); + auto ws = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(numDims, signal, errorSquared, numBins, min, max, name); + const double pMin = -1.6799; + const double pMax = 1.3441; + resetSignalsToLinearIndexValue(ws); + + // Act + IntegrateMDHistoWorkspace alg; + alg.setChild(true); + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", ws); + alg.setProperty("P1Bin", boost::assign::list_of(pMin)(0.0)(pMax).convert_to_container<std::vector<double> >()); + alg.setPropertyValue("OutputWorkspace", "dummy"); + alg.execute(); + IMDHistoWorkspace_sptr outWS=alg.getProperty("OutputWorkspace"); + + // Assert + // At this point we need to take into account the precision of a float value + TSM_ASSERT_DELTA("Should have a lower bound set to exactly PMIN", outWS->getDimension(0)->getMinimum(), static_cast<Mantid::coord_t>(pMin), 1e-6); + TSM_ASSERT_DELTA("Should have an upper bound set to exactly PMAX", outWS->getDimension(0)->getMaximum(), static_cast<Mantid::coord_t>(pMax), 1e-6); + + // Confirm that the old workspace has signals of 0,1,2,3,4,5 + TSM_ASSERT_DELTA("Should have a signal value of 0", ws->getSignalAt(0), static_cast<Mantid::signal_t>(0.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 1", ws->getSignalAt(1), static_cast<Mantid::signal_t>(1.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 2", ws->getSignalAt(2), static_cast<Mantid::signal_t>(2.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 3", ws->getSignalAt(3), static_cast<Mantid::signal_t>(3.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 4", ws->getSignalAt(4), static_cast<Mantid::signal_t>(4.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 5", ws->getSignalAt(5), static_cast<Mantid::signal_t>(5.0), 1e-4); + + // We expect that the signals have not chagned. The first bin and the last bin of the original workspace were trimmed, hence + // we expect to have signal values of 1, 2, 3, 4 for the new workspace + TSM_ASSERT_DELTA("Should have a signal value of 1", outWS->getSignalAt(0), static_cast<Mantid::signal_t>(1.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 2", outWS->getSignalAt(1), static_cast<Mantid::signal_t>(2.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 3", outWS->getSignalAt(2), static_cast<Mantid::signal_t>(3.0), 1e-4); + TSM_ASSERT_DELTA("Should have a signal value of 4", outWS->getSignalAt(3), static_cast<Mantid::signal_t>(4.0), 1e-4); + } + + void test_that_PBin_between_extent_and_bin_boundary_floors_when_pmin_not_contained_in_threshold(){ + /* + Input workspace: Is asymmetric about the origina and the origin does not lie on a bin boundary and + the PMIN and PMAX do not lie on bin boundaries.PMin is defined to be at a greater distance than 1e-06 of a bin boundary + Bins: 3 + XMin: -1 + XMAX: 1 + + XMIN XMAX + | | + | | | | + | | | + PMIN 0 PMAX + + where 0-PMin > threshold (1e-06) + */ + using namespace Mantid::DataObjects; + const size_t numDims = 1; + const double signal = 3.5; + const double errorSquared = 1.2; + size_t numBins[static_cast<int>(numDims)] = {3}; + Mantid::coord_t min[static_cast<int>(numDims)]; + min[0] = -1.0f; + Mantid::coord_t max[static_cast<int>(numDims)]; + max[0] = 1.0f; + const std::string name("test"); + auto ws = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(numDims, signal, errorSquared, numBins, min, max, name); + const double secondBinBoundary = -(1.0f)/3; + const double pMin = secondBinBoundary - 0.1; //outside of threshold + const double pMax = 1.0; + + //Act + IntegrateMDHistoWorkspace alg; + alg.setChild(true); + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", ws); + alg.setProperty("P1Bin", boost::assign::list_of(pMin)(0.0)(pMax).convert_to_container<std::vector<double> >()); + alg.setPropertyValue("OutputWorkspace", "dummy"); + alg.execute(); + IMDHistoWorkspace_sptr outWS=alg.getProperty("OutputWorkspace"); + + //Assert + Mantid::coord_t minimumDim = outWS->getDimension(0)->getMinimum(); + Mantid::coord_t maximumDim = outWS->getDimension(0)->getMaximum(); + + std::cerr << std::setprecision(10) <<minimumDim << " " << std::setprecision(10)<< static_cast<Mantid::coord_t>(min[0]) << " " << std::setprecision(10)<< min[0] <<std::endl; + std::cerr << std::setprecision(10) <<maximumDim << " " << std::setprecision(10) << static_cast<Mantid::coord_t>(max[0]) << " " << std::setprecision(10) << max[0] <<std::endl; + + TSM_ASSERT_DELTA("Should snap to the second bin boundary.", minimumDim, static_cast<Mantid::coord_t>(min[0]), 1e-6); + TSM_ASSERT_DELTA("Should snap to the last bin boundary", maximumDim, static_cast<Mantid::coord_t>(max[0]), 1e-6); + } + void test_that_PBin_between_extent_and_bin_boundary_does_snap_to_boundary_within_threshold(){ + /* + Input workspace: Is asymmetric about the origina and the origin does not lie on a bin boundary and + the PMIN and PMAX do not lie on bin boundaries. PMin is defined to be within 1e-06 of a bin boundary + Bins: 3 + XMin: -1 + XMAX: 1 + + XMIN XMAX + | | + | | | | + | | | + PMIN 0 PMAX + where 0-PMin < threshold (1e-06) + */ + using namespace Mantid::DataObjects; + const size_t numDims = 1; + const double signal = 3.5; + const double errorSquared = 1.2; + size_t numBins[static_cast<int>(numDims)] = {3}; + Mantid::coord_t min[static_cast<int>(numDims)]; + min[0] = -1.0f; + Mantid::coord_t max[static_cast<int>(numDims)]; + max[0] = 1.0f; + const std::string name("test"); + auto ws = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(numDims, signal, errorSquared, numBins, min, max, name); + const double secondBinBoundary = -(1.0f)/3; + const double pMin = secondBinBoundary - (1e-7); //within threshold + const double pMax = 1.0; + + //Act + IntegrateMDHistoWorkspace alg; + alg.setChild(true); + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", ws); + alg.setProperty("P1Bin", boost::assign::list_of(pMin)(0.0)(pMax).convert_to_container<std::vector<double> >()); + alg.setPropertyValue("OutputWorkspace", "dummy"); + alg.execute(); + IMDHistoWorkspace_sptr outWS=alg.getProperty("OutputWorkspace"); + + //Assert + Mantid::coord_t minimumDim = outWS->getDimension(0)->getMinimum(); + Mantid::coord_t maximumDim = outWS->getDimension(0)->getMaximum(); + std::cerr << std::setprecision(10) <<minimumDim << " " << std::setprecision(10)<< static_cast<Mantid::coord_t>(secondBinBoundary) << " " << std::setprecision(10)<< secondBinBoundary <<std::endl; + std::cerr << std::setprecision(10) <<maximumDim << " " << std::setprecision(10) << static_cast<Mantid::coord_t>(max[0]) << " " << std::setprecision(10) << max[0] <<std::endl; + + TSM_ASSERT_DELTA("Should snap to the second bin boundary.", minimumDim, static_cast<Mantid::coord_t>(secondBinBoundary), 1e-6); + TSM_ASSERT_DELTA("Should snap to the last bin boundary", maximumDim, static_cast<Mantid::coord_t>(max[0]), 1e-6); + } + + void test_that_PBin_NOT_on_boundary_are_detected_for_asymmetric_workspace_with_no_bin_boundary_at_origin() { + /** + Input workspace: Is asymmetric about the origina and the origin does not lie on a bin boundary and + the PMIN and PMAX do not lie on bin boundaries. + Bins: 6 + XMin: -2.4359 + XMAX: 2.1001 + + XMIN XMAX + | | + | | | | | | | + | | | + PMIN 0 PMAX + **/ + // Arrange + using namespace Mantid::DataObjects; + const size_t numDims = 1; + const double signal = 3.4; + const double errorSquared = 1.3; + size_t numBins[static_cast<int>(numDims)] = {6}; + Mantid::coord_t min[static_cast<int>(numDims)]; + min[0] = -2.4359f; + Mantid::coord_t max[static_cast<int>(numDims)]; + max[0] = 2.1001f; + const std::string name("test"); + auto ws = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(numDims, signal, errorSquared, numBins, min, max, name); + const double secondBinBoundary = -1.6799; + const double pMin = secondBinBoundary + 0.16729; + const double pMax = 1.3441 + 0.08792; + + // Act + IntegrateMDHistoWorkspace alg; + alg.setChild(true); + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("InputWorkspace", ws); + alg.setProperty("P1Bin", boost::assign::list_of(pMin)(0.0)(pMax).convert_to_container<std::vector<double> >()); + alg.setPropertyValue("OutputWorkspace", "dummy"); + alg.execute(); + IMDHistoWorkspace_sptr outWS=alg.getProperty("OutputWorkspace"); + + // Assert + Mantid::coord_t minimumDim = outWS->getDimension(0)->getMinimum(); + Mantid::coord_t maximumDim = outWS->getDimension(0)->getMaximum(); + + TSM_ASSERT_DELTA("Should snap to the second bin boundary.", minimumDim, static_cast<Mantid::coord_t>(secondBinBoundary), 1e-6); + TSM_ASSERT_DELTA("Should snap to the last bin boundary", maximumDim, static_cast<Mantid::coord_t>(max[0]), 1e-6); + } + + void test_that_signals_of_workspace_shifted_by_half_a_bin_width_is_correct() { + + } + }; //===================================================================================== @@ -435,6 +672,9 @@ public: TS_ASSERT(outWS); } + + + }; #endif /* MANTID_MDALGORITHMS_INTEGRATEMDHISTOWORKSPACETEST_H_ */ diff --git a/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h index 3b92f1d1a0043f2f1b48546d332098aa513fedea..54346d1e7411b3500999f0d0ff10d64d2b3d5c2d 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h @@ -499,6 +499,7 @@ public: TS_ASSERT_EQUALS( ws->getNPoints(), newWS->getNPoints()); TS_ASSERT_EQUALS( ws->getNumDims(), newWS->getNumDims()); + TS_ASSERT_EQUALS( ws->displayNormalization(), newWS->displayNormalization()); for (size_t i=0; i<ws->getNPoints(); i++) { TS_ASSERT_DELTA(ws->getSignalAt(i), newWS->getSignalAt(i), 1e-6); @@ -539,6 +540,7 @@ public: TS_ASSERT_EQUALS( ws->getNPoints(), newWS->getNPoints()); TS_ASSERT_EQUALS( ws->getNumDims(), newWS->getNumDims()); + TS_ASSERT_EQUALS( ws->displayNormalization(), newWS->displayNormalization()); for (size_t i=0; i<ws->getNPoints(); i++) { TS_ASSERT_DELTA(ws->getSignalAt(i), newWS->getSignalAt(i), 1e-6); @@ -551,14 +553,25 @@ public: Poco::File(filename).remove(); } - void test_histo2() + void test_histo1D() + { + Mantid::coord_t min(-10.0); + Mantid::coord_t max(10.0); + std::vector<Geometry::IMDDimension_sptr> dims(1, boost::make_shared<Geometry::MDHistoDimension>("X", "x", "m", min, max, 5)); + MDHistoWorkspace_sptr ws = boost::make_shared<MDHistoWorkspace>(dims, API::VolumeNormalization); + ws->setTo(1.0, 1.0, 1); + doTestHistoV1(ws); + doTestHisto(ws); + } + + void test_histo2D() { MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.5, 2, 10, 10.0, 3.5, "histo2", 4.5); doTestHistoV1(ws); doTestHisto(ws); } - void test_histo3() + void test_histo3D() { MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.5, 3, 4, 10.0, 3.5, "histo3", 4.5); doTestHistoV1(ws); @@ -736,6 +749,50 @@ public: AnalysisDataService::Instance().remove("OutputWorkspace"); } + void test_MDEventWorkspace_contains_normalization_flags() { + // Arrange + std::string filename("SaveMDEventNormalizationFlagTest.nxs"); + MDEventWorkspace4Lean::sptr ws = MDEventsTestHelper::makeMDEW<4>(10, 0.0, 10.0, 2); + AnalysisDataService::Instance().addOrReplace("SaveMDEventNormalizationFlagTest_ws", ws); + + auto eventNormalization = Mantid::API::NoNormalization; + auto histoNormalization = Mantid::API::NumEventsNormalization; + ws->setDisplayNormalization(eventNormalization); + ws->setDisplayNormalizationHisto(histoNormalization); + + // Act + SaveMD2 alg; + alg.initialize(); + alg.setPropertyValue("InputWorkspace", "SaveMDEventNormalizationFlagTest_ws"); + alg.setPropertyValue("Filename", filename); + alg.setProperty("MakeFileBacked","0"); + alg.execute(); + TS_ASSERT( alg.isExecuted() ); + std::string this_filename = alg.getProperty("Filename"); + + LoadMD loadAlg; + loadAlg.initialize(); + loadAlg.isInitialized(); + loadAlg.setPropertyValue("Filename", filename); + loadAlg.setProperty("FileBackEnd", false); + loadAlg.setPropertyValue("OutputWorkspace", "reloaded_MDEventNormalization"); + loadAlg.execute(); + TS_ASSERT( loadAlg.isExecuted() ); + auto newWS = AnalysisDataService::Instance().retrieveWS<IMDEventWorkspace>("reloaded_MDEventNormalization"); + + // Assert + TSM_ASSERT_EQUALS("Should have no normalization set", newWS->displayNormalization(), eventNormalization); + TSM_ASSERT_EQUALS("Should have number events normalization set", newWS->displayNormalizationHisto(), histoNormalization); + + // Clean up + if (Poco::File(this_filename).exists()) + { + Poco::File(this_filename).remove(); + } + + AnalysisDataService::Instance().remove("SaveMDEventNormalizationFlagTest_ws"); + AnalysisDataService::Instance().remove("reloaded_MDEventNormalization"); + } }; #endif /* MANTID_MDEVENTS_LOADMDEWTEST_H_ */ diff --git a/Code/Mantid/Framework/MDAlgorithms/test/MDNormDirectSCTest.h b/Code/Mantid/Framework/MDAlgorithms/test/MDNormDirectSCTest.h index 2af9465dfc8b848414b47287eb1715fc9701f934..02e65af99359af41cf90670eb1b020473d9056e5 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/MDNormDirectSCTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/MDNormDirectSCTest.h @@ -20,7 +20,6 @@ public: static MDNormDirectSCTest *createSuite() { return new MDNormDirectSCTest(); } static void destroySuite( MDNormDirectSCTest *suite ) { delete suite; } - void test_Init() { MDNormDirectSC alg; diff --git a/Code/Mantid/Framework/MDAlgorithms/test/MDTransfModQTest.h b/Code/Mantid/Framework/MDAlgorithms/test/MDTransfModQTest.h index 3008ba1ca96a21dce7b5906406e5d2c25d2c5b02..c441ecda4f465e1e538e7027e504be4e59006bec 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/MDTransfModQTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/MDTransfModQTest.h @@ -4,6 +4,7 @@ #include "MantidMDAlgorithms/MDTransfQ3D.h" #include "MantidKernel/DeltaEMode.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidTestHelpers/MDEventsTestHelper.h" #include <cxxtest/TestSuite.h> @@ -187,10 +188,13 @@ public: TSM_ASSERT_EQUALS(convResult,0,convResult.size()); + // Check if the correct display normalization is set + auto mdEventWorkspace = Mantid::DataObjects::MDEventsTestHelper::makeMDEW<3>(4, 0.0, 4.0, 1); + ModQTransf.setDisplayNormalization(mdEventWorkspace, ws2Dbig); + TSM_ASSERT_EQUALS("Should be set to number events normalization", mdEventWorkspace->displayNormalization(), Mantid::API::VolumeNormalization); + TSM_ASSERT_EQUALS("Should be set to number events normalization", mdEventWorkspace->displayNormalizationHisto(), Mantid::API::NumEventsNormalization); } - - MDTransfModQTest() { diff --git a/Code/Mantid/Framework/MDAlgorithms/test/SaveMD2Test.h b/Code/Mantid/Framework/MDAlgorithms/test/SaveMD2Test.h index f482b9ddee328185ada20b7331330a0837ce9eb6..6696ec9e8e5f4dffeed04d14654930f63b8d5a40 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/SaveMD2Test.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/SaveMD2Test.h @@ -16,11 +16,10 @@ using namespace Mantid::API; using namespace Mantid::DataObjects; using namespace Mantid::MDAlgorithms; -class SaveMD2Tester: public SaveMD2 -{ +class SaveMD2Tester : public SaveMD2 { public: - void saveExperimentInfos(::NeXus::File * const file, IMDEventWorkspace_const_sptr ws) - { + void saveExperimentInfos(::NeXus::File *const file, + IMDEventWorkspace_const_sptr ws) { this->saveExperimentInfos(file, ws); } }; @@ -29,44 +28,30 @@ public: * for a more thorough test that does * a round-trip. */ -class SaveMD2Test : public CxxTest::TestSuite -{ +class SaveMD2Test : public CxxTest::TestSuite { public: - - - void test_Init() - { + void test_Init() { SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - } - - void test_exec() - { - do_test_exec(23, "SaveMD2Test.nxs"); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) } - void test_exec_noEvents() - { - do_test_exec(0, "SaveMD2Test_noEvents.nxs"); - } + void test_exec() { do_test_exec(23, "SaveMD2Test.nxs"); } - void test_MakeFileBacked() - { - do_test_exec(23, "SaveMD2Test.nxs", true); - } + void test_exec_noEvents() { do_test_exec(0, "SaveMD2Test_noEvents.nxs"); } + + void test_MakeFileBacked() { do_test_exec(23, "SaveMD2Test.nxs", true); } - void test_MakeFileBacked_then_UpdateFileBackEnd() - { + void test_MakeFileBacked_then_UpdateFileBackEnd() { do_test_exec(23, "SaveMD2Test_updating.nxs", true, true); } + void do_test_exec(size_t numPerBox, std::string filename, + bool MakeFileBacked = false, bool UpdateFileBackEnd = false) { - void do_test_exec(size_t numPerBox, std::string filename, bool MakeFileBacked = false, bool UpdateFileBackEnd = false) - { - // Make a 1D MDEventWorkspace - MDEventWorkspace1Lean::sptr ws = MDEventsTestHelper::makeMDEW<1>(10, 0.0, 10.0, numPerBox); + MDEventWorkspace1Lean::sptr ws = + MDEventsTestHelper::makeMDEW<1>(10, 0.0, 10.0, numPerBox); // Make sure it is split ws->splitBox(); @@ -75,55 +60,55 @@ public: ws->refreshCache(); // There are this many boxes, so this is the max ID. - TS_ASSERT_EQUALS( ws->getBoxController()->getMaxId(), 11); + TS_ASSERT_EQUALS(ws->getBoxController()->getMaxId(), 11); IMDEventWorkspace_sptr iws = ws; SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) ); - TS_ASSERT_THROWS_NOTHING( alg.setProperty("MakeFileBacked", MakeFileBacked) ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws")); + TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", filename)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("MakeFileBacked", MakeFileBacked)); // clean up possible rubbish from the previous runs std::string fullName = alg.getPropertyValue("Filename"); - if (fullName!="") - if(Poco::File(fullName).exists()) Poco::File(fullName).remove(); + if (fullName != "") + if (Poco::File(fullName).exists()) + Poco::File(fullName).remove(); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); std::string this_filename = alg.getProperty("Filename"); - TSM_ASSERT( "File was indeed created", Poco::File(this_filename).exists()); + TSM_ASSERT("File was indeed created", Poco::File(this_filename).exists()); - if (MakeFileBacked) - { - TSM_ASSERT("Workspace was made file-backed", ws->isFileBacked() ); - TSM_ASSERT("File back-end no longer needs updating.", !ws->fileNeedsUpdating() ); + if (MakeFileBacked) { + TSM_ASSERT("Workspace was made file-backed", ws->isFileBacked()); + TSM_ASSERT("File back-end no longer needs updating.", + !ws->fileNeedsUpdating()); } // Continue the test if (UpdateFileBackEnd) do_test_UpdateFileBackEnd(ws, filename); - else - { + else { ws->clearFileBacked(false); - if (Poco::File(this_filename).exists()) Poco::File(this_filename).remove(); + if (Poco::File(this_filename).exists()) + Poco::File(this_filename).remove(); } - } - + /// Add some data and update the back-end - void do_test_UpdateFileBackEnd(MDEventWorkspace1Lean::sptr ws, std::string filename) - { + void do_test_UpdateFileBackEnd(MDEventWorkspace1Lean::sptr ws, + std::string filename) { size_t initial_numEvents = ws->getNPoints(); TSM_ASSERT_EQUALS("Starting off with 230 events.", initial_numEvents, 230); // Add 100 events - for (size_t i=0; i<100; i++) - { + for (size_t i = 0; i < 100; i++) { MDLeanEvent<1> ev(1.0, 1.0); ev.setCenter(0, double(i) * 0.01 + 0.4); ws->addEvent(ev); @@ -133,44 +118,49 @@ public: // Manually set the flag that the algo would set ws->setFileNeedsUpdating(true); - TSM_ASSERT_EQUALS("Correctly added 100 events to original 230.", ws->getNPoints(), 230+100); + TSM_ASSERT_EQUALS("Correctly added 100 events to original 230.", + ws->getNPoints(), 230 + 100); SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) ); - TS_ASSERT_THROWS_NOTHING( alg.setProperty("UpdateFileBackEnd", true) ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws")); + TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", filename)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("UpdateFileBackEnd", true)); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); // Since there are 330 events, the file needs to be that big (or bigger). - TS_ASSERT_LESS_THAN( 330, ws->getBoxController()->getFileIO()->getFileLength()); + TS_ASSERT_LESS_THAN(330, + ws->getBoxController()->getFileIO()->getFileLength()); - TSM_ASSERT("File back-end no longer needs updating.", !ws->fileNeedsUpdating() ); + TSM_ASSERT("File back-end no longer needs updating.", + !ws->fileNeedsUpdating()); // Clean up file ws->clearFileBacked(false); std::string fullPath = alg.getPropertyValue("Filename"); - if (Poco::File(fullPath).exists()) Poco::File(fullPath).remove(); + if (Poco::File(fullPath).exists()) + Poco::File(fullPath).remove(); } - void test_saveExpInfo() - { + void test_saveExpInfo() { std::string filename("MultiExperSaveMD2Test.nxs"); // Make a 1D MDEventWorkspace - MDEventWorkspace1Lean::sptr ws = MDEventsTestHelper::makeMDEW<1>(10, 0.0, 10.0, 2); + MDEventWorkspace1Lean::sptr ws = + MDEventsTestHelper::makeMDEW<1>(10, 0.0, 10.0, 2); // Make sure it is split ws->splitBox(); Mantid::Geometry::Goniometer gon; - gon.pushAxis("Psi",0,1,0); - // add experiment infos - for(int i=0;i<80;i++) - { - ExperimentInfo_sptr ei = boost::shared_ptr<ExperimentInfo>(new ExperimentInfo()); - ei->mutableRun().addProperty("Psi",double(i)); - ei->mutableRun().addProperty("Ei",400.); - ei->mutableRun().setGoniometer(gon,true); + gon.pushAxis("Psi", 0, 1, 0); + // add experiment infos + for (int i = 0; i < 80; i++) { + ExperimentInfo_sptr ei = + boost::shared_ptr<ExperimentInfo>(new ExperimentInfo()); + ei->mutableRun().addProperty("Psi", double(i)); + ei->mutableRun().addProperty("Ei", 400.); + ei->mutableRun().setGoniometer(gon, true); ws->addExperimentInfo(ei); } @@ -179,29 +169,30 @@ public: ws->refreshCache(); // There are this many boxes, so this is the max ID. - TS_ASSERT_EQUALS( ws->getBoxController()->getMaxId(), 11); + TS_ASSERT_EQUALS(ws->getBoxController()->getMaxId(), 11); IMDEventWorkspace_sptr iws = ws; SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) ); - TS_ASSERT_THROWS_NOTHING( alg.setProperty("MakeFileBacked","0") ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("InputWorkspace", "SaveMD2Test_ws")); + TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", filename)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("MakeFileBacked", "0")); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); std::string this_filename = alg.getProperty("Filename"); ws->clearFileBacked(false); - if (Poco::File(this_filename).exists()) Poco::File(this_filename).remove(); - + if (Poco::File(this_filename).exists()) + Poco::File(this_filename).remove(); } - void test_saveAffine() - { + void test_saveAffine() { std::string filename("MDAffineSaveMD2Test.nxs"); // Make a 4D MDEventWorkspace - MDEventWorkspace4Lean::sptr ws = MDEventsTestHelper::makeMDEW<4>(10, 0.0, 10.0, 2); + MDEventWorkspace4Lean::sptr ws = + MDEventsTestHelper::makeMDEW<4>(10, 0.0, 10.0, 2); AnalysisDataService::Instance().addOrReplace("SaveMD2Test_ws", ws); // Bin data to get affine matrix @@ -216,83 +207,76 @@ public: balg.execute(); SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", "SaveMD2TestHisto_ws") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) ); - TS_ASSERT_THROWS_NOTHING( alg.setProperty("MakeFileBacked","0") ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("InputWorkspace", "SaveMD2TestHisto_ws")); + TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", filename)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("MakeFileBacked", "0")); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); std::string this_filename = alg.getProperty("Filename"); ws->clearFileBacked(false); - if (Poco::File(this_filename).exists()) - { + if (Poco::File(this_filename).exists()) { Poco::File(this_filename).remove(); } } /** Run SaveMD with the MDHistoWorkspace */ - void doTestHisto(MDHistoWorkspace_sptr ws) - { + void doTestHisto(MDHistoWorkspace_sptr ws) { std::string filename = "SaveMD2TestHisto.nxs"; SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setProperty("InputWorkspace", ws) ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", ws)); + TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", filename)); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); filename = alg.getPropertyValue("Filename"); - TSM_ASSERT( "File was indeed created", Poco::File(filename).exists()); + TSM_ASSERT("File was indeed created", Poco::File(filename).exists()); if (Poco::File(filename).exists()) Poco::File(filename).remove(); } - void test_histo2() - { - MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.5, 2, 10, 10.0, 3.5, "histo2", 4.5); + void test_histo2() { + MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace( + 2.5, 2, 10, 10.0, 3.5, "histo2", 4.5); doTestHisto(ws); } - }; - - -class SaveMD2TestPerformance : public CxxTest::TestSuite -{ +class SaveMD2TestPerformance : public CxxTest::TestSuite { public: - MDEventWorkspace3Lean::sptr ws; - void setUp() - { + MDEventWorkspace3Lean::sptr ws; + void setUp() { // Make a 1D MDEventWorkspace ws = MDEventsTestHelper::makeMDEW<3>(10, 0.0, 10.0, 0); ws->getBoxController()->setSplitInto(5); ws->getBoxController()->setSplitThreshold(2000); - AnalysisDataService::Instance().addOrReplace("SaveMD2TestPerformance_ws", ws); + AnalysisDataService::Instance().addOrReplace("SaveMD2TestPerformance_ws", + ws); - FrameworkManager::Instance().exec("FakeMDEventData", 4, - "InputWorkspace", "SaveMD2TestPerformance_ws", "UniformParams", "10000000"); + FrameworkManager::Instance().exec("FakeMDEventData", 4, "InputWorkspace", + "SaveMD2TestPerformance_ws", + "UniformParams", "10000000"); ws->refreshCache(); } - void test_exec_3D() - { + void test_exec_3D() { SaveMD2 alg; - TS_ASSERT_THROWS_NOTHING( alg.initialize() ) - TS_ASSERT( alg.isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", "SaveMD2TestPerformance_ws") ); - TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", "SaveMD2TestPerformance.nxs") ); + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("InputWorkspace", "SaveMD2TestPerformance_ws")); + TS_ASSERT_THROWS_NOTHING( + alg.setPropertyValue("Filename", "SaveMD2TestPerformance.nxs")); alg.execute(); - TS_ASSERT( alg.isExecuted() ); + TS_ASSERT(alg.isExecuted()); } - - }; - #endif /* MANTID_MDEVENTS_SAVEMD2EWTEST_H_ */ - diff --git a/Code/Mantid/Framework/MDAlgorithms/test/SliceMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/SliceMDTest.h index 686d1d946cca71cc33101472628ad5e434b4e526..c095dedf71e103d0c8539da3cffe880e3259eddc 100644 --- a/Code/Mantid/Framework/MDAlgorithms/test/SliceMDTest.h +++ b/Code/Mantid/Framework/MDAlgorithms/test/SliceMDTest.h @@ -36,6 +36,10 @@ private: alg.initialize(); IMDEventWorkspace_sptr in_ws = MDEventsTestHelper::makeAnyMDEW<MDEvent<3>,3>(10, 0.0, 10.0, 1); + auto eventNorm = Mantid::API::MDNormalization::VolumeNormalization; + auto histoNorm = Mantid::API::MDNormalization::NumEventsNormalization; + in_ws->setDisplayNormalization(eventNorm); + in_ws->setDisplayNormalizationHisto(histoNorm); AnalysisDataService::Instance().addOrReplace("SliceMDTest_ws", in_ws); alg.setPropertyValue("InputWorkspace", "SliceMDTest_ws"); @@ -66,7 +70,10 @@ private: TSM_ASSERT_EQUALS("MaxRecusionDepth property should be enabled", true, p->getSettings()->isEnabled(&alg)); TSM_ASSERT_EQUALS("Should have passed the maxium depth onto the ouput workspace from the input workspace.", size_t(maxDepth), out->getBoxController()->getMaxDepth()); } - + + TSM_ASSERT_EQUALS("Should show volume normalization", out->displayNormalization(), eventNorm); + TSM_ASSERT_EQUALS("Should show num event normalization", out->displayNormalizationHisto(), histoNorm); + //Clean up test objects AnalysisDataService::Instance().remove("SliceMDTest_ws"); AnalysisDataService::Instance().remove("SliceMDTest_outWS"); diff --git a/Code/Mantid/Framework/Nexus/src/NexusFileIO.cpp b/Code/Mantid/Framework/Nexus/src/NexusFileIO.cpp index 9427b662c74f4a5a06f34f748334a713dd7845c8..634cdf59dc0ebe4b121503c6330c9d9df1c56ba3 100644 --- a/Code/Mantid/Framework/Nexus/src/NexusFileIO.cpp +++ b/Code/Mantid/Framework/Nexus/src/NexusFileIO.cpp @@ -476,7 +476,7 @@ int NexusFileIO::writeNexusProcessedData2D( textAxis += label + "\n"; } dims_array[0] = static_cast<int>(textAxis.size()); - NXmakedata(fileID, "axis2", NX_CHAR, 2, dims_array); + NXmakedata(fileID, "axis2", NX_CHAR, 1, dims_array); NXopendata(fileID, "axis2"); NXputdata(fileID, reinterpret_cast<void *>(const_cast<char *>(textAxis.c_str()))); diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IMDWorkspace.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IMDWorkspace.cpp index 34f94873a51a6a76f833029864ac0e5fd1aa26e0..b1005eb240bfd7fed646153bd9ba8b2ce771b71a 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IMDWorkspace.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/IMDWorkspace.cpp @@ -31,7 +31,12 @@ void export_IMDWorkspace() { "Returns the total number of events, contributed to the workspace") .def("getSpecialCoordinateSystem", &IMDWorkspace::getSpecialCoordinateSystem, args("self"), - "Returns the special coordinate system of the workspace"); + "Returns the special coordinate system of the workspace") + .def("displayNormalization", &IMDWorkspace::displayNormalization, args("self"), + "Returns the visual normalization of the workspace.") + .def("displayNormalizationHisto", &IMDWorkspace::displayNormalizationHisto, args("self"), + "For MDEventWorkspaces returns the visual normalization of dervied MDHistoWorkspaces." + "For all others returns the same as displayNormalization."); RegisterWorkspacePtrToPython<IMDWorkspace>(); } diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CollectHB3AExperimentInfo.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CollectHB3AExperimentInfo.py index 34a60e2a87299e75f0ee8c13a76521599723d0d8..3a63c7bb3ea9e21bcc69916c955933a965bdc214 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CollectHB3AExperimentInfo.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CollectHB3AExperimentInfo.py @@ -21,6 +21,8 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): self._tol2Theta = None self._dataDir = None self._ptListList = None + self._doGenerateVirtualInstrument = False + self._numPixelsDetector = -1 # Define class variable Scan-Pt. dictionary: Key scan number, Value list of pt numbers self._scanPtDict = {} @@ -55,8 +57,6 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): scanlistprop = mantid.kernel.IntArrayProperty("ScanList", []) self.declareProperty(scanlistprop, "List of scans of the experiment to be loaded. It cannot be left blank") - #self.declareProperty(IntArrayProperty("ScanList", [], Direction.Input), - # "List of scans of the experiment to be loaded. It cannot be left blank.") pd = "List of Pts to be loaded for scans specified by 'ScanList'. \ Each scan's Pt. must be started with -1 as a flag. \ @@ -67,7 +67,8 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): self.declareProperty("GetFileFromServer", False, "Obtain data file directly from neutrons.ornl.gov.") - self.declareProperty("Detector2ThetaTolerance", 0.01, "Tolerance of 2 detector's 2theta to consider as being at same position.") + self.declareProperty("Detector2ThetaTolerance", 0.01, + "Tolerance of 2 detector's 2theta to consider as being at same position.") tableprop = mantid.api.ITableWorkspaceProperty("OutputWorkspace", "", mantid.kernel.Direction.Output) self.declareProperty(tableprop, "TableWorkspace for experiment number, scan, file name and starting detector IDs.") @@ -75,9 +76,17 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): tableprop2 = mantid.api.ITableWorkspaceProperty("DetectorTableWorkspace", "", mantid.kernel.Direction.Output) self.declareProperty(tableprop2, "TableWorkspace for detector Id and information.") + self.declareProperty('GenerateVirtualInstrument', True, + 'If True, then the geometry of all the detectors will be written ' + 'to DetectorTableWorkspace') - return + default_num_dets = 256 * 256 + self.declareProperty('DetectorNumberPixels', + default_num_dets, + 'Number of pixels on the detector. \ + It is only required if GenerateVirtualInstrument is set to False.') + return def PyExec(self): """ Main executor @@ -166,6 +175,8 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): rawptlist = self.getProperty("PtLists").value self._tol2Theta = self.getProperty("Detector2ThetaTolerance").value self._dataDir = self.getProperty("DataDirectory").value + self._doGenerateVirtualInstrument = self.getProperty('GenerateVirtualInstrument').value + self._numPixelsDetector = self.getProperty('DetectorNumberPixels').value # process Pt number self._ptListList = [] @@ -185,10 +196,17 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): if len(self._ptListList) != len(self._scanList): raise RuntimeError("Number of sub Pt. list is not equal to number of scans.") + if self._doGenerateVirtualInstrument is False: + self._numPixelsDetector = int(self._numPixelsDetector) + if self._numPixelsDetector < 0: + raise RuntimeError('In case that virtual instrument is not created, number of pixels on ' + 'detector must be given. %d is not a valid number.' % self._numPixelsDetector) + elif self._numPixelsDetector < 256 * 256: + self.log().warning('User defined number of detectors is less than 256 * 256. ') + # END-IF return - def _getDetectorPositionScanPtDict(self): """ Get detector position (2theta) - Scan and pt number dictionary Dictionary: key : 2theta value @@ -248,32 +266,41 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): else: self.log().notice("[DB] Process pixels of detector centered at 2theta = %.5f." % (twotheta)) - # Load detector counts file (.xml) + # Get scan/pt and set dictionary self.log().debug("Processing detector @ 2theta = %.5f, " % (twotheta)) scannumber, ptnumber = self._2thetaScanPtDict[twotheta][0] - self.log().debug("self._2thetaScanPtDict: %s"%(self._2thetaScanPtDict[twotheta])) - dataws = self._loadHB3ADetCountFile(scannumber, ptnumber) + self.log().debug("self._2thetaScanPtDict: %s" % (self._2thetaScanPtDict[twotheta])) self._scanPt2ThetaDict[(scannumber, ptnumber)] = twotheta - self._detStartID[twotheta] = self._currStartDetID - maxdetid = 0 - for iws in xrange(dataws.getNumberHistograms()): - detector = dataws.getDetector(iws) - detpos = detector.getPos() - newdetid = self._currStartDetID + detector.getID() - if detector.getID() > maxdetid: - maxdetid = detector.getID() - self._myPixelInfoTableWS.addRow([newdetid, detpos.X(), detpos.Y(), detpos.Z(), detector.getID()]) - # ENDFOR (iws) + if self._doGenerateVirtualInstrument is True: + # Load detector counts file (.xml) + dataws = self._loadHB3ADetCountFile(scannumber, ptnumber) + + # write each detector's position and ID to table workspace + maxdetid = 0 + for iws in xrange(dataws.getNumberHistograms()): + detector = dataws.getDetector(iws) + detpos = detector.getPos() + newdetid = self._currStartDetID + detector.getID() + if detector.getID() > maxdetid: + maxdetid = detector.getID() + self._myPixelInfoTableWS.addRow([newdetid, detpos.X(), detpos.Y(), detpos.Z(), detector.getID()]) + # ENDFOR (iws) + + else: + # No need to generate virtual instrument information. + maxdetid = self._numPixelsDetector + + # END-IF-ELSE + # Update start ID self._currStartDetID += maxdetid # ENDFOR return - def _getAllPtFromTable(self, spicetablews): """ Get all Pt. from a table """ @@ -286,7 +313,6 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): return ptlist - def _loadSpiceFile(self, spicefilename): """ Load SPICE file """ @@ -298,7 +324,6 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): return spicetablews - def _loadHB3ADetCountFile(self, scannumber, ptnumber): """ Load Spice XML file """ @@ -311,7 +336,5 @@ class CollectHB3AExperimentInfo(PythonAlgorithm): return dataws - - # Register algorithm with Mantid AlgorithmFactory.subscribe(CollectHB3AExperimentInfo) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/EnggVanadiumCorrections.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/EnggVanadiumCorrections.py index 46a5c2ed9e937691885e4bd099d25a2b8bbcc3d4..fc1cacaf0808d41e106a308a540fd279c264c7c0 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/EnggVanadiumCorrections.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/EnggVanadiumCorrections.py @@ -186,7 +186,7 @@ class EnggVanadiumCorrections(PythonAlgorithm): (integWS.blocksize(), integWS.getNumberHistograms(), vanWS.getNumberHistograms())) - integTbl = sapi.CreateEmptyTableWorkspace() + integTbl = sapi.CreateEmptyTableWorkspace(OutputWorkspace='__vanIntegTbl') integTbl.addColumn('double', 'Spectra Integration') for i in range(integWS.getNumberHistograms()): integTbl.addRow([integWS.readY(i)[0]]) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ApplyPaalmanPingsCorrection.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ApplyPaalmanPingsCorrection.py index adef35b3919ae306ef648627d728cf8fa2f8307f..525db109bfc34a1bfc05a30e1cce7d45388c2892 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ApplyPaalmanPingsCorrection.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ApplyPaalmanPingsCorrection.py @@ -78,11 +78,21 @@ class ApplyPaalmanPingsCorrection(PythonAlgorithm): # Use sample factor only self._correct_sample() correction_type = 'sample_corrections_only' + # Add corrections filename to log values + AddSampleLog(Workspace=self._output_ws_name, + LogName='corrections_filename', + LogType='String', + LogText=self._corrections_ws_name) else: # Do simple subtraction self._subtract() correction_type = 'can_subtraction' + # Add container filename to log values + AddSampleLog(Workspace=self._output_ws_name, + LogName='container_filename', + LogType='String', + LogText=self._can_ws_name) # Record the container scale factor if self._use_can and self._scale_can: @@ -97,6 +107,12 @@ class ApplyPaalmanPingsCorrection(PythonAlgorithm): LogType='String', LogText=correction_type) + # Add original sample as log entry + AddSampleLog(Workspace=self._output_ws_name, + LogName='sample_filename', + LogType='String', + LogText=self._sample_ws_name) + self.setPropertyValue('OutputWorkspace', self._output_ws_name) # Remove temporary workspaces diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/ConvolutionFitSequential.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/ConvolutionFitSequential.cpp index bce7b2f99fa40c3d4e874482757eacbf1ed1de2b..5ae07daf9dbdf1e4a83478859f163944676dd814 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/ConvolutionFitSequential.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/ConvolutionFitSequential.cpp @@ -187,10 +187,10 @@ void ConvolutionFitSequential::exec() { const std::string tempFitWsName = "__convfit_fit_ws"; auto tempFitWs = convertInputToElasticQ(inputWs, tempFitWsName); - Progress plotPeakStringProg(this, 0.0, 0.05, specMax); + Progress plotPeakStringProg(this, 0.0, 0.05, specMax-specMin); // Construct plotpeak string std::string plotPeakInput = ""; - for (int i = 0; i < specMax + 1; i++) { + for (int i = specMin; i < specMax + 1; i++) { std::string nextWs = tempFitWsName + ",i"; nextWs += boost::lexical_cast<std::string>(i); plotPeakInput += nextWs + ";"; @@ -346,7 +346,7 @@ void ConvolutionFitSequential::exec() { auto renamer = createChildAlgorithm("RenameWorkspace"); Progress renamerProg(this, 0.98, 1.0, specMax + 1); for (int i = specMin; i < specMax + 1; i++) { - renamer->setProperty("InputWorkspace", groupWsNames.at(i)); + renamer->setProperty("InputWorkspace", groupWsNames.at(i - specMin)); std::string outName = outputWsName + "_"; outName += boost::lexical_cast<std::string>(i); outName += "_Workspace"; diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 47aadca47f3348c8c18644c6c7340671a9c1749d..6e4d19ca956d800095fc2029bfbc2fde73d57cb8 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -4530,23 +4530,33 @@ ApplicationWindow *ApplicationWindow::open(const QString &fn, void ApplicationWindow::openRecentFile(int index) { QString fn = recentFilesMenu->text(index); - int pos = fn.find(" ", 0); - fn = fn.right(fn.length() - pos - 1); - QFile f(fn); - if (!f.exists()) { - QMessageBox::critical( - this, tr("MantidPlot - File Open Error"), // Mantid - tr("The file: <b> %1 </b> <p>is not there anymore!" - "<p>It will be removed from the list of recent files.") - .arg(fn)); + // if "," found in the QString + if (fn.find(",", 0)) { + try { + int pos = fn.find(" ", 0); + fn = fn.right(fn.length() - pos - 1); + loadDataFileByName(fn); + } catch (Mantid::Kernel::Exception::NotFoundError &) { + throw; + } + } else { + int pos = fn.find(" ", 0); + fn = fn.right(fn.length() - pos - 1); + QFile f(fn); + if (!f.exists()) { + QMessageBox::critical( + this, tr("MantidPlot - File Open Error"), // Mantid + tr("The file: <b> %1 </b> <p>is not there anymore!" + "<p>It will be removed from the list of recent files.") + .arg(fn)); - recentFiles.remove(fn); - updateRecentFilesList(); - return; + recentFiles.remove(fn); + updateRecentFilesList(); + return; + } + loadDataFileByName(fn); } - - loadDataFileByName(fn); saveSettings(); // save new list of recent files } @@ -5369,7 +5379,7 @@ void ApplicationWindow::readSettings() { d_export_transparency = settings.value("/ExportTransparency", false).toBool(); d_export_quality = settings.value("/ImageQuality", 100).toInt(); // d_export_resolution = settings.value("/Resolution", - //QPrinter().resolution()).toInt(); + // QPrinter().resolution()).toInt(); d_export_color = settings.value("/ExportColor", true).toBool(); d_export_vector_size = settings.value("/ExportPageSize", QPrinter::Custom).toInt(); @@ -12959,7 +12969,7 @@ void ApplicationWindow::createActions() { // actionHelpForums = new QAction(tr("QtiPlot &Forums"), this); // Mantid // change // connect(actionHelpForums, SIGNAL(triggered()), this, - //SLOT(showForums())); // Mantid change + // SLOT(showForums())); // Mantid change actionHelpBugReports = new QAction(tr("Report a &Bug"), this); connect(actionHelpBugReports, SIGNAL(triggered()), this, @@ -14297,7 +14307,7 @@ void ApplicationWindow::parseCommandLineArguments(const QStringList &args) { } else if (isSilentStartup(str)) { g_log.debug("Starting in Silent mode"); } // if filename not found yet then these are all program arguments so we - // should + // should // know what they all are else if (file_name.isEmpty() && (str.startsWith("-") || str.startsWith("--"))) { diff --git a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h index 34603869b1993b6e822ff9dd8a7259c2f6a0ed2e..9f4e94067f9931e496024ecc901065788d3d60f7 100644 --- a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h +++ b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h @@ -27,6 +27,7 @@ #include <QDialog> #include <QString> +#include <QTimer> #include <QHash> #include <QVBoxLayout> @@ -240,6 +241,8 @@ protected slots: virtual void executeAlgorithmAsync(); /// Removes the algorithm from the manager. virtual void removeAlgorithmFromManager(); + /// Enable to exit button + void enableExitButton(); protected: @@ -257,6 +260,7 @@ protected: virtual void finishHandle(const Mantid::API::IAlgorithm *alg); /// Handle completion of algorithm started while staying open virtual void errorHandle(const Mantid::API::IAlgorithm *alg, const std::string &what); + virtual void closeEvent(QCloseEvent *evt); /// The following methods were made public for testing in GenericDialogDemo.cpp public: @@ -334,10 +338,15 @@ protected: //the keep open checkbox control QCheckBox* m_keepOpenCheckBox; - QPushButton* m_okButton; + QPushButton* m_okButton, *m_exitButton; /// A list of AlgorithmObservers to add to the algorithm prior to execution std::vector<Mantid::API::AlgorithmObserver *> m_observers; + + /// Enable the close button when the timer fires + QTimer m_btnTimer; + /// A flag to track whether the status of the algorithm is being tracked + bool m_statusTracked; //@} }; diff --git a/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp b/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp index 5c61acf8fc029732393c0f3297543847f34dc86e..82ac2f990d2e3ab0c1dcda3619fb265fe6086cdb 100644 --- a/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp +++ b/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp @@ -46,8 +46,10 @@ AlgorithmDialog::AlgorithmDialog(QWidget* parent) : m_enabled(), m_disabled(), m_strMessage(""), m_keepOpen(false), m_msgAvailable(false), m_isInitialized(false), m_autoParseOnInit(true), m_validators(), m_noValidation(), m_inputws_opts(), m_outputws_fields(), m_wsbtn_tracker(), - m_keepOpenCheckBox(NULL), m_okButton(NULL) + m_keepOpenCheckBox(NULL), m_okButton(NULL), m_exitButton(NULL), m_observers(), m_btnTimer(), + m_statusTracked(false) { + m_btnTimer.setSingleShot(true); } /** @@ -56,7 +58,9 @@ AlgorithmDialog::AlgorithmDialog(QWidget* parent) : AlgorithmDialog::~AlgorithmDialog() { m_observers.clear(); - this->stopObserving(m_algorithm); + if(m_statusTracked) { + this->stopObserving(m_algorithm); + } } /** @@ -712,8 +716,8 @@ AlgorithmDialog::createDefaultButtonLayout(const QString & helpText, connect(m_okButton, SIGNAL(clicked()), this, SLOT(accept())); m_okButton->setDefault(true); - QPushButton *exitButton = new QPushButton(cancelText); - connect(exitButton, SIGNAL(clicked()), this, SLOT(close())); + m_exitButton = new QPushButton(cancelText); + connect(m_exitButton, SIGNAL(clicked()), this, SLOT(close())); QHBoxLayout *buttonRowLayout = new QHBoxLayout; @@ -730,7 +734,7 @@ AlgorithmDialog::createDefaultButtonLayout(const QString & helpText, } buttonRowLayout->addWidget(m_okButton); - buttonRowLayout->addWidget(exitButton); + buttonRowLayout->addWidget(m_exitButton); return buttonRowLayout; } @@ -820,22 +824,42 @@ void AlgorithmDialog::keepOpenChanged(int state) //------------------------------------------------------------------------------------------------- + /** * Execute the underlying algorithm */ void AlgorithmDialog::executeAlgorithmAsync() { Mantid::API::IAlgorithm_sptr algToExec = m_algorithm; + // Clear any previous trackers so we know what state we are in + this->stopObserving(algToExec); + try { // Add any custom AlgorithmObservers to the algorithm - for(auto it = m_observers.begin(); it != m_observers.end(); ++it) + for(auto it = m_observers.begin(); it != m_observers.end(); ++it) { (*it)->observeAll(algToExec); + } - this->observeFinish(algToExec); - this->observeError(algToExec); - + // Only need to observe finish events if we are staying open + if(m_keepOpenCheckBox && m_keepOpenCheckBox->isChecked()) { + this->observeFinish(algToExec); + this->observeError(algToExec); + m_statusTracked = true; + // Disable close button for a short period. If it is clicked to soon then + // Mantid crashes - https://github.com/mantidproject/mantid/issues/13836 + if(m_exitButton) { + m_exitButton->setEnabled(false); + m_btnTimer.setInterval(1000); + connect(&m_btnTimer, SIGNAL(timeout()), this, + SLOT(enableExitButton())); + } else { + m_statusTracked = false; + } + } algToExec->executeAsync(); + m_btnTimer.start(); + if (m_okButton) { m_okButton->setEnabled(false); } @@ -855,6 +879,12 @@ void AlgorithmDialog::removeAlgorithmFromManager() AlgorithmManager::Instance().removeById(m_algorithm->getAlgorithmID()); } +/** + */ +void AlgorithmDialog::enableExitButton() { + m_exitButton->setEnabled(true); +} + //------------------------------------------------------ // Private member functions //------------------------------------------------------ @@ -1158,6 +1188,20 @@ void AlgorithmDialog::errorHandle(const IAlgorithm *alg, const std::string &what emit algCompletedSignal(); } +/** + * Only allow close when close is enabled + */ +void AlgorithmDialog::closeEvent(QCloseEvent *evt) { + if (m_exitButton) { + if (m_exitButton->isEnabled()) { + evt->accept(); + } else { + evt->ignore(); + } + } else { + QDialog::closeEvent(evt); + } +} /**Handle completion of algorithm started while staying open. * reenables the OK button when the algorithms finishes. diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h index d241b2dd13692aa7a65b3fb37b33183dbfce1029..47bcff662e7dc2859e0bdb2c96ed6bc156225bc7 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h @@ -41,15 +41,17 @@ public: /// for calibration EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &outFilename, const std::string &vanNo, const std::string &ceriaNo) - : m_pres(pres), m_outFilename(outFilename), m_vanNo(vanNo), - m_ceriaNo(ceriaNo), m_bank(-1) {} + : m_pres(pres), m_outFilenames(), m_outCalibFilename(outFilename), + m_vanNo(vanNo), m_ceriaNo(ceriaNo), m_banks() {} /// for focusing EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &outDir, - const std::string &outFilename, const std::string &runNo, - int bank) - : m_pres(pres), m_outFilename(outFilename), m_runNo(runNo), - m_outDir(outDir), m_bank(bank) {} + const std::vector<std::string> &outFilenames, + const std::string &runNo, const std::vector<bool> &banks, + const std::string &specIDs, const std::string &dgFile) + : m_pres(pres), m_outFilenames(outFilenames), m_outCalibFilename(), + m_runNo(runNo), m_outDir(outDir), m_banks(banks), m_specIDs(specIDs), + m_dgFile(dgFile) {} private slots: @@ -58,7 +60,7 @@ private slots: * signal. */ void calibrate() { - m_pres->doNewCalibration(m_outFilename, m_vanNo, m_ceriaNo); + m_pres->doNewCalibration(m_outCalibFilename, m_vanNo, m_ceriaNo); emit finished(); } @@ -67,7 +69,8 @@ private slots: * signal. */ void focus() { - m_pres->doFocusRun(m_outDir, m_outFilename, m_runNo, m_bank); + m_pres->doFocusRun(m_outDir, m_outFilenames, m_runNo, m_banks, m_specIDs, + m_dgFile); emit finished(); } @@ -76,14 +79,20 @@ signals: private: EnggDiffractionPresenter *m_pres; + /// parameters for calibration - std::string m_outFilename, m_vanNo, m_ceriaNo; + const std::vector<std::string> m_outFilenames; + const std::string m_outCalibFilename, m_vanNo, m_ceriaNo; /// sample run to process const std::string m_runNo; /// Output directory const std::string m_outDir; - /// instrument bank - int m_bank; + /// instrument banks: do focus/don't + const std::vector<bool> m_banks; + // parameters for specific types of focusing: "cropped" + const std::string m_specIDs; + // for focusing "texture" + const std::string m_dgFile; }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h index 2f476cbde73f93f71e67ec6a5222cd0e5ceb2521..ab2cb4672c86bae2b479c406c6ba8a9076e5fe9b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h @@ -64,8 +64,10 @@ public: const std::string &vanNo, const std::string &ceriaNo); /// the focusing hard work that a worker / thread will run - void doFocusRun(const std::string &dir, const std::string &outFilename, - const std::string &runNo, int bank); + void doFocusRun(const std::string &dir, + const std::vector<std::string> &outFilenames, + const std::string &runNo, const std::vector<bool> &banks, + const std::string &specNos, const std::string &dgFile); protected: void initialize(); @@ -76,7 +78,10 @@ protected: void processStart(); void processLoadExistingCalib(); void processCalcCalib(); - void processFocusRun(); + void processFocusBasic(); + void processFocusCropped(); + void processFocusTexture(); + void processResetFocus(); void processLogMsg(); void processInstChange(); void processShutDown(); @@ -112,17 +117,44 @@ private: /// @name Focusing related private methods //@{ /// this may also need to be mocked up in tests - virtual void startAsyncFocusWorker(const std::string &dir, - const std::string &outFilename, - const std::string &runNo, int bank); - - void inputChecksBeforeFocus(const std::string &runNo, int bank); - - std::string outputFocusFilename(const std::string &runNo, int bank); + void startFocusing(const std::string &runNo, const std::vector<bool> &banks, + const std::string &specNos = "", + const std::string &dgFile = ""); + + void startAsyncFocusWorker(const std::string &dir, + const std::vector<std::string> &outFilenames, + const std::string &runNo, + const std::vector<bool> &banks, + const std::string &specNos, + const std::string &dgFile); + + void inputChecksBeforeFocusBasic(const std::string &runNo, + const std::vector<bool> &banks); + void inputChecksBeforeFocusCropped(const std::string &runNo, + const std::vector<bool> &banks, + const std::string &specNos); + void inputChecksBeforeFocusTexture(const std::string &runNo, + const std::string &dgfile); + void inputChecksBeforeFocus(); + void inputChecksBanks(const std::vector<bool> &banks); + + std::vector<std::string> outputFocusFilenames(const std::string &runNo, + const std::vector<bool> &banks); + + std::string outputFocusCroppedFilename(const std::string &runNo); + + std::vector<std::string> + outputFocusTextureFilenames(const std::string &runNo, + const std::vector<size_t> &bankIDs); + + void loadDetectorGroupingCSV(const std::string &dgFile, + std::vector<size_t> &bankIDs, + std::vector<std::string> &specs); void doFocusing(const EnggDiffCalibSettings &cs, const std::string &fullFilename, const std::string &runNo, - int bank); + size_t bank, const std::string &specNos, + const std::string &dgFile); void loadOrCalcVanadiumWorkspaces( const std::string &vanNo, const std::string &inputDirCalib, @@ -150,6 +182,9 @@ private: /// whether to allow users to give the output calibration filename const static bool g_askUserCalibFilename; + // name of the workspace with the vanadium integration (of spectra) + static const std::string g_vanIntegrationWSName; + QThread *m_workerThread; /// true if the last calibration completed successfully @@ -167,4 +202,4 @@ private: } // namespace CustomInterfaces } // namespace MantidQt -# endif // MANTIDQTCUSTOMINTERFACES_ENGGDIFFRACTION_ENGGDIFFRACTIONPRESENTER_H_ +#endif // MANTIDQTCUSTOMINTERFACES_ENGGDIFFRACTION_ENGGDIFFRACTIONPRESENTER_H_ diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabFocus.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabFocus.ui index 89d3c88b6749759a47b576a0f38b810db4cf2c18..da4954af8627faf0c93a9d1c3268b22d655fb790 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabFocus.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabFocus.ui @@ -14,71 +14,249 @@ <string>Form</string> </property> <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox_focus"> + <item row="6" column="0"> + <widget class="QGroupBox" name="groupBox_focus_2"> <property name="title"> - <string>Focus run</string> + <string>Output</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> <item> - <spacer name="horizontalSpacer_3"> + <widget class="QCheckBox" name="checkBox_FocusedWS"> + <property name="text"> + <string>Plot Focused Workspace</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> - <width>238</width> + <width>98</width> <height>20</height> </size> </property> </spacer> </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Focus Cropped</string> + </property> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_9"> <item> - <widget class="QPushButton" name="pushButton_focus"> + <widget class="QLabel" name="label_cropped_run_num"> <property name="text"> - <string>Focus</string> + <string>Run #:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>98</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="lineEdit_cropped_run_num"> + <property name="text"> + <string/> + </property> + <property name="readOnly"> + <bool>false</bool> </property> </widget> </item> </layout> </item> <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayout_10"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_cropped_spec_ids"> <property name="text"> - <string>Bank:</string> + <string>Spectrum IDs:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>38</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="lineEdit_cropped_spec_ids"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> </widget> </item> + </layout> + </item> + <item row="2" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_12"> + <item> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_focus_cropped"> + <property name="text"> + <string>Focus</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="4" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>388</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="groupBox_focus"> + <property name="title"> + <string>Focus run</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <spacer name="horizontalSpacer_2"> + <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> - <width>128</width> + <width>238</width> <height>20</height> </size> </property> </spacer> </item> <item> - <widget class="QComboBox" name="comboBox_bank_num"> + <widget class="QPushButton" name="pushButton_focus"> + <property name="text"> + <string>Focus</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <property name="text"> - <string>1</string> - </property> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLabel" name="label_banks_sel"> + <property name="text"> + <string>Banks:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>298</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> </item> <item> - <property name="text"> - <string>2</string> - </property> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>18</height> + </size> + </property> + </spacer> </item> - </widget> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QCheckBox" name="checkBox_focus_bank1"> + <property name="text"> + <string>1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_focus_bank2"> + <property name="text"> + <string>2</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> </item> </layout> </item> @@ -119,36 +297,23 @@ </layout> </widget> </item> - <item row="1" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>388</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0"> - <widget class="QGroupBox" name="groupBox_focus_2"> + <item row="3" column="0"> + <widget class="QGroupBox" name="groupBox_2"> <property name="title"> - <string>Output</string> + <string>Focus Texture</string> </property> - <layout class="QGridLayout" name="gridLayout_2"> + <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> + <layout class="QHBoxLayout" name="horizontalLayout_7"> <item> - <widget class="QCheckBox" name="checkBox_FocusedWS"> + <widget class="QLabel" name="label_texture_run_num"> <property name="text"> - <string>Plot Focused Workspace</string> + <string>Run #:</string> </property> </widget> </item> <item> - <spacer name="horizontalSpacer_4"> + <spacer name="horizontalSpacer_6"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -160,11 +325,100 @@ </property> </spacer> </item> + <item> + <widget class="QLineEdit" name="lineEdit_texture_run_num"> + <property name="text"> + <string/> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Detector Grouping File:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEdit_texture_grouping_file"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_texture_browse_grouping_file"> + <property name="text"> + <string>Browse</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_11"> + <item> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_focus_texture"> + <property name="text"> + <string>Focus</string> + </property> + </widget> + </item> </layout> </item> </layout> </widget> </item> + <item row="5" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_13"> + <item> + <spacer name="horizontalSpacer_11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>188</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_reset"> + <property name="text"> + <string>Reset</string> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> <resources/> diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h index c9b25715a365abdd43fee4456403f3a3cdc930ff..baed981c8f15aa12f32c87aa18132004d4e24ec8 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h @@ -105,18 +105,29 @@ public: virtual std::string focusingRunNo() const; - virtual int focusingBank() const; + virtual std::string focusingCroppedRunNo() const; + + virtual std::string focusingTextureRunNo() const; + + virtual std::vector<bool> focusingBanks() const; + + virtual std::string focusingCroppedSpectrumIDs() const; + + virtual std::string focusingTextureGroupingFile() const; virtual bool focusedOutWorkspace() const; - virtual void plotFocusedSpectrum(); + virtual void resetFocus(); + + virtual void plotFocusedSpectrum(const std::string &wsName); private slots: - /// for buttons, do calibrate and similar + /// for buttons, do calibrate, focus and similar void loadCalibrationClicked(); void calibrateClicked(); void focusClicked(); - + void focusCroppedClicked(); + void focusTextureClicked(); // slots of the settings tab/section of the interface void browseInputDirCalib(); @@ -124,6 +135,11 @@ private slots: void browsePixelCalibFilename(); void browseTemplateGSAS_PRM(); void browseDirFocusing(); + + // slots for the focusing options + void browseTextureDetGroupingFile(); + void focusResetClicked(); + // slots of the calibration tab/section of the interface // slots of the general part of the interface @@ -184,6 +200,9 @@ private: static const std::string g_iparmExtStr; /// supported file extensions string for the pixel (full) claibration static const std::string g_pixelCalibExt; + /// supported/suggested file extensions for the detector groups file + /// (focusing) + static const std::string g_DetGrpExtStr; /// presenter as in the model-view-presenter boost::scoped_ptr<IEnggDiffractionPresenter> m_presenter; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionPresenter.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionPresenter.h index 42020a4c53eeb8ae3567c1107f136dd568c5b805..a2c0240d4cefb1d2befa48388c9bb25ab47bfc01 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionPresenter.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionPresenter.h @@ -41,7 +41,10 @@ public: Start, ///< Start and setup interface LoadExistingCalib, ///< Load a calibration already availble on disk CalcCalib, ///< Calculate a (new) calibration - FocusRun, ///< Focus a run file + FocusRun, ///< Focus one or more run files + FocusCropped, ///< Focus one or more run files, cropped variant + FocusTexture, ///< Focus one or more run files, texture variant + ResetFocus, ///< Re-set / clear all focus inputs and options LogMsg, ///< need to send a message to the Mantid log system InstrumentChange, ///< Instrument selection updated ShutDown ///< closing the interface diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h index 5785b8db63028282974ac8161c5a7d8ee33e4cdb..e701764dac3f0d11fa716a65cde8b98fd4ea1e00 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h @@ -206,19 +206,55 @@ public: virtual std::string focusingRunNo() const = 0; /** - * Bank to consider when focusing + * A (sample) run to focus, in "cropped" mode * - * @return instrument bank number + * @return run number, as a string + */ + virtual std::string focusingCroppedRunNo() const = 0; + + /** + * A (sample) run to focus, in "texture" mode + * + * @return run number, as a string + */ + virtual std::string focusingTextureRunNo() const = 0; + + /** + * Banks to consider when focusing + * + * @return vector with a boolean value that tells if the + * corresponding instrument bank numbers should be focused + */ + virtual std::vector<bool> focusingBanks() const = 0; + + /** + * Specification of spectrum IDs for focus in "cropped" mode. + * + * @return spectrum IDs, expected as a comma separated list of + * integers or ranges of integers. */ - virtual int focusingBank() const = 0; + virtual std::string focusingCroppedSpectrumIDs() const = 0; + + /** + * Detector grouping file, used when focusing in "texture" mode. + * + * @return name of the grouping file with texture bank definitions + */ + virtual std::string focusingTextureGroupingFile() const = 0; /** * Check box to consider when focusing * whether to plot focused workspace + * * @return bool */ virtual bool focusedOutWorkspace() const = 0; + /** + * Reset all focus inputs/options + */ + virtual void resetFocus() = 0; + /** * Save settings (normally when closing the interface). This * concerns only GUI settings, such as window max/min status and @@ -227,10 +263,12 @@ public: virtual void saveSettings() const = 0; /** - * Runs plotSpectrum function via python - * @returns single spectrum graph for focused output + * Produces a single spectrum graph for focused output. Runs + * plotSpectrum function via python. + * + * @param wsName name of the workspace to plot (must be in the ADS) */ - virtual void plotFocusedSpectrum() = 0; + virtual void plotFocusedSpectrum(const std::string &wsName) = 0; }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ApplyPaalmanPings.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ApplyPaalmanPings.ui index e8ff1caa76d5dca07dda9e37d5bebd4c0e8406db..27e53b9921cb14a0a76e3380d7c421900a03a76a 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ApplyPaalmanPings.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ApplyPaalmanPings.ui @@ -1,323 +1,410 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>ApplyPaalmanPings</class> - <widget class="QWidget" name="ApplyPaalmanPings"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>420</width> - <height>420</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QGroupBox" name="gbInput"> - <property name="title"> - <string>Input</string> - </property> - <layout class="QVBoxLayout" name="abscor_loInput"> + <class>ApplyPaalmanPings</class> + <widget class="QWidget" name="ApplyPaalmanPings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>420</width> + <height>420</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="MantidQt::MantidWidgets::DataSelector" name="dsSample" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoLoad" stdset="0"> - <bool>true</bool> - </property> - <property name="workspaceSuffixes" stdset="0"> - <stringlist> - <string>_red</string> - <string>_sqw</string> - </stringlist> - </property> - <property name="fileBrowserSuffixes" stdset="0"> - <stringlist> - <string>_red.nxs</string> - <string>_sqw.nxs</string> - </stringlist> - </property> - <property name="showLoad" stdset="0"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="gbOptions"> - <property name="title"> - <string>Options</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="1"> - <widget class="QComboBox" name="cbGeometry"> - <item> - <property name="text"> - <string>Flat Plate</string> - </property> - </item> - <item> - <property name="text"> - <string>Cylinder</string> - </property> - </item> - <item> - <property name="text"> - <string>Annulus</string> - </property> - </item> - </widget> - </item> - <item row="1" column="1"> - <widget class="MantidQt::MantidWidgets::DataSelector" name="dsCorrections" native="true"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoLoad" stdset="0"> - <bool>true</bool> - </property> - <property name="workspaceSuffixes" stdset="0"> - <stringlist> - <string>_flt_abs</string> - </stringlist> - </property> - <property name="fileBrowserSuffixes" stdset="0"> - <stringlist> - <string>_flt_abs.nxs</string> - </stringlist> - </property> - <property name="showLoad" stdset="0"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="lbGeometry"> - <property name="text"> - <string>Geometry:</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lbCorrection"> - <property name="text"> - <string>Corrections: </string> + <widget class="QGroupBox" name="gbInput"> + <property name="title"> + <string>Input</string> </property> + <layout class="QVBoxLayout" name="abscor_loInput"> + <item> + <widget class="MantidQt::MantidWidgets::DataSelector" name="dsSample" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoLoad" stdset="0"> + <bool>true</bool> + </property> + <property name="workspaceSuffixes" stdset="0"> + <stringlist> + <string>_red</string> + <string>_sqw</string> + </stringlist> + </property> + <property name="fileBrowserSuffixes" stdset="0"> + <stringlist> + <string>_red.nxs</string> + <string>_sqw.nxs</string> + </stringlist> + </property> + <property name="showLoad" stdset="0"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> </widget> - </item>S - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="gbPreview"> - <property name="title"> - <string>Preview</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_11"> - <item> - <widget class="MantidQt::MantidWidgets::PreviewPlot" name="ppPreview" native="true"> - <property name="canvasColour" stdset="0"> - <color> - <red>255</red> - <green>255</green> - <blue>255</blue> - </color> - </property> - <property name="showLegend" stdset="0"> - <bool>true</bool> - </property> - </widget> </item> <item> - <layout class="QVBoxLayout" name="loPlotOptions"> - <item> - <spacer name="verticalSpacer_0"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> + <widget class="QGroupBox" name="gbOptions"> + <property name="title"> + <string>Options</string> </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="lbPreviewSpec"> - <property name="text"> - <string>Spectrum:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="spPreviewSpec"/> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="gbOutput"> - <property name="title"> - <string>Output Options</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="lbPlotOutput"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Plot Output:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="cbPlotOutput"> - <item> - <property name="text"> - <string>None</string> - </property> - </item> - <item> - <property name="text"> - <string>Contour</string> - </property> - </item> - <item> - <property name="text"> - <string>Spectra</string> - </property> - </item> - <item> - <property name="text"> - <string>Both</string> - </property> - </item> - </widget> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QCheckBox" name="ckUseCan"> + <property name="text"> + <string>Use Can:</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="ckUseCorrections"> + <property name="text"> + <string>Use Corrections:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="cbGeometry"> + <item> + <property name="text"> + <string>Flat Plate</string> + </property> + </item> + <item> + <property name="text"> + <string>Cylinder</string> + </property> + </item> + <item> + <property name="text"> + <string>Annulus</string> + </property> + </item> + </widget> + </item> + <item row="4" column="1"> + <widget class="MantidQt::MantidWidgets::DataSelector" name="dsCorrections" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoLoad" stdset="0"> + <bool>true</bool> + </property> + <property name="workspaceSuffixes" stdset="0"> + <stringlist> + <string>_flt_abs</string> + </stringlist> + </property> + <property name="fileBrowserSuffixes" stdset="0"> + <stringlist> + <string>_flt_abs.nxs</string> + </stringlist> + </property> + <property name="showLoad" stdset="0"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="MantidQt::MantidWidgets::DataSelector" name="dsContainer" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoLoad" stdset="0"> + <bool>true</bool> + </property> + <property name="workspaceSuffixes" stdset="0"> + <stringlist> + <string>_red</string> + <string>_sqw</string> + </stringlist> + </property> + <property name="fileBrowserSuffixes" stdset="0"> + <stringlist> + <string>_red.nxs</string> + <string>_sqw.nxs</string> + </stringlist> + </property> + <property name="showLoad" stdset="0"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="lbGeometry"> + <property name="text"> + <string>Geometry:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="ckScaleCan"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Scale Can by factor:</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="3" column="1"> + <layout class="QHBoxLayout" name="loScaleFactor"> + <item> + <widget class="QDoubleSpinBox" name="spCanScale"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="decimals"> + <number>5</number> + </property> + <property name="maximum"> + <double>999.990000000000009</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> </item> <item> - <spacer name="horizontalSpacer_1"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> + <widget class="QGroupBox" name="gbPreview"> + <property name="title"> + <string>Preview</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_11"> + <item> + <widget class="MantidQt::MantidWidgets::PreviewPlot" name="ppPreview" native="true"> + <property name="canvasColour" stdset="0"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + <property name="showLegend" stdset="0"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="loPlotOptions"> + <item> + <spacer name="verticalSpacer_0"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="lbPreviewSpec"> + <property name="text"> + <string>Spectrum:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spPreviewSpec"/> + </item> + </layout> + </item> + </layout> + </widget> </item> <item> - <widget class="QCheckBox" name="ckSave"> - <property name="text"> - <string>Save Result</string> - </property> - </widget> + <widget class="QGroupBox" name="gbOutput"> + <property name="title"> + <string>Output Options</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="lbPlotOutput"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Plot Output:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cbPlotOutput"> + <item> + <property name="text"> + <string>None</string> + </property> + </item> + <item> + <property name="text"> + <string>Contour</string> + </property> + </item> + <item> + <property name="text"> + <string>Spectra</string> + </property> + </item> + <item> + <property name="text"> + <string>Both</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="ckSave"> + <property name="text"> + <string>Save Result</string> + </property> + </widget> + </item> + </layout> + </widget> </item> - </layout> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>MantidQt::MantidWidgets::DataSelector</class> - <extends>QWidget</extends> - <header>MantidQtMantidWidgets/DataSelector.h</header> - </customwidget> - <customwidget> - <class>MantidQt::MantidWidgets::PreviewPlot</class> - <extends>QWidget</extends> - <header>MantidQtMantidWidgets/PreviewPlot.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>ckUseCan</sender> - <signal>toggled(bool)</signal> - <receiver>ckScaleCan</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>50</x> - <y>111</y> - </hint> - <hint type="destinationlabel"> - <x>61</x> - <y>142</y> - </hint> - </hints> - </connection> - <connection> - <sender>ckScaleCan</sender> - <signal>toggled(bool)</signal> - <receiver>spCanScale</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>133</x> - <y>143</y> - </hint> - <hint type="destinationlabel"> - <x>251</x> - <y>147</y> - </hint> - </hints> - </connection> - <connection> - <sender>ckUseCan</sender> - <signal>toggled(bool)</signal> - <receiver>dsContainer</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>119</x> - <y>114</y> - </hint> - <hint type="destinationlabel"> - <x>324</x> - <y>114</y> - </hint> - </hints> - </connection> - <connection> - <sender>ckUseCorrections</sender> - <signal>toggled(bool)</signal> - <receiver>dsCorrections</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>119</x> - <y>167</y> - </hint> - <hint type="destinationlabel"> - <x>324</x> - <y>167</y> - </hint> - </hints> - </connection> - </connections> -</ui> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>MantidQt::MantidWidgets::DataSelector</class> + <extends>QWidget</extends> + <header>MantidQtMantidWidgets/DataSelector.h</header> + </customwidget> + <customwidget> + <class>MantidQt::MantidWidgets::PreviewPlot</class> + <extends>QWidget</extends> + <header>MantidQtMantidWidgets/PreviewPlot.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>ckUseCan</sender> + <signal>toggled(bool)</signal> + <receiver>ckScaleCan</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>50</x> + <y>111</y> + </hint> + <hint type="destinationlabel"> + <x>61</x> + <y>142</y> + </hint> + </hints> + </connection> + <connection> + <sender>ckScaleCan</sender> + <signal>toggled(bool)</signal> + <receiver>spCanScale</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>133</x> + <y>143</y> + </hint> + <hint type="destinationlabel"> + <x>251</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>ckUseCan</sender> + <signal>toggled(bool)</signal> + <receiver>dsContainer</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>114</y> + </hint> + <hint type="destinationlabel"> + <x>324</x> + <y>114</y> + </hint> + </hints> + </connection> + <connection> + <sender>ckUseCorrections</sender> + <signal>toggled(bool)</signal> + <receiver>dsCorrections</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>119</x> + <y>167</y> + </hint> + <hint type="destinationlabel"> + <x>324</x> + <y>167</y> + </hint> + </hints> + </connection> + </connections> +</ui> \ No newline at end of file diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MantidEVWorker.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MantidEVWorker.h index 5f92a905fa2eb2ad2d050a7bdb9ae23c4fc470f6..c1f4c9b00a26930e661832b3baca69afcd10c6bf 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MantidEVWorker.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MantidEVWorker.h @@ -143,11 +143,13 @@ public: /// Select conventional cell using the cell type and centering bool selectCellOfType( const std::string & peaks_ws_name, const std::string & cell_type, - const std::string & centering ); + const std::string & centering, + bool allow_perm); /// Select conventional cell using the form number from the Mighell paper bool selectCellWithForm( const std::string & peaks_ws_name, - size_t form_num ); + size_t form_num, + bool allow_perm); /// Apply a mapping to the h,k,l indices and the UB matrix bool changeHKL( const std::string & peaks_ws_name, diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit/MultiDatasetFit.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit/MultiDatasetFit.h index bac813b4345df23a81cca6dbf2d9d193ae7750b5..63956ba671fa2fb3a0e926a3a73cc14b0d30412a 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit/MultiDatasetFit.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit/MultiDatasetFit.h @@ -56,7 +56,7 @@ public: /// Destructor ~MultiDatasetFit(); /// Get the name of the output workspace - QString getOutputWorkspaceName() const {return QString::fromStdString(m_outputWorkspaceName);} + QString getOutputWorkspaceName() const; /// Workspace name for the i-th spectrum std::string getWorkspaceName(int i) const; /// Workspace index of the i-th spectrum @@ -90,6 +90,7 @@ private slots: void enableRange(); void checkFittingType(); void setLogNames(); + void invalidateOutput(); protected: virtual void initLayout(); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSConstants.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSConstants.h index 77286a688dd659ce14e42d961638e0a07329be15..fec5247513bd2620f1dff9fd8ae13370afaaf479 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSConstants.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSConstants.h @@ -13,9 +13,16 @@ class SANSConstants public: SANSConstants(); ~SANSConstants(); + + // Python related QString getPythonSuccessKeyword(); QString getPythonEmptyKeyword(); QString getPythonTrueKeyword(); + + // Input related + double getMaxDoubleValue(); + int getMaxIntValue(); + int getDecimals(); }; } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h index 3c144a09848d50bd922b39a64893968f03f48ca5..7d2c8cac639627a40a5c281b436d5d9b6a634dcd 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/SANSRunWindow.h @@ -374,6 +374,10 @@ private: QMap<Tab, QString> m_helpPageUrls; /// SANS constants SANSConstants m_constants; + /// Validators + QValidator* m_mustBeDouble; + QValidator* m_doubleValidatorZeroToMax; + QValidator* m_intValidatorZeroToMax; void initAnalysDetTab(); void makeValidator(QLabel * const newValid, QWidget * control, QWidget * tab, const QString & errorMsg); @@ -408,6 +412,12 @@ private: void initTransmissionSettings(); /// Set all trans fields to a certain enabled state void resetAllTransFields(); + /// Check the validty of inputs + bool areSettingsValid(); + /// Check setting for wavelengths and Q values + void checkWaveLengthAndQValues(bool &isValid, QString &message, + QLineEdit *min, QLineEdit *max, + QComboBox *selection, QString type); UserSubWindow * slicingWindow; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp index 2f2d9ab63e3e55fe9ac8011ad5335199da386f34..0b0be67c9f4055f395f0eedcd8b963851a9b1b64 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp @@ -8,6 +8,8 @@ #include "MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h" #include "MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h" +#include <fstream> + #include <boost/lexical_cast.hpp> #include <Poco/File.h> @@ -28,6 +30,8 @@ Mantid::Kernel::Logger g_log("EngineeringDiffractionGUI"); const std::string EnggDiffractionPresenter::g_enginxStr = "ENGINX"; // discouraged at the moment const bool EnggDiffractionPresenter::g_askUserCalibFilename = false; +const std::string EnggDiffractionPresenter::g_vanIntegrationWSName = + "engggui_vanadium_integration_ws"; EnggDiffractionPresenter::EnggDiffractionPresenter(IEnggDiffractionView *view) : m_workerThread(NULL), m_calibFinishedOK(false), m_focusFinishedOK(false), @@ -53,8 +57,7 @@ void EnggDiffractionPresenter::cleanup() { if (m_workerThread) { if (m_workerThread->isRunning()) { g_log.notice() << "A calibration process is currently running, shutting " - "it down immediately..." - << std::endl; + "it down immediately..." << std::endl; m_workerThread->wait(10); } delete m_workerThread; @@ -80,7 +83,19 @@ void EnggDiffractionPresenter::notify( break; case IEnggDiffractionPresenter::FocusRun: - processFocusRun(); + processFocusBasic(); + break; + + case IEnggDiffractionPresenter::FocusCropped: + processFocusCropped(); + break; + + case IEnggDiffractionPresenter::FocusTexture: + processFocusTexture(); + break; + + case IEnggDiffractionPresenter::ResetFocus: + processResetFocus(); break; case IEnggDiffractionPresenter::LogMsg: @@ -121,8 +136,8 @@ void EnggDiffractionPresenter::processLoadExistingCalib() { } void EnggDiffractionPresenter::processCalcCalib() { - std::string vanNo = m_view->newVanadiumNo(); - std::string ceriaNo = m_view->newCeriaNo(); + const std::string vanNo = m_view->newVanadiumNo(); + const std::string ceriaNo = m_view->newCeriaNo(); try { inputChecksBeforeCalibrate(vanNo, ceriaNo); } catch (std::invalid_argument &ia) { @@ -130,10 +145,8 @@ void EnggDiffractionPresenter::processCalcCalib() { ia.what()); return; } - g_log.notice() << "EnggDiffraction GUI: starting new calibration. This may " - "take a few seconds... " - << std::endl; + "take a few seconds... " << std::endl; const std::string outFilename = outputCalibFilename(vanNo, ceriaNo); @@ -144,31 +157,96 @@ void EnggDiffractionPresenter::processCalcCalib() { startAsyncCalibWorker(outFilename, vanNo, ceriaNo); } -void EnggDiffractionPresenter::processFocusRun() { - std::string runNo = m_view->focusingRunNo(); - int bank = m_view->focusingBank(); +void EnggDiffractionPresenter::processFocusBasic() { + const std::string runNo = m_view->focusingRunNo(); + const std::vector<bool> banks = m_view->focusingBanks(); + try { - inputChecksBeforeFocus(runNo, bank); + inputChecksBeforeFocusBasic(runNo, banks); } catch (std::invalid_argument &ia) { m_view->userWarning("Error in the inputs required to focus a run", ia.what()); return; } - g_log.notice() << "EnggDiffraction GUI: starting new focusing. This may take " - "some seconds... " - << std::endl; + startFocusing(runNo, banks, "", ""); +} + +void EnggDiffractionPresenter::processFocusCropped() { + const std::string runNo = m_view->focusingCroppedRunNo(); + const std::vector<bool> banks = m_view->focusingBanks(); + const std::string specNos = m_view->focusingCroppedSpectrumIDs(); + + try { + inputChecksBeforeFocusCropped(runNo, banks, specNos); + } catch (std::invalid_argument &ia) { + m_view->userWarning( + "Error in the inputs required to focus a run (in cropped mode)", + ia.what()); + return; + } + + startFocusing(runNo, banks, specNos, ""); +} + +void EnggDiffractionPresenter::processFocusTexture() { + const std::string runNo = m_view->focusingTextureRunNo(); + const std::string dgFile = m_view->focusingTextureGroupingFile(); + + try { + inputChecksBeforeFocusTexture(runNo, dgFile); + } catch (std::invalid_argument &ia) { + m_view->userWarning( + "Error in the inputs required to focus a run (in texture mode)", + ia.what()); + return; + } + + startFocusing(runNo, std::vector<bool>(), "", dgFile); +} + +/** + * Starts a focusing worker, for different modes depending on the + * inputs provided. Assumes that the inputs have been checked by the + * respective specific processFocus methods (for normal, cropped, + * texture, etc. focusing). + * + * @param runNo run/file number to focus + * @param banks banks to include in the focusing, processed one at a time + * + * @param specNos list of spectra to use when focusing. If not empty + * this implies focusing in cropped mode. + * + * @param dgFile detector grouping file to define banks (texture). If + * not empty, this implies focusing in texture mode. + */ +void EnggDiffractionPresenter::startFocusing(const std::string &runNo, + const std::vector<bool> &banks, + const std::string &specNos, + const std::string &dgFile) { + + std::string optMsg = ""; + if (!specNos.empty()) { + optMsg = " (cropped)"; + } else if (!dgFile.empty()) { + optMsg = " (texture)"; + } + g_log.notice() << "EnggDiffraction GUI: starting new focusing" << optMsg + << ". This may take some seconds... " << std::endl; const std::string focusDir = m_view->focusingDir(); - const std::string outFilename = outputFocusFilename(runNo, bank); + const std::vector<std::string> outFilenames = + outputFocusFilenames(runNo, banks); m_view->enableCalibrateAndFocusActions(false); // GUI-blocking alternative: - // doFocusRun(focusDir, outFilename, runNo, bank) + // doFocusRun(focusDir, outFilenames, runNo, banks, specNos, dgFile) // focusingFinished() - startAsyncFocusWorker(focusDir, outFilename, runNo, bank); + startAsyncFocusWorker(focusDir, outFilenames, runNo, banks, specNos, dgFile); } +void EnggDiffractionPresenter::processResetFocus() { m_view->resetFocus(); } + void EnggDiffractionPresenter::processLogMsg() { std::vector<std::string> msgs = m_view->logMsgs(); for (size_t i = 0; i < msgs.size(); i++) { @@ -336,9 +414,10 @@ void EnggDiffractionPresenter::parseCalibrateFilename(const std::string &path, * @param vanNo vanadium run number * @param ceriaNo ceria run number */ -void EnggDiffractionPresenter::startAsyncCalibWorker( - const std::string &outFilename, const std::string &vanNo, - const std::string &ceriaNo) { +void +EnggDiffractionPresenter::startAsyncCalibWorker(const std::string &outFilename, + const std::string &vanNo, + const std::string &ceriaNo) { delete m_workerThread; m_workerThread = new QThread(this); EnggDiffWorker *worker = @@ -387,13 +466,11 @@ void EnggDiffractionPresenter::doNewCalibration(const std::string &outFilename, } catch (std::runtime_error &) { g_log.error() << "The calibration calculations failed. One of the " "algorithms did not execute correctly. See log messages " - "for details. " - << std::endl; + "for details. " << std::endl; } catch (std::invalid_argument &) { g_log.error() << "The calibration calculations failed. Some input properties " - "were not valid. See log messages for details. " - << std::endl; + "were not valid. See log messages for details. " << std::endl; } // restore normal data search paths conf.setDataSearchDirs(tmpDirs); @@ -548,26 +625,118 @@ void EnggDiffractionPresenter::doCalib(const EnggDiffCalibSettings &cs, } /** - * Performs several checks on the current focusing inputs and - * settings. This should be done before starting any focus work. The - * message return should be shown to the user as a visible message - * (pop-up, error log, etc.) + * Perform checks specific to normal/basic run focusing in addition to + * the general checks for any focusing (as done by + * inputChecksBeforeFocus() which is called from this method). Use + * always before running 'Focus' + * + * @param runNo run number to focus + * @param banks which banks to consider in the focusing + * + * @throws std::invalid_argument with an informative message. + */ +void EnggDiffractionPresenter::inputChecksBeforeFocusBasic( + const std::string &runNo, const std::vector<bool> &banks) { + if (runNo.empty()) { + const std::string msg = "The sample run number to focus cannot be " + "empty and must be an integer number."; + throw std::invalid_argument(msg); + } + + inputChecksBanks(banks); + + inputChecksBeforeFocus(); +} + +/** + * Perform checks specific to focusing in "cropped" mode, in addition + * to the general checks for any focusing (as done by + * inputChecksBeforeFocus() which is called from this method). Use + * always before running 'FocusCropped' * * @param runNo run number to focus - * @param bank bank to focus + * @param banks which banks to consider in the focusing + * @param specNos list of spectra (as usual csv list of spectra in Mantid) * * @throws std::invalid_argument with an informative message. */ -void EnggDiffractionPresenter::inputChecksBeforeFocus(const std::string &runNo, - int bank) { +void EnggDiffractionPresenter::inputChecksBeforeFocusCropped( + const std::string &runNo, const std::vector<bool> &banks, + const std::string &specNos) { if (runNo.empty()) { + throw std::invalid_argument("To focus cropped the sample run number cannot " + "be empty and must be an integer number."); + } + + if (specNos.empty()) { + throw std::invalid_argument("The list of spectrum IDs cannot be empty when " + "focusing in 'cropped' mode."); + } + + inputChecksBanks(banks); + + inputChecksBeforeFocus(); +} + +/** + * Perform checks specific to focusing in "texture" mode, in addition + * to the general checks for any focusing (as done by + * inputChecksBeforeFocus() which is called from this method). Use + * always before running 'FocusCropped' + * + * @param runNo run number to focus + * @param dgFile file with detector grouping info + * + * @throws std::invalid_argument with an informative message. + */ +void EnggDiffractionPresenter::inputChecksBeforeFocusTexture( + const std::string &runNo, const std::string &dgFile) { + if (runNo.empty()) { + throw std::invalid_argument("To focus texture banks the sample run number " + "cannot be empty and must be an integer " + "number."); + } + + if (dgFile.empty()) { + throw std::invalid_argument("A detector grouping file needs to be " + "specified when focusing texture banks."); + } + Poco::File dgf(dgFile); + if (!dgf.exists()) { throw std::invalid_argument( - "The sample run number cannot be empty and must be an integer number."); + "The detector grouping file coult not be found: " + dgFile); } - if (bank < 1) { - throw std::invalid_argument("The bank number must be a positive integer."); + + inputChecksBeforeFocus(); +} + +void +EnggDiffractionPresenter::inputChecksBanks(const std::vector<bool> &banks) { + if (0 == banks.size()) { + const std::string msg = + "Error in specification of banks found when starting the " + "focusing process. Cannot continue."; + g_log.error() << msg << std::endl; + throw std::invalid_argument(msg); + } + if (banks.end() == std::find(banks.begin(), banks.end(), true)) { + const std::string msg = + "EnggDiffraction GUI: not focusing, as none of the banks " + "have been selected. You probably forgot to select at least one."; + g_log.warning() << msg << std::endl; + throw std::invalid_argument(msg); } +} +/** + * Performs several checks on the current focusing inputs and + * settings. This should be done before starting any focus work. The + * message return should be shown to the user as a visible message + * (pop-up, error log, etc.) + * + * @throws std::invalid_argument with an informative message. + */ +void EnggDiffractionPresenter::inputChecksBeforeFocus() { EnggDiffCalibSettings cs = m_view->currentCalibSettings(); const std::string pixelCalib = cs.m_pixelCalibFilename; if (pixelCalib.empty()) { @@ -577,23 +746,49 @@ void EnggDiffractionPresenter::inputChecksBeforeFocus(const std::string &runNo, } /** - * Builds the name of the output focused file, given the sample run - * number and the bank to focus. + * Builds the names of the output focused files (one per bank), given + * the sample run number and which banks should be focused. * * @param runNo number of the run for which we want a focused output * file name * - * @param bank bank number which is normally used as a suffix + * @param banks for every bank, (true/false) to consider it or not for + * the focusing * - * @return filename (without the full path) + * @return filenames (without the full path) */ +std::vector<std::string> +EnggDiffractionPresenter::outputFocusFilenames(const std::string &runNo, + const std::vector<bool> &banks) { + const std::string instStr = m_view->currentInstrument(); + + std::vector<std::string> res; + for (size_t b = 1; b <= banks.size(); b++) { + res.push_back(instStr + "_" + runNo + "_focused_bank_" + + boost::lexical_cast<std::string>(b) + ".nxs"); + } + + return res; +} + std::string -EnggDiffractionPresenter::outputFocusFilename(const std::string &runNo, - int bank) { +EnggDiffractionPresenter::outputFocusCroppedFilename(const std::string &runNo) { const std::string instStr = m_view->currentInstrument(); - return instStr + runNo + "_focused_bank_" + - boost::lexical_cast<std::string>(bank); + return instStr + "_" + runNo + "_focused_cropped.nxs"; +} + +std::vector<std::string> EnggDiffractionPresenter::outputFocusTextureFilenames( + const std::string &runNo, const std::vector<size_t> &bankIDs) { + const std::string instStr = m_view->currentInstrument(); + + std::vector<std::string> res; + for (size_t b = 0; b < bankIDs.size(); b++) { + res.push_back(instStr + "_" + runNo + "_focused_texture_bank_" + + boost::lexical_cast<std::string>(bankIDs[b]) + ".nxs"); + } + + return res; } /** @@ -603,17 +798,21 @@ EnggDiffractionPresenter::outputFocusFilename(const std::string &runNo, * Q_OBJECT. * * @param dir directory (full path) for the focused output files - * @param outFilename full name for the output focused run -o * @param runNo input run number - * @param bank instrument bank to focus + * @param outFilenames full names for the output focused runs + * @param runNo input run number + * @param banks instrument bank to focus + * @param specNos list of spectra (as usual csv list of spectra in Mantid) + * @param dgFile detector grouping file name */ void EnggDiffractionPresenter::startAsyncFocusWorker( - const std::string &dir, const std::string &outFilename, - const std::string &runNo, int bank) { + const std::string &dir, const std::vector<std::string> &outFilenames, + const std::string &runNo, const std::vector<bool> &banks, + const std::string &specNos, const std::string &dgFile) { + delete m_workerThread; m_workerThread = new QThread(this); - EnggDiffWorker *worker = - new EnggDiffWorker(this, dir, outFilename, runNo, bank); + EnggDiffWorker *worker = new EnggDiffWorker(this, dir, outFilenames, runNo, + banks, specNos, dgFile); worker->moveToThread(m_workerThread); connect(m_workerThread, SIGNAL(started()), worker, SLOT(focus())); @@ -631,20 +830,25 @@ void EnggDiffractionPresenter::startAsyncFocusWorker( * push or similar from the user. * * @param dir directory (full path) for the output focused files - * @param outFilename name for the output focused file + * @param outFilenames names for the output focused files (one per bank) * @param runNo input run number - * @param bank bank number for the focusing + * + * @param specNos list of spectra to use when focusing. Not empty + * implies focusing in cropped mode. + * + * @param dgFile detector grouping file to define banks (texture). Not + * empty implies focusing in texture mode. + * + * @param banks for every bank, (true/false) to consider it or not for + * the focusing */ -void EnggDiffractionPresenter::doFocusRun(const std::string &dir, - const std::string &outFilename, - const std::string &runNo, int bank) { - g_log.notice() << "Generating new focused file (bank " + - boost::lexical_cast<std::string>(bank) + ") for run " + - runNo + " into: " - << outFilename << std::endl; +void EnggDiffractionPresenter::doFocusRun( + const std::string &dir, const std::vector<std::string> &outFilenames, + const std::string &runNo, const std::vector<bool> &banks, + const std::string &specNos, const std::string &dgFile) { - Poco::Path fpath(dir); - const std::string fullFilename = fpath.append(outFilename).toString(); + g_log.notice() << "Generating new focusing workspace(s) and file(s) into " + "this directory: " << dir << std::endl; // TODO: this is almost 100% common with doNewCalibrate() - refactor EnggDiffCalibSettings cs = m_view->currentCalibSettings(); @@ -660,24 +864,121 @@ void EnggDiffractionPresenter::doFocusRun(const std::string &dir, conf.appendDataSearchDir(cs.m_inputDirRaw); } - try { - doFocusing(cs, fullFilename, runNo, bank); - m_focusFinishedOK = true; - } catch (std::runtime_error &) { - g_log.error() << "The focusing calculations failed. One of the algorithms" - "did not execute correctly. See log messages for details." - << std::endl; - } catch (std::invalid_argument &ia) { - g_log.error() - << "The focusing failed. Some input properties were not valid. " - "See log messages for details. Error: " - << ia.what() << std::endl; + // Prepare special inputs for "texture" focusing + std::vector<size_t> bankIDs; + std::vector<std::string> effectiveFilenames; + std::vector<std::string> specs; + if (!specNos.empty()) { + // just to iterate once, but there's no real bank here + bankIDs.push_back(0); + specs.push_back(specNos); // one spectrum IDs list given by the user + effectiveFilenames.push_back(outputFocusCroppedFilename(runNo)); + } else { + if (dgFile.empty()) { + for (size_t bidx = 0; bidx < banks.size(); bidx++) { + if (banks[bidx]) { + bankIDs.push_back(bidx + 1); + specs.push_back(""); + effectiveFilenames.push_back(outFilenames[bidx]); + } + } + } else { + try { + loadDetectorGroupingCSV(dgFile, bankIDs, specs); + } catch (std::runtime_error &re) { + g_log.error() << "Error loading detector grouping file: " + dgFile + + ". Detailed error: " + re.what() << std::endl; + bankIDs.clear(); + specs.clear(); + } + effectiveFilenames = outputFocusTextureFilenames(runNo, bankIDs); + } + } + + // focus all requested banks + for (size_t idx = 0; idx < bankIDs.size(); idx++) { + + Poco::Path fpath(dir); + const std::string fullFilename = + fpath.append(effectiveFilenames[idx]).toString(); + g_log.notice() << "Generating new focused file (bank " + + boost::lexical_cast<std::string>(bankIDs[idx]) + + ") for run " + runNo + + " into: " << effectiveFilenames[idx] << std::endl; + try { + doFocusing(cs, fullFilename, runNo, bankIDs[idx], specs[idx], dgFile); + m_focusFinishedOK = true; + } catch (std::runtime_error &) { + g_log.error() + << "The focusing calculations failed. One of the algorithms" + "did not execute correctly. See log messages for details." + << std::endl; + } catch (std::invalid_argument &ia) { + g_log.error() + << "The focusing failed. Some input properties were not valid. " + "See log messages for details. Error: " << ia.what() << std::endl; + } } // restore initial data search paths conf.setDataSearchDirs(tmpDirs); } +void EnggDiffractionPresenter::loadDetectorGroupingCSV( + const std::string &dgFile, std::vector<size_t> &bankIDs, + std::vector<std::string> &specs) { + const char commentChar = '#'; + const std::string delim = ","; + + std::ifstream file(dgFile.c_str()); + if (!file.is_open()) { + throw std::runtime_error("Failed to open file."); + } + + bankIDs.clear(); + specs.clear(); + std::string line; + for (size_t li = 1; getline(file, line); li++) { + if (line.empty() || commentChar == line[0]) + continue; + + auto delimPos = line.find_first_of(delim); + if (std::string::npos == delimPos) { + throw std::runtime_error( + "In file '" + dgFile + "', wrong format in line: " + + boost::lexical_cast<std::string>(li) + + " which does not containe any delimiters (comma, etc.)"); + } + + try { + const std::string bstr = line.substr(0, delimPos); + const std::string spec = line.substr(delimPos + 1, std::string::npos); + + if (bstr.empty()) { + throw std::runtime_error( + "In file '" + dgFile + "', wrong format in line: " + + boost::lexical_cast<std::string>(li) + ", the bank ID is empty!"); + } + if (spec.empty()) { + throw std::runtime_error("In file '" + dgFile + + "', wrong format in line: " + + boost::lexical_cast<std::string>(li) + + ", the list of spectrum IDs is empty!"); + } + + size_t bankID = boost::lexical_cast<size_t>(bstr); + bankIDs.push_back(bankID); + specs.push_back(spec); + } catch (std::runtime_error &re) { + throw std::runtime_error( + "In file '" + dgFile + + "', issue found when trying to interpret line: " + + boost::lexical_cast<std::string>(li) + ". Error description: " + + re.what()); + } + } +} + /** * Method (Qt slot) to call when the focusing work has finished, * possibly from a separate thread but sometimes not (as in this @@ -692,7 +993,8 @@ void EnggDiffractionPresenter::focusingFinished() { g_log.warning() << "The cablibration did not finished correctly." << std::endl; } else { - g_log.notice() << "Focusing finished - focused run ready." << std::endl; + g_log.notice() << "Focusing finished - focused run(s) are ready." + << std::endl; } if (m_workerThread) { delete m_workerThread; @@ -707,13 +1009,23 @@ void EnggDiffractionPresenter::focusingFinished() { * @param cs user settings for calibration (this does not calibrate but * uses calibration input files such as vanadium runs * - * @param fullFilename full paht for the output (focused) filename + * @param fullFilename full path for the output (focused) filename + * * @param runNo input run to focus - * @param bank instrument bank to focus + * + * @param bank instrument bank number to focus + * + * @param specNos string specifying a list of spectra (for cropped + * focusing), only considered if not empty + * + * @param dgFile detector grouping file name. If not empty implies + * texture focusing */ void EnggDiffractionPresenter::doFocusing(const EnggDiffCalibSettings &cs, const std::string &fullFilename, - const std::string &runNo, int bank) { + const std::string &runNo, size_t bank, + const std::string &specNos, + const std::string &dgFile) { ITableWorkspace_sptr vanIntegWS; MatrixWorkspace_sptr vanCurvesWS; MatrixWorkspace_sptr inWS; @@ -743,7 +1055,17 @@ void EnggDiffractionPresenter::doFocusing(const EnggDiffCalibSettings &cs, throw; } - const std::string outWSName = "engggui_focusing_output_ws"; + std::string outWSName; + if (!dgFile.empty()) { + outWSName = "engggui_focusing_output_ws_texture_bank_" + + boost::lexical_cast<std::string>(bank); + } else if (specNos.empty()) { + outWSName = "engggui_focusing_output_ws_bank_" + + boost::lexical_cast<std::string>(bank); + } else { + outWSName = "engggui_focusing_output_ws_cropped"; + } + try { auto alg = Algorithm::fromString("EnggFocus"); alg->initialize(); @@ -751,14 +1073,19 @@ void EnggDiffractionPresenter::doFocusing(const EnggDiffCalibSettings &cs, alg->setProperty("OutputWorkspace", outWSName); alg->setProperty("VanIntegrationWorkspace", vanIntegWS); alg->setProperty("VanCurvesWorkspace", vanCurvesWS); - alg->setPropertyValue("Bank", boost::lexical_cast<std::string>(bank)); + // cropped / normal focusing + if (specNos.empty()) { + alg->setPropertyValue("Bank", boost::lexical_cast<std::string>(bank)); + } else { + alg->setPropertyValue("SpectrumNumbers", specNos); + } // TODO: use detector positions (from calibrate full) when available // alg->setProperty(DetectorPositions, TableWorkspace) alg->execute(); - bool plotFocusedWS = m_view->focusedOutWorkspace(); + const bool plotFocusedWS = m_view->focusedOutWorkspace(); if (plotFocusedWS == true) { - m_view->plotFocusedSpectrum(); + m_view->plotFocusedSpectrum(outWSName); } } catch (std::runtime_error &re) { @@ -833,8 +1160,7 @@ void EnggDiffractionPresenter::loadOrCalcVanadiumWorkspaces( "This is possibly because some of the settings are not " "consistent. Please check the log messages for " "details. Details: " + - std::string(ia.what()) - << std::endl; + std::string(ia.what()) << std::endl; throw; } catch (std::runtime_error &re) { g_log.error() << "Failed to calculate Vanadium corrections. " @@ -843,8 +1169,7 @@ void EnggDiffractionPresenter::loadOrCalcVanadiumWorkspaces( "There was no obvious error in the input properties " "but the algorithm failed. Please check the log " "messages for details." + - std::string(re.what()) - << std::endl; + std::string(re.what()) << std::endl; throw; } } else { @@ -942,7 +1267,7 @@ void EnggDiffractionPresenter::loadVanadiumPrecalcWorkspaces( auto alg = Algorithm::fromString("LoadNexus"); alg->initialize(); alg->setPropertyValue("Filename", preIntegFilename); - std::string integWSName = "engggui_vanadium_integration_ws"; + std::string integWSName = g_vanIntegrationWSName; alg->setPropertyValue("OutputWorkspace", integWSName); alg->execute(); // alg->getProperty("OutputWorkspace"); @@ -983,15 +1308,15 @@ void EnggDiffractionPresenter::calcVanadiumWorkspaces( load->execute(); AnalysisDataServiceImpl &ADS = Mantid::API::AnalysisDataService::Instance(); MatrixWorkspace_sptr vanWS = ADS.retrieveWS<MatrixWorkspace>(vanWSName); - // TODO: maybe use setChild() and then load->getProperty("OutputWorkspace"); + // TODO?: maybe use setChild() and then load->getProperty("OutputWorkspace"); auto alg = Algorithm::fromString("EnggVanadiumCorrections"); alg->initialize(); alg->setProperty("VanadiumWorkspace", vanWS); - std::string integName = "engggui_van_integration_ws"; - alg->setPropertyValue("IntegrationWorkspace", integName); + std::string integName = g_vanIntegrationWSName; + alg->setPropertyValue("OutIntegrationWorkspace", integName); std::string curvesName = "engggui_van_curves_ws"; - alg->setPropertyValue("CurvesWorkspace", curvesName); + alg->setPropertyValue("OutCurvesWorkspace", curvesName); alg->execute(); ADS.remove(vanWSName); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp index 956e47f54fcffc425b15dc1f97c26a3a646ed956..c594b5b2732fcbf545042214fcd30a80cc6dc117 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp @@ -40,6 +40,11 @@ const std::string EnggDiffractionViewQtGUI::g_pixelCalibExt = "(*.csv *.nxs *.nexus);;" "Other extensions/all files (*.*)"; +const std::string EnggDiffractionViewQtGUI::g_DetGrpExtStr = + "Detector Grouping File: CSV " + "(*.csv *.txt);;" + "Other extensions/all files (*.*)"; + const std::string EnggDiffractionViewQtGUI::m_settingsGroup = "CustomInterfaces/EnggDiffractionView"; @@ -146,6 +151,18 @@ void EnggDiffractionViewQtGUI::doSetupTabSettings() { void EnggDiffractionViewQtGUI::doSetupTabFocus() { connect(m_uiTabFocus.pushButton_focus, SIGNAL(released()), this, SLOT(focusClicked())); + + connect(m_uiTabFocus.pushButton_focus_cropped, SIGNAL(released()), this, + SLOT(focusCroppedClicked())); + + connect(m_uiTabFocus.pushButton_texture_browse_grouping_file, + SIGNAL(released()), this, SLOT(browseTextureDetGroupingFile())); + + connect(m_uiTabFocus.pushButton_focus_texture, SIGNAL(released()), this, + SLOT(focusTextureClicked())); + + connect(m_uiTabFocus.pushButton_reset, SIGNAL(released()), this, + SLOT(focusResetClicked())); } void EnggDiffractionViewQtGUI::doSetupGeneralWidgets() { @@ -180,9 +197,43 @@ void EnggDiffractionViewQtGUI::readSettings() { m_uiTabCalib.lineEdit_new_ceria_num->setText( qs.value("user-params-new-ceria-num", "").toString()); + m_uiTabCalib.lineEdit_new_vanadium_num->setText( + qs.value("user-params-new-vanadium-num", "").toString()); + + m_uiTabCalib.lineEdit_new_ceria_num->setText( + qs.value("user-params-new-ceria-num", "").toString()); + + // user params - focusing + m_uiTabFocus.lineEdit_run_num->setText( + qs.value("user-params-focus-runno", "").toString()); + + qs.beginReadArray("user-params-focus-bank_i"); + qs.setArrayIndex(0); + m_uiTabFocus.checkBox_focus_bank1->setChecked(qs.value("value", true).toBool()); + qs.setArrayIndex(1); + m_uiTabFocus.checkBox_focus_bank2->setChecked(qs.value("value", true).toBool()); + qs.endArray(); + + m_uiTabFocus.lineEdit_cropped_run_num->setText( + qs.value("user-params-focus-cropped-runno", "").toString()); + + m_uiTabFocus.lineEdit_cropped_spec_ids->setText( + qs.value("user-params-focus-cropped-spectrum-nos", "").toString()); + + m_uiTabFocus.lineEdit_texture_run_num->setText( + qs.value("user-params-focus-texture-runno", "").toString()); + + m_uiTabFocus.lineEdit_texture_grouping_file->setText( + qs.value("user-params-focus-texture-detector-grouping-file", "") + .toString()); + + m_uiTabFocus.checkBox_FocusedWS->setChecked( + qs.value("user-params-focus-plot-ws", true).toBool()); + QString lastPath = MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - // TODO: this should become << >> operators on EnggDiffCalibSettings + // TODO: this should become << >> operators on + // EnggDiffCalibSettings m_calibSettings.m_inputDirCalib = qs.value("input-dir-calib-files", lastPath).toString().toStdString(); m_calibSettings.m_inputDirRaw = @@ -225,6 +276,29 @@ void EnggDiffractionViewQtGUI::saveSettings() const { qs.setValue("user-params-new-ceria-num", m_uiTabCalib.lineEdit_new_ceria_num->text()); + // user params - focusing + qs.setValue("user-params-focus-runno", m_uiTabFocus.lineEdit_run_num->text()); + + qs.beginWriteArray("user-params-focus-bank_i"); + qs.setArrayIndex(0); + qs.setValue("value", m_uiTabFocus.checkBox_focus_bank1->isChecked()); + qs.setArrayIndex(1); + qs.setValue("value", m_uiTabFocus.checkBox_focus_bank2->isChecked()); + qs.endArray(); + + qs.setValue("user-params-focus-cropped-runno", + m_uiTabFocus.lineEdit_cropped_run_num->text()); + qs.setValue("user-params-focus-cropped-spectrum-nos", + m_uiTabFocus.lineEdit_cropped_spec_ids->text()); + + qs.setValue("user-params-focus-texture-runno", + m_uiTabFocus.lineEdit_texture_run_num->text()); + qs.setValue("user-params-focus-texture-detector-grouping-file", + m_uiTabFocus.lineEdit_texture_grouping_file->text()); + + qs.setValue("user-params-focus-plot-ws", + m_uiTabFocus.checkBox_FocusedWS->checkState()); + // TODO: this should become << >> operators on EnggDiffCalibSettings qs.setValue("input-dir-calib-files", QString::fromStdString(m_calibSettings.m_inputDirCalib)); @@ -340,23 +414,42 @@ void EnggDiffractionViewQtGUI::enableCalibrateAndFocusActions(bool enable) { m_uiTabFocus.lineEdit_run_num->setEnabled(enable); m_uiTabFocus.pushButton_focus->setEnabled(enable); m_uiTabFocus.checkBox_FocusedWS->setEnabled(enable); + + m_uiTabFocus.pushButton_focus->setEnabled(enable); + m_uiTabFocus.pushButton_focus_cropped->setEnabled(enable); + m_uiTabFocus.pushButton_focus_texture->setEnabled(enable); } -void EnggDiffractionViewQtGUI::plotFocusedSpectrum() { - std::string pyCode = "plotSpectrum('engggui_focusing_output_ws', 0)"; +void EnggDiffractionViewQtGUI::plotFocusedSpectrum(const std::string &wsName) { + std::string pyCode = "plotSpectrum('" + wsName + "', 0)"; - std::string status = runPythonCode(QString::fromStdString(pyCode), false).toStdString(); - m_logMsgs.push_back( - "Run Python code to save output file, with status string: " + status); + std::string status = + runPythonCode(QString::fromStdString(pyCode), false).toStdString(); + m_logMsgs.push_back("Plotted output focused data, with status string " + + status); m_presenter->notify(IEnggDiffractionPresenter::LogMsg); } -void EnggDiffractionViewQtGUI::writeOutCalibFile( - const std::string &outFilename, const std::vector<double> &difc, - const std::vector<double> &tzero) { +void EnggDiffractionViewQtGUI::resetFocus() { + m_uiTabFocus.lineEdit_run_num->setText(""); + m_uiTabFocus.checkBox_focus_bank1->setChecked(true); + m_uiTabFocus.checkBox_focus_bank2->setChecked(true); + + m_uiTabFocus.lineEdit_cropped_run_num->setText(""); + m_uiTabFocus.lineEdit_cropped_spec_ids->setText(""); + + m_uiTabFocus.lineEdit_texture_run_num->setText(""); + m_uiTabFocus.lineEdit_texture_grouping_file->setText(""); +} + +void +EnggDiffractionViewQtGUI::writeOutCalibFile(const std::string &outFilename, + const std::vector<double> &difc, + const std::vector<double> &tzero) { // TODO: this is horrible and should not last much here. // Avoid running Python code - // Update this as soon as we have a more stable way of generating IPARM files + // Update this as soon as we have a more stable way of generating IPARM + // files // Writes a file doing this: // write_ENGINX_GSAS_iparam_file(output_file, difc, zero, ceria_run=241391, // vanadium_run=236516, template_file=None): @@ -421,6 +514,19 @@ void EnggDiffractionViewQtGUI::focusClicked() { m_presenter->notify(IEnggDiffractionPresenter::FocusRun); } +void EnggDiffractionViewQtGUI::focusCroppedClicked() { + m_presenter->notify(IEnggDiffractionPresenter::FocusCropped); +} + +void EnggDiffractionViewQtGUI::focusTextureClicked() { + m_presenter->notify(IEnggDiffractionPresenter::FocusTexture); +} + +void EnggDiffractionViewQtGUI::focusResetClicked() { + m_presenter->notify(IEnggDiffractionPresenter::ResetFocus); + // TODO +} + void EnggDiffractionViewQtGUI::browseInputDirCalib() { QString prevPath = QString::fromStdString(m_calibSettings.m_inputDirCalib); if (prevPath.isEmpty()) { @@ -517,17 +623,54 @@ void EnggDiffractionViewQtGUI::browseDirFocusing() { QString::fromStdString(m_focusDir)); } +void EnggDiffractionViewQtGUI::browseTextureDetGroupingFile() { + QString prevPath = QString::fromStdString(m_calibSettings.m_inputDirRaw); + if (prevPath.isEmpty()) { + prevPath = + MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); + } + + QString path(QFileDialog::getOpenFileName( + this, tr("Open detector grouping file"), prevPath, + QString::fromStdString(g_DetGrpExtStr))); + + if (path.isEmpty()) { + return; + } + + MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory(path); + m_uiTabFocus.lineEdit_texture_grouping_file->setText(path); +} + std::string EnggDiffractionViewQtGUI::focusingRunNo() const { return m_uiTabFocus.lineEdit_run_num->text().toStdString(); } +std::string EnggDiffractionViewQtGUI::focusingCroppedRunNo() const { + return m_uiTabFocus.lineEdit_cropped_run_num->text().toStdString(); +} + +std::string EnggDiffractionViewQtGUI::focusingTextureRunNo() const { + return m_uiTabFocus.lineEdit_texture_run_num->text().toStdString(); +} + std::string EnggDiffractionViewQtGUI::focusingDir() const { return m_uiTabSettings.lineEdit_dir_focusing->text().toStdString(); } -int EnggDiffractionViewQtGUI::focusingBank() const { - int idx = m_uiTabFocus.comboBox_bank_num->currentIndex(); - return m_uiTabFocus.comboBox_bank_num->itemData(idx).toInt() + 1; +std::vector<bool> EnggDiffractionViewQtGUI::focusingBanks() const { + std::vector<bool> res; + res.push_back(m_uiTabFocus.checkBox_focus_bank1->isChecked()); + res.push_back(m_uiTabFocus.checkBox_focus_bank2->isChecked()); + return res; +} + +std::string EnggDiffractionViewQtGUI::focusingCroppedSpectrumIDs() const { + return m_uiTabFocus.lineEdit_cropped_spec_ids->text().toStdString(); +} + +std::string EnggDiffractionViewQtGUI::focusingTextureGroupingFile() const { + return m_uiTabFocus.lineEdit_texture_grouping_file->text().toStdString(); } bool EnggDiffractionViewQtGUI::focusedOutWorkspace() const { diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ApplyPaalmanPings.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ApplyPaalmanPings.cpp index 042905b2189bc4cceae7a1884844230113b2705b..42270faab779a63de3226cd5b3b3cc4ebd2c2de6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ApplyPaalmanPings.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ApplyPaalmanPings.cpp @@ -1,3 +1,4 @@ + #include "MantidQtCustomInterfaces/Indirect/ApplyPaalmanPings.h" #include "MantidQtCustomInterfaces/UserInputValidator.h" #include "MantidAPI/AnalysisDataService.h" @@ -68,50 +69,97 @@ void ApplyPaalmanPings::run() { absCorProps["SampleWorkspace"] = sampleWsName.toStdString(); } - QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); - - WorkspaceGroup_sptr corrections = - AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( - correctionsWsName.toStdString()); - bool interpolateAll = false; - for (size_t i = 0; i < corrections->size(); i++) { - MatrixWorkspace_sptr factorWs = - boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i)); - - // Check for matching binning - if (sampleWs && (sampleWs->blocksize() != factorWs->blocksize())) { - int result; - if (interpolateAll) { - result = QMessageBox::Yes; - } else { - QString text = "Number of bins on sample and " + - QString::fromStdString(factorWs->name()) + - " workspace does not match.\n" + - "Would you like to interpolate this workspace to " - "match the sample?"; - - result = QMessageBox::question(NULL, tr("Interpolate corrections?"), - tr(text), QMessageBox::YesToAll, - QMessageBox::Yes, QMessageBox::No); - } + bool useCan = m_uiForm.ckUseCan->isChecked(); + if (useCan) { + QString canWsName = m_uiForm.dsContainer->getCurrentDataName(); + MatrixWorkspace_sptr canWs = + AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( + canWsName.toStdString()); + + // If not in wavelength then do conversion + std::string originalCanUnits = canWs->getAxis(0)->unit()->unitID(); + if (originalCanUnits != "Wavelength") { + g_log.information("Container workspace not in wavelength, need to " + "convert to continue."); + absCorProps["CanWorkspace"] = addConvertUnitsStep(canWs, "Wavelength"); + } else { + absCorProps["CanWorkspace"] = canWsName.toStdString(); + } + + bool useCanScale = m_uiForm.ckScaleCan->isChecked(); + if (useCanScale) { + double canScaleFactor = m_uiForm.spCanScale->value(); + applyCorrAlg->setProperty("CanScaleFactor", canScaleFactor); + } + + // Check for same binning across sample and container + if (!checkWorkspaceBinningMatches(sampleWs, canWs)) { + QString text = + "Binning on sample and container does not match." + "Would you like to rebin the sample to match the container?"; + + int result = QMessageBox::question(NULL, tr("Rebin sample?"), tr(text), + QMessageBox::Yes, QMessageBox::No, + QMessageBox::NoButton); - switch (result) { - case QMessageBox::YesToAll: - interpolateAll = true; - case QMessageBox::Yes: - addInterpolationStep(factorWs, absCorProps["SampleWorkspace"]); - break; - default: + if (result == QMessageBox::Yes) { + addRebinStep(sampleWsName, canWsName); + } else { m_batchAlgoRunner->clearQueue(); - g_log.error("ApplyPaalmanPings cannot run with corrections that do " - "not match sample binning."); + g_log.error("Cannot apply absorption corrections using a sample and " + "container with different binning."); return; } } } - applyCorrAlg->setProperty("CorrectionsWorkspace", - correctionsWsName.toStdString()); + bool useCorrections = m_uiForm.ckUseCorrections->isChecked(); + if (useCorrections) { + QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); + + WorkspaceGroup_sptr corrections = + AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( + correctionsWsName.toStdString()); + bool interpolateAll = false; + for (size_t i = 0; i < corrections->size(); i++) { + MatrixWorkspace_sptr factorWs = + boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i)); + + // Check for matching binning + if (sampleWs && (sampleWs->blocksize() != factorWs->blocksize())) { + int result; + if (interpolateAll) { + result = QMessageBox::Yes; + } else { + QString text = "Number of bins on sample and " + + QString::fromStdString(factorWs->name()) + + " workspace does not match.\n" + + "Would you like to interpolate this workspace to " + "match the sample?"; + + result = QMessageBox::question(NULL, tr("Interpolate corrections?"), + tr(text), QMessageBox::YesToAll, + QMessageBox::Yes, QMessageBox::No); + } + + switch (result) { + case QMessageBox::YesToAll: + interpolateAll = true; + case QMessageBox::Yes: + addInterpolationStep(factorWs, absCorProps["SampleWorkspace"]); + break; + default: + m_batchAlgoRunner->clearQueue(); + g_log.error("ApplyPaalmanPings cannot run with corrections that do " + "not match sample binning."); + return; + } + } + } + + applyCorrAlg->setProperty("CorrectionsWorkspace", + correctionsWsName.toStdString()); + } // Generate output workspace name int nameCutIndex = sampleWsName.lastIndexOf("_"); @@ -261,33 +309,63 @@ bool ApplyPaalmanPings::validate() { MatrixWorkspace_sptr sampleWs; - if (m_uiForm.dsCorrections->getCurrentDataName().compare("") == 0) { - uiv.addErrorMessage( - "Use Correction must contain a corrections file or workspace."); - } else { + bool useCan = m_uiForm.ckUseCan->isChecked(); + bool useCorrections = m_uiForm.ckUseCorrections->isChecked(); - QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); - WorkspaceGroup_sptr corrections = - AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( - correctionsWsName.toStdString()); - for (size_t i = 0; i < corrections->size(); i++) { - // Check it is a MatrixWorkspace - MatrixWorkspace_sptr factorWs = - boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i)); - if (!factorWs) { - QString msg = "Correction factor workspace " + QString::number(i) + - " is not a MatrixWorkspace"; - uiv.addErrorMessage(msg); - continue; - } + if (!(useCan || useCorrections)) + uiv.addErrorMessage("Must use either container subtraction or corrections"); + + if (useCan) { + uiv.checkDataSelectorIsValid("Container", m_uiForm.dsContainer); + + // Check can and sample workspaces are the same "type" (reduced or S(Q, w)) + QString sample = m_uiForm.dsSample->getCurrentDataName(); + QString sampleType = + sample.right(sample.length() - sample.lastIndexOf("_")); + QString container = m_uiForm.dsContainer->getCurrentDataName(); + QString containerType = + container.right(container.length() - container.lastIndexOf("_")); + + g_log.debug() << "Sample type is: " << sampleType.toStdString() + << std::endl; + g_log.debug() << "Can type is: " << containerType.toStdString() + << std::endl; - // Check X unit is wavelength - Mantid::Kernel::Unit_sptr xUnit = factorWs->getAxis(0)->unit(); - if (xUnit->caption() != "Wavelength") { - QString msg = "Correction factor workspace " + - QString::fromStdString(factorWs->name()) + - " is not in wavelength"; - uiv.addErrorMessage(msg); + if (containerType != sampleType) + uiv.addErrorMessage( + "Sample and can workspaces must contain the same type of data."); + } + + if (useCorrections) { + if (m_uiForm.dsCorrections->getCurrentDataName().compare("") == 0) { + uiv.addErrorMessage( + "Use Correction must contain a corrections file or workspace."); + } else { + + QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); + WorkspaceGroup_sptr corrections = + AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( + correctionsWsName.toStdString()); + for (size_t i = 0; i < corrections->size(); i++) { + // Check it is a MatrixWorkspace + MatrixWorkspace_sptr factorWs = + boost::dynamic_pointer_cast<MatrixWorkspace>( + corrections->getItem(i)); + if (!factorWs) { + QString msg = "Correction factor workspace " + QString::number(i) + + " is not a MatrixWorkspace"; + uiv.addErrorMessage(msg); + continue; + } + + // Check X unit is wavelength + Mantid::Kernel::Unit_sptr xUnit = factorWs->getAxis(0)->unit(); + if (xUnit->caption() != "Wavelength") { + QString msg = "Correction factor workspace " + + QString::fromStdString(factorWs->name()) + + " is not in wavelength"; + uiv.addErrorMessage(msg); + } } } } @@ -301,6 +379,7 @@ bool ApplyPaalmanPings::validate() { void ApplyPaalmanPings::loadSettings(const QSettings &settings) { m_uiForm.dsCorrections->readSettings(settings.group()); + m_uiForm.dsContainer->readSettings(settings.group()); m_uiForm.dsSample->readSettings(settings.group()); } @@ -335,6 +414,7 @@ void ApplyPaalmanPings::handleGeometryChange(int index) { * @param specIndex Spectrum index to plot */ void ApplyPaalmanPings::plotPreview(int specIndex) { + bool useCan = m_uiForm.ckUseCan->isChecked(); m_uiForm.ppPreview->clear(); @@ -347,7 +427,12 @@ void ApplyPaalmanPings::plotPreview(int specIndex) { m_uiForm.ppPreview->addSpectrum( "Corrected", QString::fromStdString(m_pythonExportWsName), specIndex, Qt::green); + + // Plot can + if (useCan) + m_uiForm.ppPreview->addSpectrum( + "Can", m_uiForm.dsContainer->getCurrentDataName(), specIndex, Qt::red); } } // namespace CustomInterfaces -} // namespace MantidQt +} // namespace MantidQt \ No newline at end of file diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp index cc0c67956272625f3367551ea6e2ad4f43bd30c5..379c194341bba5284c8abb7c32fe366869aeadde 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp @@ -373,6 +373,7 @@ void ConvFit::algorithmComplete(bool error) { addSample->execute(); } } + m_batchAlgoRunner->executeBatchAsync(); updatePlot(); } @@ -983,10 +984,11 @@ void ConvFit::updatePlot() { } // If there is a result plot then plot it - if (AnalysisDataService::Instance().doesExist(m_pythonExportWsName)) { + std::string groupName = m_baseName.toStdString() + "_Workspaces"; + if (AnalysisDataService::Instance().doesExist(groupName)) { WorkspaceGroup_sptr outputGroup = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( - m_pythonExportWsName); + groupName); if (specNo >= static_cast<int>(outputGroup->size())) return; MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>( diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ISISEnergyTransfer.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ISISEnergyTransfer.cpp index 11bf3c4d198a0094e13aeaedaa3269af5a9c078a..ae32ddc36c2e30d07b9ff6dd2d5de8769a48a24a 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ISISEnergyTransfer.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect/ISISEnergyTransfer.cpp @@ -438,10 +438,8 @@ void ISISEnergyTransfer::plotRaw() { return; } - specid_t detectorMin = - static_cast<specid_t>(m_uiForm.spPlotTimeSpecMin->value()); - specid_t detectorMax = - static_cast<specid_t>(m_uiForm.spPlotTimeSpecMax->value()); + int detectorMin = m_uiForm.spPlotTimeSpecMin->value(); + int detectorMax = m_uiForm.spPlotTimeSpecMax->value(); if (detectorMin > detectorMax) { emit showMessageBox( @@ -450,15 +448,26 @@ void ISISEnergyTransfer::plotRaw() { } QString rawFile = m_uiForm.dsRunFiles->getFirstFilename(); + auto pos = rawFile.lastIndexOf("."); + auto extension = rawFile.right(rawFile.length() - pos); QFileInfo rawFileInfo(rawFile); std::string name = rawFileInfo.baseName().toStdString(); - IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().create("Load"); + IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().create("Load"); loadAlg->initialize(); loadAlg->setProperty("Filename", rawFile.toStdString()); loadAlg->setProperty("OutputWorkspace", name); - loadAlg->setProperty("SpectrumMin", detectorMin); - loadAlg->setProperty("SpectrumMax", detectorMax); + if (extension.compare(".nxs") == 0) { + int64_t detectorMin = + static_cast<int64_t>(m_uiForm.spPlotTimeSpecMin->value()); + int64_t detectorMax = + static_cast<int64_t>(m_uiForm.spPlotTimeSpecMax->value()); + loadAlg->setProperty("SpectrumMin", detectorMin); + loadAlg->setProperty("SpectrumMax", detectorMax); + } else { + loadAlg->setProperty("SpectrumMin", detectorMin); + loadAlg->setProperty("SpectrumMax", detectorMax); + } m_batchAlgoRunner->addAlgorithm(loadAlg); // Rebin the workspace to its self to ensure constant binning diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp index 5ac92097495116849472d24de678d91822f465b9..e13ab5d3e19be94d2dd10cf73a65f3d73cde9a95 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEV.cpp @@ -1040,11 +1040,11 @@ void MantidEV::chooseCell_slot() bool show_cells = m_uiForm.ShowPossibleCells_rbtn->isChecked(); bool select_cell_type = m_uiForm.SelectCellOfType_rbtn->isChecked(); bool select_cell_form = m_uiForm.SelectCellWithForm_rbtn->isChecked(); + bool allow_perm = m_uiForm.AllowPermutations_ckbx->isChecked(); if ( show_cells ) { bool best_only = m_uiForm.BestCellOnly_ckbx->isChecked(); - bool allow_perm = m_uiForm.AllowPermutations_ckbx->isChecked(); double max_scalar_error = 0; if ( !getPositiveDouble( m_uiForm.MaxScalarError_ledt, max_scalar_error ) ) return; @@ -1058,7 +1058,7 @@ void MantidEV::chooseCell_slot() { std::string cell_type = m_uiForm.CellType_cmbx->currentText().toStdString(); std::string centering = m_uiForm.CellCentering_cmbx->currentText().toStdString(); - if ( !worker->selectCellOfType( peaks_ws_name, cell_type, centering ) ) + if ( !worker->selectCellOfType( peaks_ws_name, cell_type, centering, allow_perm ) ) { errorMessage("Failed to Select Specified Conventional Cell"); } @@ -1069,7 +1069,7 @@ void MantidEV::chooseCell_slot() std::string form = m_uiForm.CellFormNumber_cmbx->currentText().toStdString(); double form_num = 0; getDouble( form, form_num ); - if ( !worker->selectCellWithForm( peaks_ws_name, (size_t)form_num ) ) + if ( !worker->selectCellWithForm( peaks_ws_name, (size_t)form_num, allow_perm ) ) { errorMessage("Failed to Select the Requested Form Number"); } diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEVWorker.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEVWorker.cpp index f4377e76fdcffb0c87ccabbadb89f0b69bf58914..c38bb836d42d5fe42ad7b7f52b3e75ca628daf98 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEVWorker.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MantidEVWorker.cpp @@ -711,12 +711,16 @@ bool MantidEVWorker::showCells( const std::string & peaks_ws_name, * @param peaks_ws_name The name of the peaks workspace. * @param cell_type String with the cell type, such as "Cubic". * @param centering String with the centering such as "F". + * @param allow_perm If true, permutations are used to find the + * best fitting cell of any + * particular type. * * @return true if the SelectCellOfType algorithm completes successfully. */ bool MantidEVWorker::selectCellOfType( const std::string & peaks_ws_name, const std::string & cell_type, - const std::string & centering ) + const std::string & centering, + bool allow_perm) { if ( !isPeaksWorkspace( peaks_ws_name ) ) return false; @@ -727,6 +731,7 @@ bool MantidEVWorker::selectCellOfType( const std::string & peaks_ws_name, alg->setProperty("Centering",centering); alg->setProperty("Apply",true); alg->setProperty("tolerance",0.12); + alg->setProperty("AllowPermutations",allow_perm); if ( alg->execute() ) return true; @@ -743,11 +748,15 @@ bool MantidEVWorker::selectCellOfType( const std::string & peaks_ws_name, * * @param peaks_ws_name The name of the peaks workspace. * @param form_num The form number, 1..44. + * @param allow_perm If true, permutations are used to find the + * best fitting cell of any + * particular type. * * @return true if the SelectCellWithForm algorithm completes successfully. */ bool MantidEVWorker::selectCellWithForm( const std::string & peaks_ws_name, - size_t form_num ) + size_t form_num, + bool allow_perm) { if ( !isPeaksWorkspace( peaks_ws_name ) ) return false; @@ -757,6 +766,7 @@ bool MantidEVWorker::selectCellWithForm( const std::string & peaks_ws_name, alg->setProperty("FormNumber",(int)form_num); alg->setProperty("Apply",true); alg->setProperty("tolerance",0.12); + alg->setProperty("AllowPermutations",allow_perm); if ( alg->execute() ) return true; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit/MultiDatasetFit.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit/MultiDatasetFit.cpp index 9054ef5c5fe0d2a63986de674ca76e8dfabecc1e..869d74cfc7c93d8fb63b1d76cddf1f5819f23c47 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit/MultiDatasetFit.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit/MultiDatasetFit.cpp @@ -77,6 +77,7 @@ void MultiDatasetFit::initLayout() connect(m_dataController,SIGNAL(dataTableUpdated()),m_plotController,SLOT(tableUpdated())); connect(m_dataController,SIGNAL(dataSetUpdated(int)),m_plotController,SLOT(updateRange(int))); connect(m_dataController,SIGNAL(dataTableUpdated()),this,SLOT(setLogNames())); + connect(m_dataController,SIGNAL(dataTableUpdated()),this,SLOT(invalidateOutput())); connect(m_plotController,SIGNAL(fittingRangeChanged(int, double, double)),m_dataController,SLOT(setFittingRange(int, double, double))); connect(m_uiForm.cbShowDataErrors,SIGNAL(toggled(bool)),m_plotController,SLOT(showDataErrors(bool))); connect(m_uiForm.btnToVisibleRange,SIGNAL(clicked()),m_plotController,SLOT(resetRange())); @@ -151,6 +152,12 @@ void MultiDatasetFit::createPlotToolbar() } +/// Get the name of the output workspace +QString MultiDatasetFit::getOutputWorkspaceName() const +{ + return QString::fromStdString(m_outputWorkspaceName); +} + /// Create a multi-domain function to fit all the spectra in the data table. boost::shared_ptr<Mantid::API::IFunction> MultiDatasetFit::createFunction() const { @@ -239,8 +246,14 @@ void MultiDatasetFit::fitSimultaneous() fit->setPropertyValue("Output",m_outputWorkspaceName); m_fitOptionsBrowser->setProperty("Output","out"); } - - m_outputWorkspaceName += "_Workspaces"; + if (n == 1) + { + m_outputWorkspaceName += "_Workspace"; + } + else + { + m_outputWorkspaceName += "_Workspaces"; + } removeOldOutput(); @@ -618,5 +631,13 @@ void MultiDatasetFit::removeOldOutput() } } +/// Invalidate the previous fit output +void MultiDatasetFit::invalidateOutput() +{ + m_outputWorkspaceName = ""; + m_plotController->clear(); + m_plotController->update(); +} + } // CustomInterfaces } // MantidQt diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSConstants.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSConstants.cpp index 8d34051f49f63831215aa44f83149ebf96693fe8..93ffc5689b8ed4ae782a91792d896044413f0c8c 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSConstants.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSConstants.cpp @@ -1,5 +1,5 @@ #include "MantidQtCustomInterfaces/SANSConstants.h" - +#include <limits> namespace MantidQt { @@ -36,5 +36,29 @@ QString SANSConstants::getPythonTrueKeyword() { return pythonSuccessKeyword; } +/** + * Gets the max double value + * @returns the max double + */ +double SANSConstants::getMaxDoubleValue() { + return std::numeric_limits<double>::max(); +} + +/** + * Get the number of decimals + * @returns the number of decimals + */ +int SANSConstants::getDecimals() { + return 6; +} + +/** + * Get the max integer value + * @returns the max integer value + */ +int SANSConstants::getMaxIntValue() { + return std::numeric_limits<int>::max(); +} + +} } -} \ No newline at end of file diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp index 2609d7818480fef0069a37eaa9af78ac2b55b080..2fdc4aace80a53990fb3652d739fed59037e1350 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/SANSRunWindow.cpp @@ -51,6 +51,7 @@ #include <boost/foreach.hpp> #include <boost/function.hpp> #include <boost/tuple/tuple.hpp> +#include <cmath> using Mantid::detid_t; @@ -154,19 +155,19 @@ namespace // Public member functions //---------------------------------------------- ///Constructor -SANSRunWindow::SANSRunWindow(QWidget *parent) : - UserSubWindow(parent), m_addFilesTab(NULL), m_displayTab(NULL), m_diagnosticsTab(NULL), - m_saveWorkspaces(NULL), m_ins_defdir(""), m_last_dir(""), - m_cfg_loaded(true), m_userFname(false), m_sample_file(), - m_reducemapper(NULL), - m_warnings_issued(false), m_force_reload(false), - m_newInDir(*this, &SANSRunWindow::handleInputDirChange), - m_delete_observer(*this, &SANSRunWindow::handleMantidDeleteWorkspace), - m_s2d_detlabels(), m_loq_detlabels(), m_allowed_batchtags(), - m_have_reducemodule(false), m_dirty_batch_grid(false), m_tmp_batchfile(""), - m_batch_paste(NULL), m_batch_clear(NULL), - slicingWindow(NULL) -{ +SANSRunWindow::SANSRunWindow(QWidget *parent) + : UserSubWindow(parent), m_addFilesTab(NULL), m_displayTab(NULL), + m_diagnosticsTab(NULL), m_saveWorkspaces(NULL), m_ins_defdir(""), + m_last_dir(""), m_cfg_loaded(true), m_userFname(false), m_sample_file(), + m_reducemapper(NULL), m_warnings_issued(false), m_force_reload(false), + m_newInDir(*this, &SANSRunWindow::handleInputDirChange), + m_delete_observer(*this, &SANSRunWindow::handleMantidDeleteWorkspace), + m_s2d_detlabels(), m_loq_detlabels(), m_allowed_batchtags(), + m_have_reducemodule(false), m_dirty_batch_grid(false), + m_tmp_batchfile(""), m_batch_paste(NULL), m_batch_clear(NULL), + m_mustBeDouble(NULL), m_doubleValidatorZeroToMax(NULL), + m_intValidatorZeroToMax(NULL), + slicingWindow(NULL) { ConfigService::Instance().addObserver(m_newInDir); } @@ -2363,6 +2364,12 @@ QString SANSRunWindow::readSampleObjectGUIChanges() void SANSRunWindow::handleReduceButtonClick(const QString & typeStr) { const States type = typeStr == "1D" ? OneD : TwoD; + + // Make sure that all settings are valid + if (!areSettingsValid()){ + return; + } + //new reduction is going to take place, remove the results from the last reduction resetDefaultOutput(); @@ -3869,10 +3876,81 @@ void SANSRunWindow::openHelpPage() void SANSRunWindow::setValidators() { // Validator policies - QDoubleValidator* mustBeDouble = new QDoubleValidator(this); + if (!m_mustBeDouble) { + m_mustBeDouble = new QDoubleValidator(this); + } + + if (!m_doubleValidatorZeroToMax) { + m_doubleValidatorZeroToMax = new QDoubleValidator( + 0.0, m_constants.getMaxDoubleValue(), m_constants.getDecimals(), this); + } + + // Range is [0, max] + if (!m_intValidatorZeroToMax) { + m_intValidatorZeroToMax = + new QIntValidator(0, m_constants.getMaxIntValue(), this); + } + + + // Run Numbers tab + + // ----------- Run Settings Tab--------------------------------- + m_uiForm.gravity_extra_length_line_edit->setValidator(m_mustBeDouble); + m_uiForm.rad_min->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.rad_max->setValidator(m_mustBeDouble); - // For gravity extra length - m_uiForm.gravity_extra_length_line_edit->setValidator(mustBeDouble); + m_uiForm.wav_min->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.wav_max->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.wav_dw->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.q_min->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.q_max->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.q_dq->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.qy_max->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.qy_dqy->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.trans_min->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.trans_max->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.trans_min_can->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.trans_max_can->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.monitor_spec->setValidator(m_intValidatorZeroToMax); + m_uiForm.trans_monitor->setValidator(m_intValidatorZeroToMax); + + m_uiForm.trans_M3M4_line_edit->setValidator(m_mustBeDouble); + m_uiForm.trans_radius_line_edit->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.phi_min->setValidator(m_mustBeDouble); + m_uiForm.phi_max->setValidator(m_mustBeDouble); + + m_uiForm.frontDetRescale->setValidator(m_mustBeDouble); + m_uiForm.frontDetShift->setValidator(m_mustBeDouble); + m_uiForm.frontDetQmin->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.frontDetQmax->setValidator(m_doubleValidatorZeroToMax); + + m_uiForm.tof_min->setValidator(m_mustBeDouble); + m_uiForm.tof_max->setValidator(m_mustBeDouble); + m_uiForm.scale_factor->setValidator(m_mustBeDouble); + + // ----------- Geometry Tab----------------------------------- + m_uiForm.rear_beam_x->setValidator(m_mustBeDouble); + m_uiForm.rear_beam_y->setValidator(m_mustBeDouble); + m_uiForm.front_beam_x->setValidator(m_mustBeDouble); + m_uiForm.front_beam_y->setValidator(m_mustBeDouble); + + // Geometry + m_uiForm.sample_thick->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.sample_height->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.sample_width->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.smpl_offset->setValidator(m_mustBeDouble); + + // Beam Centre Finder + m_uiForm.beam_rmin->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.beam_rmax->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.toleranceLineEdit->setValidator(m_doubleValidatorZeroToMax); + m_uiForm.beam_iter->setValidator(m_intValidatorZeroToMax); } /** @@ -4226,6 +4304,102 @@ void SANSRunWindow::resetAllTransFields() { m_uiForm.trans_radius_check_box->setChecked(state); } -} //namespace CustomInterfaces +/** + * Check tha the Settings are valid. We need to do this for inputs which cannot + * be checked with simple validators + */ +bool SANSRunWindow::areSettingsValid() { + bool isValid = true; + QString message; + // ------------ GUI INPUT CHECKS ------------ + + // R_MAX -- can be only >0 or -1 + auto r_max = m_uiForm.rad_max->text().simplified().toDouble(); + if ((r_max < 0.0) && (r_max != -1)) { + isValid = false; + message += "R_max issue: Only values >= 0 and -1 are allowed.\n"; + } + + // WAVELENGTH + checkWaveLengthAndQValues(isValid, message, m_uiForm.wav_min, + m_uiForm.wav_max, m_uiForm.wav_dw_opt, + "Wavelength"); + + // QX + checkWaveLengthAndQValues(isValid, message, m_uiForm.q_min, + m_uiForm.q_max, m_uiForm.q_dq_opt, + "Qx"); + + // TRANS SAMPLE + checkWaveLengthAndQValues(isValid, message, m_uiForm.trans_min, + m_uiForm.trans_max, m_uiForm.trans_opt, + "Trans"); + + // TRANS CAN + if (m_uiForm.trans_selector_opt->currentText().toUpper().contains("SEPARATE")) { + checkWaveLengthAndQValues(isValid, message, m_uiForm.trans_min_can, + m_uiForm.trans_max_can, m_uiForm.trans_opt_can, + "Trans Can"); + } + + // Geometry + if (m_uiForm.sample_thick->text().simplified().toDouble() == 0.0) { + isValid = false; + message += "Sample height issue: Only values > 0 are allowed.\n"; + } + + if (m_uiForm.sample_height->text().simplified().toDouble() == 0.0) { + isValid = false; + message += "Sample height issue: Only values > 0 are allowed.\n"; + } + if (m_uiForm.sample_width->text().simplified().toDouble() == 0.0) { + isValid = false; + message += "Sample width issue: Only values > 0 are allowed.\n"; + } + + // Print the error message if there are any + if (!message.isEmpty()) { + QString warning = "Please correct these settings before proceeding:\n"; + warning += message; + QMessageBox::warning(this, "Inconsistent input", warning); + } + + return isValid; +} + +/** + * Check the wavelength and Q values + * @param isValid: flag by reference to set the check if invalid + * @param message: the message to display + * @param min: the min line edit field + * @param max: the max line edit field + * @param selection: the combo box which is being querried + * @param type: message type + */ +void SANSRunWindow::checkWaveLengthAndQValues(bool &isValid, QString &message, + QLineEdit *min, QLineEdit *max, + QComboBox *selection, QString type) { + auto min_value = min->text().simplified().toDouble(); + auto max_value = max->text().simplified().toDouble(); + + // Make sure that min<=max + if (min_value > max_value) { + isValid = false; + message += type; + message += + " issue: The min value is larger than the max value. \n"; + } + + // Make sure that when selecting log, then we don't have 0 values + if (selection->currentText().toUpper().contains("LOG") && + (min_value == 0.0 || max_value == 0.0)) { + isValid = false; + message += type; + message += + " issue: Trying to use Logarithmic steps and values which are <= 0.0. \n"; + } +} + +} //namespace CustomInterfaces } //namespace MantidQt diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h b/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h index 2160af7b5aff88e6e25327b1cd3054317ae2387c..043aba68ed970e70f14f1dd292e947a3ddcf03a6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h @@ -23,16 +23,19 @@ public: private: // not async at all void startAsyncCalibWorker(const std::string &outFilename, - const std::string &vanNo, - const std::string &ceriaNo) { + const std::string &vanNo, + const std::string &ceriaNo) { doNewCalibration(outFilename, vanNo, ceriaNo); calibrationFinished(); } void startAsyncFocusWorker(const std::string &dir, - const std::string &outFilename, - const std::string &runNo, int bank) { - doFocusRun(dir, outFilename, runNo, bank); + const std::vector<std::string> &outFilenames, + const std::string &runNo, + const std::vector<bool> banks, + const std::string &specIDs, + const std::string &dgFile) { + doFocusRun(dir, outFilenames, runNo, banks, specIDs, dgFile); focusingFinished(); } }; @@ -59,6 +62,9 @@ public: m_view.reset(new testing::NiceMock<MockEnggDiffractionView>()); m_presenter.reset( new MantidQt::CustomInterfaces::EnggDiffractionPresenter(m_view.get())); + + m_ex_enginx_banks.push_back(true); + m_ex_enginx_banks.push_back(false); } void tearDown() { @@ -223,6 +229,13 @@ public: "_both_banks.prm")).Times(0); // .WillOnce(Return(filename)); // if enabled ask user output filename + // Should not try to use options for focusing + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + // should disable actions at the beginning of the calculations EXPECT_CALL(mockView, enableCalibrateAndFocusActions(false)).Times(1); @@ -240,7 +253,7 @@ public: EXPECT_CALL(mockView, newCalibLoaded(testing::_, testing::_, testing::_)) .Times(0); - //TS_ASSERT_THROWS_NOTHING(pres.notify(IEnggDiffractionPresenter::CalcCalib)); + // TS_ASSERT_THROWS_NOTHING(pres.notify(IEnggDiffractionPresenter::CalcCalib)); pres.notify(IEnggDiffractionPresenter::CalcCalib); } @@ -267,8 +280,15 @@ public: // empty run number! EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("")); - // any bank will do - EXPECT_CALL(mockView, focusingBank()).Times(1).WillOnce(Return(1)); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); // should not get that far that it tries to get these parameters EXPECT_CALL(mockView, currentInstrument()).Times(0); @@ -281,17 +301,25 @@ public: pres.notify(IEnggDiffractionPresenter::FocusRun); } - void test_focusWithRunNumberButWrongBank() { + void test_focusWithRunNumberButWrongBanks() { testing::NiceMock<MockEnggDiffractionView> mockView; MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("999999")); - // negative bank number! - EXPECT_CALL(mockView, focusingBank()).Times(1).WillOnce(Return(-34)); + // missing bank on/off vector! + std::vector<bool> banks; + banks.push_back(false); + banks.push_back(false); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce(Return(banks)); + + // would needs basic calibration settings, but only if there was at least + // one bank selected + EXPECT_CALL(mockView, currentCalibSettings()).Times(0); // should not get that far that it tries to get these parameters EXPECT_CALL(mockView, currentInstrument()).Times(0); - EXPECT_CALL(mockView, currentCalibSettings()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); // 1 warning pop-up to user, 0 errors EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); @@ -310,16 +338,24 @@ public: // pres(&mockView); EnggDiffPresenterNoThread pres(&mockView); - // empty run number! + // wrong run number! EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("999999")); - // any bank will do - EXPECT_CALL(mockView, focusingBank()).Times(1).WillOnce(Return(1)); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); // needs basic calibration settings from the user to start focusing EnggDiffCalibSettings calibSettings; EXPECT_CALL(mockView, currentCalibSettings()).Times(1).WillOnce( Return(calibSettings)); + // Should not try to use options for other types of focusing + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + // it should not get there EXPECT_CALL(mockView, enableCalibrateAndFocusActions(false)).Times(0); EXPECT_CALL(mockView, enableCalibrateAndFocusActions(true)).Times(0); @@ -338,13 +374,50 @@ public: // an example run available in unit test data: EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("228061")); - EXPECT_CALL(mockView, focusingBank()).Times(1).WillOnce(Return(1)); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); + + // will need basic calibration settings from the user + EnggDiffCalibSettings calibSettings; + EXPECT_CALL(mockView, currentCalibSettings()).Times(1).WillOnce( + Return(calibSettings)); + + // check automatic plotting + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(1).WillOnce(Return(true)); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(1); + + // Should not try to use options for other types of focusing + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + + // No errors/warnings + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); + + pres.notify(IEnggDiffractionPresenter::FocusRun); + } + + void disabled_test_focusOK_allBanksOff() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // an example run available in unit test data: + EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("228061")); + std::vector<bool> banks; + banks.push_back(false); + banks.push_back(false); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce(Return(banks)); // will need basic calibration settings from the user EnggDiffCalibSettings calibSettings; EXPECT_CALL(mockView, currentCalibSettings()).Times(1).WillOnce( Return(calibSettings)); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + // No errors/warnings EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); @@ -352,6 +425,214 @@ public: pres.notify(IEnggDiffractionPresenter::FocusRun); } + void test_focusCropped_withoutRunNo() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // empty run number! + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(1).WillOnce(Return("")); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(1).WillOnce( + Return("1")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + + // should not get that far that it tries to get these parameters + EXPECT_CALL(mockView, currentInstrument()).Times(0); + EXPECT_CALL(mockView, currentCalibSettings()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusCropped); + } + + void test_focusCropped_withoutBanks() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // ok run number + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(1).WillOnce( + Return("228061")); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(std::vector<bool>())); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(1).WillOnce( + Return("1,5")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // should not get that far that it tries to get these parameters + EXPECT_CALL(mockView, currentInstrument()).Times(0); + EXPECT_CALL(mockView, currentCalibSettings()).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusCropped); + } + + void test_focusCropped_withoutSpectrumIDs() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // ok run number + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(1).WillOnce( + Return("228061")); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(1).WillOnce( + Return("")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(0); + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // should not get that far that it tries to get these parameters + EXPECT_CALL(mockView, currentInstrument()).Times(0); + EXPECT_CALL(mockView, currentCalibSettings()).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusCropped); + } + + void test_focusTexture_withoutRunNo() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // empty run number! + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(1).WillOnce(Return("")); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(1).WillOnce( + Return("")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + EXPECT_CALL(mockView, focusingBanks()).Times(0); + + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusTexture); + } + + void test_focusTexture_withoutFilename() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // goo run number + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(1).WillOnce( + Return("228061")); + EXPECT_CALL(mockView, focusingBanks()).Times(0); + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(1).WillOnce( + Return("")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusTexture); + } + + void test_focusTexture_withInexistentTextureFile() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // goo run number + EXPECT_CALL(mockView, focusingTextureRunNo()).Times(1).WillOnce( + Return("228061")); + // non empty but absurd csv file of detector groups + EXPECT_CALL(mockView, focusingTextureGroupingFile()).Times(1).WillOnce( + Return("i_dont_exist_dont_look_for_me.csv")); + + // should not try to use these ones + EXPECT_CALL(mockView, focusingRunNo()).Times(0); + + EXPECT_CALL(mockView, focusingCroppedRunNo()).Times(0); + EXPECT_CALL(mockView, focusingCroppedSpectrumIDs()).Times(0); + + EXPECT_CALL(mockView, focusedOutWorkspace()).Times(0); + EXPECT_CALL(mockView, plotFocusedSpectrum(testing::_)).Times(0); + + // 1 warning pop-up to user, 0 errors + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusTexture); + } + + void test_resetFocus() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + EXPECT_CALL(mockView, resetFocus()).Times(1); + + // No errors/warnings when resetting options + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); + + pres.notify(IEnggDiffractionPresenter::ResetFocus); + } + + void test_resetFocus_thenFocus() { + testing::NiceMock<MockEnggDiffractionView> mockView; + MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); + + // No errors/warnings when resetting options + EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); + + pres.notify(IEnggDiffractionPresenter::ResetFocus); + + // empty run number! + EXPECT_CALL(mockView, focusingRunNo()).Times(1).WillOnce(Return("")); + EXPECT_CALL(mockView, focusingBanks()).Times(1).WillOnce( + Return(m_ex_enginx_banks)); + + // should not get that far that it tries to get these parameters + EXPECT_CALL(mockView, currentInstrument()).Times(0); + EXPECT_CALL(mockView, currentCalibSettings()).Times(0); + + // Now one error shown as a warning-pop-up cause inputs and options are + // empty + EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); + + pres.notify(IEnggDiffractionPresenter::FocusRun); + } + void test_logMsg() { testing::NiceMock<MockEnggDiffractionView> mockView; MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView); @@ -394,6 +675,8 @@ private: boost::scoped_ptr<testing::NiceMock<MockEnggDiffractionView>> m_view; boost::scoped_ptr<MantidQt::CustomInterfaces::EnggDiffractionPresenter> m_presenter; + + std::vector<bool> m_ex_enginx_banks; }; #endif // MANTID_CUSTOMINTERFACES_ENGGDIFFRACTIONPRESENTERTEST_H diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h b/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h index ffd010a806efea3e4e77af8300813bd568dd925f..36c5bdd0a65a6a4d027c6a2f19146fc64ec9bf73 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h @@ -80,17 +80,32 @@ public: // virtual std::string focusingRunNo() const; MOCK_CONST_METHOD0(focusingRunNo, std::string()); + // virtual std::string focusingCroppedRunNo() const; + MOCK_CONST_METHOD0(focusingCroppedRunNo, std::string()); + + // virtual std::string focusingTextureRunNo() const; + MOCK_CONST_METHOD0(focusingTextureRunNo, std::string()); + // virtual int focusingBank() const; - MOCK_CONST_METHOD0(focusingBank, int()); + MOCK_CONST_METHOD0(focusingBanks, std::vector<bool>()); + + // virtual std::string focusingCroppedSpectrumIDs() const; + MOCK_CONST_METHOD0(focusingCroppedSpectrumIDs, std::string()); + + // virtual std::string focusingTextureGroupingFile() const; + MOCK_CONST_METHOD0(focusingTextureGroupingFile, std::string()); + + // virtual void resetFocus(); + MOCK_METHOD0(resetFocus, void()); // virtual bool focusedOutWorkspace() const; MOCK_CONST_METHOD0(focusedOutWorkspace, bool()); - // virtual void plotFocusedSpectrum(); - MOCK_METHOD0(plotFocusedSpectrum, void()); - // void saveSettings() const; MOCK_CONST_METHOD0(saveSettings, void()); + + // virtual void plotFocusedSpectrum(); + MOCK_METHOD1(plotFocusedSpectrum, void(const std::string&)); }; #endif // MANTID_CUSTOMINTERFACES_ENGGDIFFRACTIONVIEWMOCK_H diff --git a/Code/Mantid/Testing/SystemTests/lib/systemtests/stresstesting.py b/Code/Mantid/Testing/SystemTests/lib/systemtests/stresstesting.py index a67e9538a86ae4e8a30e6bd902f4ac8d894ad6bb..f6e7d9abb604bfefa48d1b3aa7ee1ac2c5cb713b 100644 --- a/Code/Mantid/Testing/SystemTests/lib/systemtests/stresstesting.py +++ b/Code/Mantid/Testing/SystemTests/lib/systemtests/stresstesting.py @@ -515,7 +515,9 @@ class PythonTestRunner(object): self._mtdpy_header = '' self._test_dir = '' # Get the path that this module resides in so that the tests know about it - self._framework_path = THIS_MODULE_DIR + # Some windows paths can contain sequences such as \r, e.g. \release_systemtests + # that need to be escaped or the module cannot be found + self._framework_path = THIS_MODULE_DIR.replace('\\', '\\\\') # A string to prefix the code with self._code_prefix = '' self._using_escape = need_escaping diff --git a/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py b/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py index a7d518fc5f73554db1d5c1dd53dc2ab55b1c6617..f5878442575fdaa2f55268bc216ff80b5e8cec4b 100644 --- a/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py +++ b/Code/Mantid/Testing/SystemTests/scripts/mantidinstaller.py @@ -260,22 +260,26 @@ if __name__ == "__main__": import optparse parser = optparse.OptionParser("Usage: %prog <command> <pkg directory>", description="Commands available: install, uninstall") + parser.add_option("-d", "--dump-exe-path", dest="dump_exe_path", + help="Filepath to write the full path of the MantidPlot executable") (options, args) = parser.parse_args() # All arguments are required if len(args) != 2: parser.print_help() sys.exit(1) - + command, package_dir = args[0], args[1] package_dir = os.path.abspath(package_dir) - print package_dir + print "Searching for packages in '%s'" % package_dir installer = get_installer(package_dir) if command.lower() == "install": print "Installing package '%s'" % installer.mantidInstaller installer.install() + if options.dump_exe_path is not None: + with open(options.dump_exe_path, 'w') as f: + f.write(installer.mantidPlotPath) elif command.lower() == "uninstall": print "Removing package '%s'" % installer.mantidInstaller installer.uninstall() else: raise RuntimeError("Invalid command '%s'. Options are: install, uninstall" % command) - diff --git a/Code/Mantid/Testing/SystemTests/tests/analysis/ISISPowderDiffractionTest.py b/Code/Mantid/Testing/SystemTests/tests/analysis/ISISPowderDiffractionTest.py index b4a6c898a11e4686625c969a6558f6232ec354ed..d95e042ba633c7857f2d7cde31d714cd564db536 100644 --- a/Code/Mantid/Testing/SystemTests/tests/analysis/ISISPowderDiffractionTest.py +++ b/Code/Mantid/Testing/SystemTests/tests/analysis/ISISPowderDiffractionTest.py @@ -1,54 +1,203 @@ -# pylint: disable=no-init +# pylint: disable=no-init,attribute-defined-outside-init,too-many-public-methods -from mantid.api import FileFinder +from mantid.api import AnalysisDataService, MatrixWorkspace, WorkspaceGroup, ITableWorkspace, FileFinder from mantid.simpleapi import * from mantid import config import os.path import stresstesting import sys +import unittest + F_DIR = FileFinder.getFullPath("PowderISIS") sys.path.append(F_DIR) import cry_ini import cry_focus -class ISISPowderDiffraction(stresstesting.MantidStressTest): +DIFF_PLACES = 8 +DIRS = config['datasearch.directories'].split(';') + +class ISISPowderDiffraction(stresstesting.MantidStressTest): def requiredFiles(self): return set(["hrp39191.raw", "hrp39187.raw", "hrp43022.raw", "hrpd/test/GrpOff/hrpd_new_072_01.cal", - "hrpd/test/GrpOff/hrpd_new_072_01_corr.cal", "hrpd/test/cycle_09_2/Calibration/van_s1_old-0.nxs", - "hrpd/test/cycle_09_2/Calibration/van_s1_old-1.nxs", - "hrpd/test/cycle_09_2/Calibration/van_s1_old-2.nxs", "hrpd/test/cycle_09_2/tester/mtd.pref"]) + "hrpd/test/GrpOff/hrpd_new_072_01_corr.cal", "hrpd/test/cycle_09_2/Calibration/van_s1_old-0.nxs", + "hrpd/test/cycle_09_2/Calibration/van_s1_old-1.nxs", + "hrpd/test/cycle_09_2/Calibration/van_s1_old-2.nxs", "hrpd/test/cycle_09_2/tester/mtd.pref"]) + def _clean_up_files(self, filenames, directories): try: - for file in filenames: - path = os.path.join(directories[0], file) + for files in filenames: + path = os.path.join(directories[0], files) os.remove(path) except OSError, ose: print 'could not delete generated file : ', ose.filename - def runTest(self): - dirs = config['datasearch.directories'].split(';') - expt = cry_ini.Files('hrpd', RawDir=(dirs[0]), Analysisdir='test', forceRootDirFromScripts=False, - inputInstDir=dirs[0]) + self._success = False + expt = cry_ini.Files('hrpd', RawDir=(DIRS[0]), Analysisdir='test', forceRootDirFromScripts=False, + inputInstDir=DIRS[0]) expt.initialize('cycle_09_2', user='tester', prefFile='mtd.pref') expt.tell() cry_focus.focus_all(expt, "43022") + # Custom code to create and run this single test suite + # and then mark as success or failure + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(LoadTests, "test")) + runner = unittest.TextTestRunner() + # Run using either runner + res = runner.run(suite) + if res.wasSuccessful(): + self._success = True + else: + self._success = False + def validate(self): - return 'ResultTOFgrp', 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old.nxs' + return self._success def cleanup(self): - dirs = config['datasearch.directories'].split(';') filenames = set(["hrpd/test/cycle_09_2/Calibration/hrpd_new_072_01_corr.cal", - "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.gss", - "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.nxs", - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_D.dat', - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_TOF.dat', - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_D.dat', - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_TOF.dat', - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_D.dat', - 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_TOF.dat', - 'hrpd/test/cycle_09_2/tester/hrpd_new_072_01_corr.cal']) - - self._clean_up_files(filenames, dirs) + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.gss", + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.nxs", + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_D.dat', + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_TOF.dat', + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_D.dat', + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_TOF.dat', + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_D.dat', + 'hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_TOF.dat', + 'hrpd/test/cycle_09_2/tester/hrpd_new_072_01_corr.cal']) + + self._clean_up_files(filenames, DIRS) + + +# ====================================================================== +# work horse +class LoadTests(unittest.TestCase): + wsname = "__LoadTest" + cleanup_names = [] + + def tearDown(self): + self.cleanup_names.append(self.wsname) + for name in self.cleanup_names: + try: + AnalysisDataService.remove(name) + except KeyError: + pass + self.cleanup_names = [] + + # ============================ Success ============================== + def runTest(self): + expt = cry_ini.Files('hrpd', RawDir=(DIRS[0]), Analysisdir='test', forceRootDirFromScripts=False, + inputInstDir=DIRS[0]) + expt.initialize('cycle_09_2', user='tester', prefFile='mtd.pref') + expt.tell() + cry_focus.focus_all(expt, "43022") + + def test_calfile_with_workspace(self): + self.wsname = "CalWorkspace1" + calfile1 = (DIRS[0] + 'hrpd/test/cycle_09_2/Calibration/hrpd_new_072_01_corr.cal') + calfile2 = (DIRS[0] + 'hrpd/test/cycle_09_2/tester/hrpd_new_072_01_corr.cal') + data1 = LoadCalFile(InstrumentName="ENGIN-X", CalFilename=calfile1, + WorkspaceName=self.wsname) + data2 = LoadCalFile(InstrumentName="ENGIN-X", CalFilename=calfile2, + WorkspaceName="CalWorkspace2") + + self.assertTrue(isinstance(data1[0], MatrixWorkspace)) + self.assertTrue(isinstance(data1[1], MatrixWorkspace)) + self.assertTrue(isinstance(data1[2], MatrixWorkspace)) + self.assertTrue(isinstance(data1[3], ITableWorkspace)) + + self.assertTrue("CalWorkspace1_group" in data1[0].getName()) + self.assertTrue("CalWorkspace1_offsets" in data1[1].getName()) + self.assertTrue("CalWorkspace1_mask" in data1[2].getName()) + self.assertTrue("CalWorkspace1_cal" in data1[3].getName()) + + self.assertTrue(isinstance(data2[0], MatrixWorkspace)) + self.assertTrue(isinstance(data2[1], MatrixWorkspace)) + self.assertTrue(isinstance(data2[2], MatrixWorkspace)) + self.assertTrue(isinstance(data2[3], ITableWorkspace)) + + self.assertTrue("CalWorkspace2_group" in data2[0].getName()) + self.assertTrue("CalWorkspace2_offsets" in data2[1].getName()) + self.assertTrue("CalWorkspace2_mask" in data2[2].getName()) + self.assertTrue("CalWorkspace2_cal" in data2[3].getName()) + + def test_nxsfile_with_workspace(self): + self.wsname = "NexusWorkspace" + nxsfile = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.nxs") + data = LoadNexusProcessed(Filename=nxsfile, OutputWorkspace=self.wsname) + + self.assertTrue(isinstance(data[0], WorkspaceGroup)) + self.assertEquals(3, data[0].getNumberOfEntries()) + + self.assertTrue(isinstance(data[1], MatrixWorkspace)) + self.assertTrue(isinstance(data[2], MatrixWorkspace)) + self.assertTrue(isinstance(data[3], MatrixWorkspace)) + + self.assertTrue("ResultTOF-1" in data[1].getName()) + self.assertTrue("ResultTOF-2" in data[2].getName()) + self.assertTrue("ResultTOF-3" in data[3].getName()) + + self.assertTrue('ResultTOFgrp', self.wsname[0]) + + def test_gssfile_with_workspace(self): + gssfile = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old.gss") + data = LoadGSS(Filename=gssfile, OutputWorkspace=self.wsname) + + self.assertTrue(isinstance(data, MatrixWorkspace)) + self.assertEquals(3, data.getNumberHistograms()) + self.assertEquals(22981, data.blocksize()) + self.assertAlmostEqual(9783.15138, data.readX(2)[1], places=DIFF_PLACES) + + def test_datfile_with_workspace(self): + datfile1 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_D.dat") + datfile2 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b1_TOF.dat") + datfile3 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_D.dat") + datfile4 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b2_TOF.dat") + datfile5 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_D.dat") + datfile6 = (DIRS[0] + "hrpd/test/cycle_09_2/tester/hrp43022_s1_old_b3_TOF.dat") + + data1 = LoadAscii(Filename=datfile1, OutputWorkspace="datWorkspace1") + data2 = LoadAscii(Filename=datfile2, OutputWorkspace="datWorkspace2") + data3 = LoadAscii(Filename=datfile3, OutputWorkspace="datWorkspace3") + data4 = LoadAscii(Filename=datfile4, OutputWorkspace="datWorkspace4") + data5 = LoadAscii(Filename=datfile5, OutputWorkspace="datWorkspace5") + data6 = LoadAscii(Filename=datfile6, OutputWorkspace="datWorkspace6") + + self.assertTrue(isinstance(data1, MatrixWorkspace)) + self.assertTrue(isinstance(data2, MatrixWorkspace)) + self.assertTrue(isinstance(data3, MatrixWorkspace)) + self.assertTrue(isinstance(data4, MatrixWorkspace)) + self.assertTrue(isinstance(data5, MatrixWorkspace)) + self.assertTrue(isinstance(data6, MatrixWorkspace)) + + self.assertTrue("datWorkspace1" in data1.getName()) + self.assertTrue("datWorkspace2" in data2.getName()) + self.assertTrue("datWorkspace3" in data3.getName()) + self.assertTrue("datWorkspace4" in data4.getName()) + self.assertTrue("datWorkspace5" in data5.getName()) + self.assertTrue("datWorkspace6" in data6.getName()) + + self.assertEquals(1, data1.getNumberHistograms()) + self.assertEquals(22981, data1.blocksize()) + self.assertAlmostEqual(0.2168, data1.readX(0)[2], places=DIFF_PLACES) + + self.assertEquals(1, data2.getNumberHistograms()) + self.assertEquals(22981, data2.blocksize()) + self.assertAlmostEqual(data1.readY(0)[6], data2.readY(0)[6], places=DIFF_PLACES) + + self.assertEquals(1, data3.getNumberHistograms()) + self.assertEquals(23038, data3.blocksize()) + self.assertAlmostEqual(0.44656, data3.readX(0)[4311], places=DIFF_PLACES) + + self.assertEquals(1, data4.getNumberHistograms()) + self.assertEquals(23038, data4.blocksize()) + self.assertAlmostEqual(1.58185696, data4.readE(0)[10], places=DIFF_PLACES) + + self.assertEquals(1, data5.getNumberHistograms()) + self.assertEquals(23025, data5.blocksize()) + self.assertAlmostEqual(data5.readY(0)[15098], data6.readY(0)[15098], places=DIFF_PLACES) + + self.assertEquals(1, data6.getNumberHistograms()) + self.assertEquals(23025, data6.blocksize()) + self.assertAlmostEqual(9782.63819, data6.readX(0)[0], places=DIFF_PLACES) diff --git a/Code/Mantid/Testing/Tools/cxxtest/python/cxxtest/cxxtest_parser.py b/Code/Mantid/Testing/Tools/cxxtest/python/cxxtest/cxxtest_parser.py index 0f9d98e22e9746cbdf59497987c94a85098ca990..245962b85765b73b2db7253ea5bf615c51be63dc 100644 --- a/Code/Mantid/Testing/Tools/cxxtest/python/cxxtest/cxxtest_parser.py +++ b/Code/Mantid/Testing/Tools/cxxtest/python/cxxtest/cxxtest_parser.py @@ -10,6 +10,7 @@ suites = [] suite = None inBlock = 0 options=None +lastLineVoid = False def scanInputFiles(files, _options): '''Scan all input files for test suites''' @@ -143,11 +144,24 @@ def lineStartsBlock( line ): return re.search( r'\bCXXTEST_CODE\s*\(', line ) is not None test_re = re.compile( r'^([^/]|/[^/])*\bvoid\s+([Tt]est\w+)\s*\(\s*(void)?\s*\)' ) +void_re = re.compile( r'^([^/]|/[^/])*\bvoid\s*$' ) +test_novoid_re = re.compile( r'^([^/]|/[^/])*\b([Tt]est\w+)\s*\(\s*(void)?\s*\)' ) def scanLineForTest( suite, lineNo, line ): '''Check if current line starts a test''' + global lastLineVoid m = test_re.search( line ) if m: addTest( suite, m.group(2), lineNo ) + lastLineVoid = False + elif lastLineVoid: + m2 = test_novoid_re.search(line) + if m2: + addTest( suite, m2.group(2), lineNo ) + lastLineVoid = False + else: + m3 = void_re.search(line) + if m3: + lastLineVoid = True def addTest( suite, name, line ): '''Add a test function to the current suite''' diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/StandardView.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/StandardView.cpp index 07b671e33b1978ae25a75a51f2993fff59606b3d..0763521df2385581798b8548d913ae53d8c9bd6d 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/StandardView.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/StandardView.cpp @@ -197,8 +197,7 @@ void StandardView::render() return; } pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); - - //setRebinAndUnbinButtons(); + activeSourceChangeListener(this->origSrc); if (this->isPeaksWorkspace(this->origSrc)) { diff --git a/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst b/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst index 5eff1ac7803867a0801c5d824ff19e0f024f1e8f..904b8dd2a5ccd21368da10509b6c936c4aa5fe42 100644 --- a/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst +++ b/Code/Mantid/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst @@ -103,21 +103,61 @@ MDEventWorkspace There is only one *virtual* instrument and *N* ExperimentInfo. *N* is the total number of experiment points in the *experiment*. +Inconsistency between using virtual instrument and copying instrument +===================================================================== + +It is found that the results, i.e., the peak's position in sample-momentum +space, by FindPeaksMD, are different betweent the MDEventWorkspaces +output by this algorithm with copying instrument or creating virtual instrument. + +It is caused by the difference of the instruments in the MDEventWorkspace. +The native HB3A's detector is of type *RectangularDetector*, +while the virtual instrument's detector is just of class *ComAssembly*. + +FindPeaksMD calculates the centre of the mass for peak centre, +and then locates the nearest pixel of the peak center +and re-define the position of the pixel as peak center. + +For virtual instrument, CompAssembly::testIntersectionWithChildren() +is used to find the pixel's position; +while for rectangular detector, RectangularDetector::testIntersectionWithChildren() +is used. +Due to the difference in algorithm, there is slightly difference between +the position of the pixel found. + +Use cases +--------- + +It is found that creating an instrument with tens of thousands detectors is very +time consuming in Mantid. +It is caused by creating a map upon these detectors. +With this generation of Mantid, there is no simple solution for it. + +For HB3A, there are usually :math:`2\theta` scan, :math:`\omega` scan and :math:`\phi`. +Only the :math:`2\theta` scan requires to create virtual instrument, +while the MDEventWorkspace can be created by copying instrument instance +from parent MatrixWorkspace for the other type of scans. + +Therefore, it is suggested to do :math:`\omega` and :math:`\phi` scans for HB3A +with 2D angular detector. + Usage ----- -**Example - convert SPICE file for HB3A to Fullprof file:** +**Example - convert an HB3A's experiment to MDWorkspace in sample momentum workspae and creating virtual instrument.:** -.. testcode:: ExConvertHB3AToMD +.. testcode:: ExConvertHB3AToMDVirtualInstrument # Create input table workspaces for experiment information and virtual instrument parameters CollectHB3AExperimentInfo(ExperimentNumber='355', ScanList='11', PtLists='-1,11', DataDirectory='', + GenerateVirtualInstrument = True, OutputWorkspace='ExpInfoTable', DetectorTableWorkspace='VirtualInstrumentTable') # Convert to MDWorkspace ConvertCWSDExpToMomentum(InputWorkspace='ExpInfoTable', DetectorTableWorkspace='VirtualInstrumentTable', + CreateVirtualInstrument = True, OutputWorkspace='QSampleMD', SourcePosition='0,0,2', SamplePosition='0,0,0', PixelDimension='1,2,2,3,3,4,3,3', Directory='') @@ -135,7 +175,7 @@ Usage print 'In Q-sample frame, center of peak 0 is at (%.5f, %.5f, %.5f) at detector with ID %d'%( qsample.X(), qsample.Y(), qsample.Z(), peak.getDetectorID()) -.. testcleanup:: ExConvertHB3AToMD +.. testcleanup:: ExConvertHB3AToMDVirtualInstrument DeleteWorkspace(Workspace='QSampleMD') DeleteWorkspace(Workspace='ExpInfoTable') @@ -144,12 +184,56 @@ Usage Output: -.. testoutput:: ExConvertHB3AToMD +.. testoutput:: ExConvertHB3AToMDVirtualInstrument Output MDEventWorkspace has 397 events. There are 1 peaks found in output MDWorkspace In Q-sample frame, center of peak 0 is at (-6.95467, -0.06937, 8.14106) at detector with ID 29072 +**Example - convert an HB3A experiment to MDEventWorkspace by copying instrument.:** + +.. testcode:: ExConvertHB3AToMDCopyInstrument + + # Create input table workspaces for experiment information and virtual instrument parameters + CollectHB3AExperimentInfo(ExperimentNumber='355', ScanList='11', PtLists='-1,11', + DataDirectory='', + GenerateVirtualInstrument=False, + OutputWorkspace='ExpInfoTable', DetectorTableWorkspace='VirtualInstrumentTable') + + # Convert to MDWorkspace + ConvertCWSDExpToMomentum(InputWorkspace='ExpInfoTable', + CreateVirtualInstrument = False, + OutputWorkspace='QSampleMD', Directory='') + + # Find peak in the MDEventWorkspace + FindPeaksMD(InputWorkspace='QSampleMD', DensityThresholdFactor=0.10000000000000001, + OutputWorkspace='PeakTable') + + # Examine + mdws = mtd['QSampleMD'] + print 'Output MDEventWorkspace has %d events.'%(mdws.getNEvents()) + peakws = mtd['PeakTable'] + print 'There are %d peaks found in output MDWorkspace'%(peakws.getNumberPeaks()) + peak = peakws.getPeak(0) + qsample = peak.getQSampleFrame() + print 'In Q-sample frame, center of peak 0 is at (%.5f, %.5f, %.5f) at detector with ID %d'%( + qsample.X(), qsample.Y(), qsample.Z(), peak.getDetectorID()) + +.. testcleanup:: ExConvertHB3AToMDCopyInstrument + + DeleteWorkspace(Workspace='QSampleMD') + DeleteWorkspace(Workspace='ExpInfoTable') + DeleteWorkspace(Workspace='VirtualInstrumentTable') + DeleteWorkspace(Workspace='PeakTable') + +Output: + +.. testoutput:: ExConvertHB3AToMDCopyInstrument + + Output MDEventWorkspace has 397 events. + There are 1 peaks found in output MDWorkspace + In Q-sample frame, center of peak 0 is at (-3.57179, -4.37952, -3.01737) at detector with ID 32626 + .. categories:: .. sourcelink:: diff --git a/Code/Mantid/docs/source/algorithms/SaveOpenGenieAscii-v1.rst b/Code/Mantid/docs/source/algorithms/SaveOpenGenieAscii-v1.rst new file mode 100644 index 0000000000000000000000000000000000000000..0c93ff9da3c725ffd20d6137351d8479691e43db --- /dev/null +++ b/Code/Mantid/docs/source/algorithms/SaveOpenGenieAscii-v1.rst @@ -0,0 +1,68 @@ +.. algorithm:: + +.. summary:: + +.. alias:: + +.. properties:: + +Description +----------- + +This algorithm outputs the data in OpenGenie ASCII file, which +can also be generated by `put /New/Ascii... ` on OpenGenie. The +algorithm takes a focused workspaces which would generate an +OpenGenie ASCII file with data saved inside. The algorithm will +assume focused data (which contains single spectrum) has been +provided, but if a workspace with multiple spectra is passed, the +algorithm will save the first spectrum, while ignoring the rest. +The algorithms will write out the x, y and e axis for each spectra +along with all the sample logs which are available in the nexus +file which is provided. The x, y, e axis and the sample logs are +sorted by ascending alphabetical order within the file, which +matches the format of OpenGenie ASCII file. The`ntc` field is +also included, which is required in order to run the generated +file on OpenGenie, the value for `ntc` is the number of bins of +the provided workspace. + +Usage +----- +**Example - a basic example using SaveOpenGenieAscii.** + +.. testcode:: ExSaveOpenGenie + + import os + + ws = CreateSampleWorkspace() + ws = ExtractSingleSpectrum(ws, WorkspaceIndex=0) + file_name = "myworkspace.ascii" + path = os.path.join(os.path.expanduser("~"), file_name) + + SaveOpenGenieAscii(ws, path) + + path = os.path.join(os.path.expanduser("~"), "myworkspace.ascii") + print os.path.isfile(path) + + +Output: + +.. testoutput:: ExSaveOpenGenie + + True + +.. testcleanup:: ExSaveOpenGenie + + import os + def removeFiles(files): + for ws in files: + try: + path = os.path.join(os.path.expanduser("~"), ws) + os.remove(path) + except: + pass + + removeFiles(["myworkspace.ascii"]) + +.. categories:: + +.. sourcelink:: diff --git a/Code/Mantid/docs/source/interfaces/Engineering_Diffraction.rst b/Code/Mantid/docs/source/interfaces/Engineering_Diffraction.rst index 0d0f32f464cebf3ad27eafcb48092bbab3886724..fa92627075643a5f5df84bfa47f8633c0877e737 100644 --- a/Code/Mantid/docs/source/interfaces/Engineering_Diffraction.rst +++ b/Code/Mantid/docs/source/interfaces/Engineering_Diffraction.rst @@ -8,10 +8,10 @@ Overview -------- This custom interface integrates several tasks related to engineeering -diffraction. The interface is under heavy development, and at the -moment it only provides calibration related functionality. The -following sections will describe the different sections or tabs of the -interface. +diffraction. It provides calibration and focusing functionality which +can be expected to expand for next releases as it is under active +development. The following sections describe the different tabs or +functionality areas of the interface. .. interface:: Engineering Diffraction :align: center @@ -54,17 +54,50 @@ Calibration sample # Focus ----- -Here it is possible to focus run files, provided a run number and an -instrument bank. The focusing process uses the algorithm -:ref:`EnggFocus <algm-EnggFocus>`. In the documentation of the -algorithm you can find the details on how the input runs are focused. +Here it is possible to focus run files, provided a run number or run +file. The focusing process uses the algorithm :ref:`EnggFocus +<algm-EnggFocus>`. In the documentation of the algorithm you can find +the details on how the input runs are focused. The interface will also create workspaces that can be inspected in the workspaces window: 1. The *engg_focusing_input_ws workspace* for the data being focused -2. The *engg_focusing_input_ws workspace* for the corresponding - focused data +2. The *engg_focusing_output_ws... workspace* for the corresponding + focused data (where the ... denotes a suffix explained below). + +Three focusing alternatives are provided: + +1. Normal focusing, which includes all the spectra from the input run. +2. Cropped focusing, where several spectra or ranges of spectra can + be specified, as a list separated by commas. +3. Texture focusing, where the *texture* group of detectors is given + in a Detector Gropuing File. + +Depending on the alternative chosen, the focusing operation will +include different banks and/or combinations of spectra (detectors). In +the firs option, normal focusing, all the selected banks and all the +spectra present in the input runs are considered. In the second +alternative, cropped focusing, all the banks are considered in +principle but only a list of spectra provided manually are +processed. In the third option, *texture focusing*, the banks are +defined by a user-defined list of banks and corresponding spectrum IDs +provided in a file. For these alternatives, the output focused +workspace will take different suffixes: *_bank_1, _bank_2*, and so on +for normal focusing, *_cropped* for cropped focusing, and +*_texture_bank_1, _texture_bank_2*, and so on for texture focusing +(using the bank IDs given in the detector grouping file). + +For texture focusing, the detector grouping file is a text (csv) file +with one line per bank. Each line must contain at least two numeric +fields, where the first one specifies the bank ID, and the second and +subsequent ones different spectrum numbers or ranges of spectrum +numbers. For example: +:: + # Bank ID, spectrum numbers + 1, 205-210 + 2, 100, 102, 107 + 3, 300, 310, 320-329, 350-370 Settings -------- diff --git a/Code/Mantid/instrument/BIOSANS_Parameters.xml b/Code/Mantid/instrument/BIOSANS_Parameters.xml index 426f4bff28dbb5de9ae36ed4522b26527b92b948..2a13e9a6e0fea75dbf020db3e12c7c576af71790 100644 --- a/Code/Mantid/instrument/BIOSANS_Parameters.xml +++ b/Code/Mantid/instrument/BIOSANS_Parameters.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<parameter-file instrument = "BIOSANS" valid-from = "2011-03-03 08:35:49"> +<parameter-file instrument = "BIOSANS" valid-from="1900-01-31 23:59:59" valid-to="2012-01-31 23:59:59"> <component-link name = "BIOSANS"> diff --git a/Code/Mantid/instrument/BIOSANS_Parameters_2012.xml b/Code/Mantid/instrument/BIOSANS_Parameters_2012.xml new file mode 100644 index 0000000000000000000000000000000000000000..77406a3d636b8b5cc4b6d9edf4cc31d2c03a0a88 --- /dev/null +++ b/Code/Mantid/instrument/BIOSANS_Parameters_2012.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<parameter-file instrument = "BIOSANS" valid-from="2012-02-01 00:00:00" valid-to="2100-01-31 23:59:59"> + +<component-link name = "BIOSANS"> + +<parameter name="detector-name" type="string"> + <value val="detector1"/> +</parameter> + +<parameter name="default-incident-timer-spectrum"> + <value val="2"/> +</parameter> + +<parameter name="default-incident-monitor-spectrum"> + <value val="1"/> +</parameter> + +<parameter name="number-of-x-pixels"> + <value val="192"/> +</parameter> + +<parameter name="number-of-y-pixels"> + <value val="256"/> +</parameter> + +<parameter name="number-of-monitors"> + <value val="2"/> +</parameter> + +<parameter name="x-pixel-size"> + <value val="5.1000000"/> +</parameter> + +<parameter name="y-pixel-size"> + <value val="5.1000000"/> +</parameter> + +<parameter name="detector-distance-offset"> + <value val="837.9"/> +</parameter> + +<!-- Aperture distances for 8 guides to 0 guides --> +<parameter name="aperture-distances" type="string"> + <value val="2018.0, 3426.9, 5449.1, 7473.8, 9497.2, 11527.1, 13546.6, 15568.2, 17594.6" /> +</parameter> + +<parameter name="source-distance-offset"> + <value val="-171.0"/> +</parameter> + +</component-link> + +</parameter-file> diff --git a/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py b/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py index d555dc0f53d88e4bdaba66ba999ef7582ac4fc13..7140a4df5633e57ccaaca3b9719cc32474b3539f 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py @@ -334,10 +334,13 @@ class DiffractionReductionScripter(BaseReductionScripter): if int(runsetupdict["DisableVanadiumBackgroundCorrection"]) == 1: runsetupdict["VanadiumBackgroundNumber"] = -1 - # b) do sample X + # b) do resample X or binning if int(runsetupdict["DoReSampleX"]) == 0: # turn off the option of SampleX - runsetupdict["ReSampleX"] = "" + runsetupdict["ResampleX"] = '' + else: + # turn off the binning + runsetupdict["Binning"] = '' # c) all properties for propname in runsetupdict.keys(): @@ -350,7 +353,7 @@ class DiffractionReductionScripter(BaseReductionScripter): propvalue = runsetupdict[propname] - if propvalue == "" or propvalue is None: + if propvalue == '' or propvalue is None: # Skip not-defined value continue diff --git a/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_run_setup_script.py b/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_run_setup_script.py index d05f5e60e765cdbd26d45b89289cbb310e58997d..39534b2dd20fa98c929151e56ae68d5c95d4877f 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_run_setup_script.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_run_setup_script.py @@ -183,8 +183,11 @@ class RunSetupScript(BaseScriptElement): "binindspace", default=str(int(RunSetupScript.binindspace))) self.binindspace = bool(int(tempbool)) - self.resamplex = BaseScriptElement.getIntElement(instrument_dom,\ - "resamplex", default=RunSetupScript.resamplex) + try: + self.resamplex = BaseScriptElement.getIntElement(instrument_dom,\ + "resamplex", default=RunSetupScript.resamplex) + except ValueError: + self.resamplex = 0 self.saveas = BaseScriptElement.getStringElement(instrument_dom,\ "saveas", default=RunSetupScript.saveas) diff --git a/Code/Mantid/scripts/Interface/reduction_gui/widgets/diffraction/diffraction_run_setup.py b/Code/Mantid/scripts/Interface/reduction_gui/widgets/diffraction/diffraction_run_setup.py index ebf5f2629f44f09c83eaca3468ec7adb90d83a1b..76b6b5b40c21c4803f5d54c743b2e16735759a20 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/widgets/diffraction/diffraction_run_setup.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/widgets/diffraction/diffraction_run_setup.py @@ -199,6 +199,7 @@ class RunSetupWidget(BaseWidget): def get_state(self): """ Returns a RunSetupScript with the state of Run_Setup_Interface Set up all the class parameters in RunSetupScrpt with values in the content + i.e., get the all parameters from GUI """ s = RunSetupScript(self._instrument_name) @@ -211,15 +212,29 @@ class RunSetupWidget(BaseWidget): s.calibfilename = self._content.calfile_edit.text() s.charfilename = self._content.charfile_edit.text() s.dosum = self._content.sum_checkbox.isChecked() - s.binning = self._content.binning_edit.text() + bintypestr = self._content.bintype_combo.currentText() - if s.binning != "" and s.binning is not None: - if bintypestr.count("Linear") == 1: - s.binning = abs(float(s.binning)) - else: - s.binning = -1.*abs(float(s.binning)) s.binindspace = self._content.binind_checkbox.isChecked() - s.resamplex = int(self._content.resamplex_edit.text()) + + if self._content.resamplex_button.isChecked() is True: + # use ResampleX + s.resamplex = int(self._content.resamplex_edit.text()) + s.doresamplex = True + if s.resamplex <= 0: + raise RuntimeError('ResampleX\'s parameter must be larger than 0!') + # s.binning = '' + else: + # use binning + s.doresamplex = False + # s.resamplex = '' + s.binning = str(self._content.binning_edit.text()) + if len(s.binning) > 0: + if bintypestr.count("Linear") == 1: + s.binning = abs(float(s.binning)) + else: + s.binning = -1.*abs(float(s.binning)) + else: + raise RuntimeError('Binning parameter is not given!') s.outputdir = self._content.outputdir_edit.text() s.saveas = str(self._content.saveas_combo.currentText()) s.finalunits = str(self._content.unit_combo.currentText()) @@ -233,10 +248,6 @@ class RunSetupWidget(BaseWidget): s.vanbkgdrunnumber = self._content.vanbkgdrun_edit.text() s.disablevanbkgdcorrection = self._content.disablevanbkgdcorr_chkbox.isChecked() - s.dosamplex = self._content.resamplex_button.isChecked() - - #s.vannoiserunnumber = self._content.vannoiserun_edit.text() - return s diff --git a/Code/Mantid/scripts/Interface/ui/diffraction/diffraction_run_setup.ui b/Code/Mantid/scripts/Interface/ui/diffraction/diffraction_run_setup.ui index 2a76ff03caf4bab3af71ccfedda3f1e3af3a6436..b63babfb81473dc98150b4dca0803d5fa99df458 100644 --- a/Code/Mantid/scripts/Interface/ui/diffraction/diffraction_run_setup.ui +++ b/Code/Mantid/scripts/Interface/ui/diffraction/diffraction_run_setup.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>1026</width> - <height>1273</height> + <width>1020</width> + <height>805</height> </rect> </property> <property name="sizePolicy"> @@ -32,16 +32,7 @@ <number>8</number> </property> <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> + <property name="margin"> <number>0</number> </property> <item> @@ -78,8 +69,8 @@ <rect> <x>0</x> <y>0</y> - <width>1026</width> - <height>1273</height> + <width>1020</width> + <height>805</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_4"> diff --git a/README.md b/README.md index d8a69fba18a73719d33050ec2162209f1c4d576c..5ab307927d944f0750c4bebffab53e89b97e6b26 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,6 @@ Useful links * Build server: http://builds.mantidproject.org * Developer site: http://developer.mantidproject.org -[](http://builds.mantidproject.org/job/master_clean/) +[](http://builds.mantidproject.org/job/master_incremental/) [](https://coveralls.io/r/mantidproject/mantid?branch=master) [](https://scan.coverity.com/projects/335")