diff --git a/Code/Mantid/Build/CMake/CPackCommon.cmake b/Code/Mantid/Build/CMake/CPackCommon.cmake index 2e7248036fc029ed6e25c99cfa6b3b5263977832..ee3bb1de11dfe7c5522067fb3c8af5ebfe2b91db 100644 --- a/Code/Mantid/Build/CMake/CPackCommon.cmake +++ b/Code/Mantid/Build/CMake/CPackCommon.cmake @@ -7,7 +7,6 @@ set ( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Neutron Scattering Data Analysis" ) set ( CPACK_PACKAGE_VENDOR "ISIS Rutherford Appleton Laboratory and NScD Oak Ridge National Laboratory" ) set ( CPACK_PACKAGE_URL http://www.mantidproject.org/ ) set ( CPACK_PACKAGE_CONTACT mantid-help@mantidproject.org ) -include ( PatchVersionNumber ) set ( CPACK_PACKAGE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} ) set ( CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR} ) set ( CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR} ) diff --git a/Code/Mantid/Build/CMake/CommonSetup.cmake b/Code/Mantid/Build/CMake/CommonSetup.cmake index 1e9ef1cd0a35f31d7b975d131e661b84688d39b2..9c35f190602cf4e3a22641b856110ca7096969a0 100644 --- a/Code/Mantid/Build/CMake/CommonSetup.cmake +++ b/Code/Mantid/Build/CMake/CommonSetup.cmake @@ -80,7 +80,6 @@ endif() # Also makes sure our commit hooks are linked in the right place. ########################################################################### -set ( MtdVersion_WC_LAST_CHANGED_REV 0 ) set ( MtdVersion_WC_LAST_CHANGED_DATE Unknown ) set ( MtdVersion_WC_LAST_CHANGED_DATETIME 0 ) set ( NOT_GIT_REPO "Not" ) @@ -94,14 +93,12 @@ if ( GIT_FOUND ) WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} ) if ( NOT NOT_GIT_REPO ) # i.e This is a git repository! - # Remove the tag name part string ( REGEX MATCH "[-](.*)" MtdVersion_WC_LAST_CHANGED_REV ${GIT_DESCRIBE} ) # Extract the SHA1 part (with a 'g' prefix which stands for 'git') # N.B. The variable comes back from 'git describe' with a line feed on the end, so we need to lose that string ( REGEX MATCH "(g.*)[^\n]" MtdVersion_WC_LAST_CHANGED_SHA ${MtdVersion_WC_LAST_CHANGED_REV} ) - # Get the number part (number of commits since tag) - string ( REGEX MATCH "[0-9]+" MtdVersion_WC_LAST_CHANGED_REV ${MtdVersion_WC_LAST_CHANGED_REV} ) + # Get the date of the last commit execute_process ( COMMAND ${GIT_EXECUTABLE} log -1 --format=format:%cD OUTPUT_VARIABLE MtdVersion_WC_LAST_CHANGED_DATE WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} @@ -190,27 +187,28 @@ else() message ( STATUS "Git not found - using dummy revision number and date" ) endif() -mark_as_advanced( MtdVersion_WC_LAST_CHANGED_REV MtdVersion_WC_LAST_CHANGED_DATE - MtdVersion_WC_LAST_CHANGED_DATETIME ) +mark_as_advanced( MtdVersion_WC_LAST_CHANGED_DATE MtdVersion_WC_LAST_CHANGED_DATETIME ) -########################################################################### -# Include the file that contains the version number -# This must come after the git describe business above because it can be -# used to override the patch version number (MtdVersion_WC_LAST_CHANGED_REV) -########################################################################### - -include ( VersionNumber ) if ( NOT NOT_GIT_REPO ) # i.e This is a git repository! ########################################################################### # Create the file containing the patch version number for use by cpack - # The patch number make have been overridden by VerisonNumber so create + # The patch number make have been overridden by VersionNumber so create # the file used by cpack here ########################################################################### configure_file ( ${GIT_TOP_LEVEL}/Code/Mantid/Build/CMake/PatchVersionNumber.cmake.in ${GIT_TOP_LEVEL}/Code/Mantid/Build/CMake/PatchVersionNumber.cmake ) + include ( PatchVersionNumber ) endif() +########################################################################### +# Include the file that contains the version number +# This must come after the git describe business above because it can be +# used to override the patch version number (MtdVersion_WC_LAST_CHANGED_REV) +########################################################################### +include ( VersionNumber ) + + ########################################################################### # Look for OpenMP and set compiler flags if found ########################################################################### diff --git a/Code/Mantid/Build/CMake/VersionNumber.cmake b/Code/Mantid/Build/CMake/VersionNumber.cmake index 050d54a6e10004c819f20156f495370dda35cbf6..5b8ba9f737acd04ba6f737dbf0d1299fec33f57e 100644 --- a/Code/Mantid/Build/CMake/VersionNumber.cmake +++ b/Code/Mantid/Build/CMake/VersionNumber.cmake @@ -6,5 +6,5 @@ set ( VERSION_MINOR 6 ) # UNCOMMENT the next 'set' line to 'force' the patch version number to # a value (instead of using the count coming out of 'git describe') # DO NOT COMMIT THIS TO MASTER UNCOMMENTED, ONLY TO A RELEASE BRANCH -#set ( MtdVersion_WC_LAST_CHANGED_REV 1 ) +#set ( VERSION_PATCH 0 ) diff --git a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp index 37a51e13f3b55a53e13865a9d88c3dfcb13512cb..b7263e6f226b497b0255861bb60e90b92f3bd5dd 100644 --- a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp +++ b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp @@ -780,6 +780,8 @@ namespace API * date is selected. If no such files are found the file with the latest from date is * selected. * + * If no file is found for the given instrument, an empty string is returned. + * * @param instrumentName :: Instrument name e.g. GEM, TOPAS or BIOSANS * @param date :: ISO 8601 date * @return full path of IDF diff --git a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h index a6508a1dc8fa88e7f86ee30b8c3ee2216e7a52f6..27fd286cdd0ef7ca839bca8a6973f44338366bdb 100644 --- a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h +++ b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h @@ -538,11 +538,13 @@ public: { if (it1 != it2) { - if ( it2->second.from == it1->second.from ) - { - // some more intelligent stuff here later - TS_ASSERT_EQUALS("Two IDFs for one instrument have equal valid-from dates", "0"); - } + // some more intelligent stuff here later + std::stringstream messageBuffer; + messageBuffer << "Two IDFs for one instrument have equal valid-from dates" << + "IDFs are: " << it1->first << " and " << it2->first << + " Date One: "<< it1->second.from.toFormattedString() << + " Date Two: "<< it2->second.from.toFormattedString(); + TSM_ASSERT_DIFFERS(messageBuffer.str(), it2->second.from, it1->second.from); } } diff --git a/Code/Mantid/Framework/Algorithms/CMakeLists.txt b/Code/Mantid/Framework/Algorithms/CMakeLists.txt index 88101f8cad8f827560ec0f57477bd44a60eacc46..a0772d8879a063d6933e999bd2f29ff8a8051a24 100644 --- a/Code/Mantid/Framework/Algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/Algorithms/CMakeLists.txt @@ -104,7 +104,6 @@ set ( SRC_FILES src/FindDetectorsOutsideLimits.cpp src/FindPeaks.cpp src/FindPeakBackground.cpp - src/FlatBackground.cpp src/FlatPlateAbsorption.cpp src/GeneralisedSecondDifference.cpp src/GenerateEventsFilter.cpp @@ -328,7 +327,6 @@ set ( INC_FILES inc/MantidAlgorithms/FindDetectorsOutsideLimits.h inc/MantidAlgorithms/FindPeaks.h inc/MantidAlgorithms/FindPeakBackground.h - inc/MantidAlgorithms/FlatBackground.h inc/MantidAlgorithms/FlatPlateAbsorption.h inc/MantidAlgorithms/GSLFunctions.h inc/MantidAlgorithms/GeneralisedSecondDifference.h @@ -556,7 +554,6 @@ set ( TEST_FILES FindDetectorsOutsideLimitsTest.h FindPeaksTest.h FindPeakBackgroundTest.h - FlatBackgroundTest.h FlatPlateAbsorptionTest.h GenerateEventsFilterTest.h GeneratePeaksTest.h diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h index f6ae4c311bb63585d8499c6494556b26d436ff37..266c77aba6512d9e24a7fadce30b57069c2fe110 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CheckWorkspacesMatch.h @@ -5,6 +5,8 @@ // Includes //---------------------------------------------------------------------- #include "MantidAPI/Algorithm.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidDataObjects/EventWorkspace.h" namespace Mantid { @@ -38,10 +40,7 @@ namespace Algorithms <LI> Result - Contains 'success' if the workspaces match, the reason for the failure otherwise </LI> </UL> - @author Russell Taylor, Tessella Support Services plc - @date 01/12/2009 - - Copyright © 2009 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + Copyright © 2009-2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory This file is part of Mantid. @@ -92,11 +91,11 @@ private: /// Execution code void exec(); - // property indicate that relative error tolerance in data is set up rather then absolute error. - bool m_ErrorIsRelative; void doComparison(); - // Compare two MD workspaces + void doPeaksComparison(API::IPeaksWorkspace_sptr tws1, API::IPeaksWorkspace_sptr tws2); + void doTableComparison(API::ITableWorkspace_const_sptr tws1, API::ITableWorkspace_const_sptr tws2); void doMDComparison(API::Workspace_sptr w1, API::Workspace_sptr w2); + bool checkEventLists(DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2); bool checkData(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); bool checkAxes(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); bool checkSpectraMap(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2); diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h index ee05215f87bbf30a3a752275d9bcaf8cf8d119ae..b6bf2960d8f2ae1c8b3126ff20a1c53177b29894 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/CopySample.h @@ -55,7 +55,8 @@ namespace Algorithms virtual int version() const { return 1;}; /// Algorithm's category for identification virtual const std::string category() const { return "Sample;Utility\\Workspaces;DataHandling";} - + /// @inheritdocs + virtual std::map<std::string, std::string> validateInputs(); private: /// Sets documentation strings for this algorithm virtual void initDocs(); @@ -64,9 +65,7 @@ namespace Algorithms /// Run the algorithm void exec(); /// Function to copy information from one sample to another - void copyParameters(API::Sample& from,API::Sample& to,bool nameFlag,bool materialFlag, bool environmentFlag, bool shapeFlag,bool latticeFlag); - - + void copyParameters(API::Sample& from, API::Sample& to, bool nameFlag, bool materialFlag, bool environmentFlag, bool shapeFlag, bool latticeFlag, bool orientationOnlyFlag); }; diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/FlatBackground.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/FlatBackground.h deleted file mode 100644 index df697064f7832e1da8e479ec808287bd18376d7d..0000000000000000000000000000000000000000 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/FlatBackground.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef MANTID_ALGORITHMS_FLATBACKGROUND_H_ -#define MANTID_ALGORITHMS_FLATBACKGROUND_H_ - -//---------------------------------------------------------------------- -// Includes -//---------------------------------------------------------------------- -#include "MantidAPI/Algorithm.h" -#include "MantidAPI/DeprecatedAlgorithm.h" - -namespace Mantid -{ -namespace Algorithms -{ -/** Finds a constant value fit to an appropriate range of each desired spectrum - and subtracts that value from the entire spectrum. - - Required Properties: - <UL> - <LI> InputWorkspace - The name of the input workspace. </LI> - <LI> OutputWorkspace - The name to give the output workspace. </LI> - <LI> SpectrumIndexList - The workspace indices of the spectra to fit background to. </LI> - <LI> StartX - The start of the flat region to fit to. </LI> - <LI> EndX - The end of the flat region to fit to. </LI> - <LI> Mode - How to estimate the background number of counts: a linear fit or the mean. </LI> - <LI> OutputMode - What to return in the Outputworkspace: the corrected signal or just the background. </LI> - </UL> - - @author Russell Taylor, Tessella plc - @date 5/02/2009 - - Copyright © 2009 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - - This file is part of Mantid. - - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - File change history is stored at: <https://github.com/mantidproject/mantid> - Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class DLLExport FlatBackground : public API::Algorithm, public API::DeprecatedAlgorithm -{ -public: - /// Constructor - FlatBackground(); - /// Virtual destructor - virtual ~FlatBackground() {if(m_progress) delete m_progress;m_progress=NULL;} - /// Algorithm's name - virtual const std::string name() const { return "FlatBackground"; } - /// Algorithm's version - virtual int version() const { return (1); } - /// Algorithm's category for identification - virtual const std::string category() const { return "Deprecated"; } - -private: - /// Sets documentation strings for this algorithm - virtual void initDocs(); - /// Initialisation code - void init(); - ///Execution code - void exec(); - - void convertToDistribution(API::MatrixWorkspace_sptr workspace); - void restoreDistributionState(API::MatrixWorkspace_sptr workspace); - void checkRange(double& startX, double& endX); - void getSpecInds(std::vector<int> &output, const int workspaceTotal); - double Mean(const API::MatrixWorkspace_const_sptr WS, const int specInd, const double startX, const double endX, double &variance) const; - double LinearFit(API::MatrixWorkspace_sptr WS, int spectrum, double startX, double endX); - - /// variable bin width raw count data must be converted to distributions first and then converted back, keep track of this - bool m_convertedFromRawCounts; - /// Progress reporting - API::Progress* m_progress; - -}; - -} // namespace Algorithms -} // namespace Mantid - -#endif /*MANTID_ALGORITHMS_FLATBACKGROUND_H_*/ diff --git a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp index 71c52227a2760a9bd128530558805aba0593a6fb..254a0387f4c3571af85e9534c2f522e2e5a979cb 100644 --- a/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CheckWorkspacesMatch.cpp @@ -17,8 +17,9 @@ In the case of [[EventWorkspace]]s, they are checked to hold identical event lis #include "MantidAPI/IMDEventWorkspace.h" #include "MantidAPI/IMDHistoWorkspace.h" #include "MantidAPI/WorkspaceGroup.h" +#include "MantidAPI/IPeak.h" +#include "MantidAPI/TableRow.h" #include "MantidDataObjects/EventWorkspace.h" -#include "MantidDataObjects/PeaksWorkspace.h" #include "MantidGeometry/MDGeometry/IMDDimension.h" #include <sstream> @@ -162,7 +163,8 @@ void CheckWorkspacesMatch::init() declareProperty("Result","",Direction::Output); - declareProperty("ToleranceRelErr",false, "Treat tolerance as relative error rather then the absolute error"); + declareProperty("ToleranceRelErr",false, "Treat tolerance as relative error rather then the absolute error.\n"\ + "This is only applicable to Matrix workspaces."); declareProperty("CheckAllData",false, "Usually checking data ends when first mismatch occurs. This forces algorithm to check all data and print mismatch to the debug log.\n"\ "Very often such logs are huge so making it true should be the last option."); // Have this one false by default - it can be a lot of printing. @@ -173,7 +175,7 @@ void CheckWorkspacesMatch::init() void CheckWorkspacesMatch::exec() { result.clear(); - m_ErrorIsRelative = getProperty("ToleranceRelerr"); + this->doComparison(); if ( result != "") @@ -195,195 +197,81 @@ void CheckWorkspacesMatch::doComparison() Workspace_sptr w1 = getProperty("Workspace1"); Workspace_sptr w2 = getProperty("Workspace2"); - // Not implemented yet for table workspaces - if ( w1->id() == "TableWorkspace" || w2->id() == "TableWorkspace" ) - { - throw Kernel::Exception::NotImplementedError("This algorithm does not (yet) work for table workspaces"); - } + // ============================================================================== + // Peaks workspaces + // ============================================================================== // Check that both workspaces are the same type - bool checkType = getProperty("CheckType"); - PeaksWorkspace_sptr tws1, tws2; - tws1 = boost::dynamic_pointer_cast<PeaksWorkspace>(w1); - tws2 = boost::dynamic_pointer_cast<PeaksWorkspace>(w2); - if (checkType) + IPeaksWorkspace_sptr pws1 = boost::dynamic_pointer_cast<IPeaksWorkspace>(w1); + IPeaksWorkspace_sptr pws2 = boost::dynamic_pointer_cast<IPeaksWorkspace>(w2); + if ((pws1 && !pws2) ||(!pws1 && pws2)) { - if ((tws1 && !tws2) ||(!tws1 && tws2)) - { - result = "One workspace is an PeaksWorkspace and the other is not."; - return; - } + result = "One workspace is a PeaksWorkspace and the other is not."; + return; } // Check some peak-based stuff - if (tws1 && tws2) + if (pws1 && pws2) { - // Check some table-based stuff - if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) - { - result = "Mismatched number of rows."; - return; - } - if (tws1->columnCount() != tws2->columnCount()) - { - result = "Mismatched number of columns."; - return; - } - - // sort the workspaces before comparing - { - auto sortPeaks = createChildAlgorithm("SortPeaksWorkspace"); - sortPeaks->setProperty("InputWorkspace", tws1); - sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing"); - sortPeaks->setProperty("SortAscending", true); - sortPeaks->executeAsChildAlg(); - IPeaksWorkspace_sptr temp = sortPeaks->getProperty("OutputWorkspace"); - tws1 = boost::dynamic_pointer_cast<PeaksWorkspace>(temp); - - sortPeaks = createChildAlgorithm("SortPeaksWorkspace"); - sortPeaks->setProperty("InputWorkspace", tws2); - sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing"); - sortPeaks->setProperty("SortAscending", true); - sortPeaks->executeAsChildAlg(); - temp = sortPeaks->getProperty("OutputWorkspace"); - tws2 = boost::dynamic_pointer_cast<PeaksWorkspace>(temp); - } - - const double tolerance = getProperty("Tolerance"); - for (int i =0; i<tws1->getNumberPeaks(); i++) - { - Peak & peak1 = tws1->getPeaks()[i]; - Peak & peak2 = tws2->getPeaks()[i]; - for (size_t j =0; j<tws1->columnCount(); j++) - { - boost::shared_ptr<const API::Column> col = tws1->getColumn(j); - std::string name = col->name(); - double s1 = 0.0; - double s2 = 0.0; - if (name == "runnumber") - { - s1 = double(peak1.getRunNumber()); - s2 = double(peak2.getRunNumber()); - } - else if (name == "detid") - { - s1 = double(peak1.getDetectorID()); - s2 = double(peak2.getDetectorID()); - } - else if (name == "h") - { - s1 = peak1.getH(); - s2 = peak2.getH(); - } - else if (name == "k") - { - s1 = peak1.getK(); - s2 = peak2.getK(); - } - else if (name == "l") - { - s1 = peak1.getL(); - s2 = peak2.getL(); - } - else if (name == "wavelength") - { - s1 = peak1.getWavelength(); - s2 = peak2.getWavelength(); - } - else if (name == "energy") - { - s1 = peak1.getInitialEnergy(); - s2 = peak2.getInitialEnergy(); - } - else if (name == "tof") - { - s1 = peak1.getTOF(); - s2 = peak2.getTOF(); - } - else if (name == "dspacing") - { - s1 = peak1.getDSpacing(); - s2 = peak2.getDSpacing(); - } - else if (name == "intens") - { - s1 = peak1.getIntensity(); - s2 = peak2.getIntensity(); - } - else if (name == "sigint") - { - s1 = peak1.getSigmaIntensity(); - s2 = peak2.getSigmaIntensity(); - } - else if (name == "bincount") - { - s1 = peak1.getBinCount(); - s2 = peak2.getBinCount(); - } - else if (name == "row") - { - s1 = peak1.getRow(); - s2 = peak2.getRow(); - } - else if (name == "col") - { - s1 = peak1.getCol(); - s2 = peak2.getCol(); - } - if (std::fabs(s1 - s2) > tolerance) - { - g_log.debug() << "Data mismatch at cell (row#,col#): (" << i << "," << j << ")\n"; - result = "Data mismatch"; - return; - } - } - } + doPeaksComparison(pws1,pws2); return; } - // Check things for IMDEventWorkspaces - IMDEventWorkspace_const_sptr mdews1, mdews2; - mdews1 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w1); - mdews2 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w2); - if (checkType) + // ============================================================================== + // Table workspaces + // ============================================================================== + + // Check that both workspaces are the same type + auto tws1 = boost::dynamic_pointer_cast<const ITableWorkspace>(w1); + auto tws2 = boost::dynamic_pointer_cast<const ITableWorkspace>(w2); + if ((tws1 && !tws2) ||(!tws1 && tws2)) { - if ((mdews1 && !mdews2) ||(!mdews1 && mdews2)) - { - result = "One workspace is an IMDEventWorkspace and the other is not."; - return; - } + result = "One workspace is a TableWorkspace and the other is not."; + return; } - if (mdews1 && mdews2) + if (tws1 && tws2) { - this->doMDComparison(w1, w2); + doTableComparison(tws1,tws2); return; } + // ============================================================================== + // MD workspaces + // ============================================================================== + + // Check things for IMDEventWorkspaces + IMDEventWorkspace_const_sptr mdews1 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w1); + IMDEventWorkspace_const_sptr mdews2 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w2); + if ((mdews1 && !mdews2) ||(!mdews1 && mdews2)) + { + result = "One workspace is an IMDEventWorkspace and the other is not."; + return; + } // Check things for IMDHistoWorkspaces - IMDHistoWorkspace_const_sptr mdhws1, mdhws2; - mdhws1 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w1); - mdhws2 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w2); - if (checkType) + IMDHistoWorkspace_const_sptr mdhws1 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w1); + IMDHistoWorkspace_const_sptr mdhws2 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w2); + if ((mdhws1 && !mdhws2) ||(!mdhws1 && mdhws2)) { - if ((mdhws1 && !mdhws2) ||(!mdhws1 && mdhws2)) - { - result = "One workspace is an IMDHistoWorkspace and the other is not."; - return; - } + result = "One workspace is an IMDHistoWorkspace and the other is not."; + return; } - if (mdhws1 && mdhws2) + + if (mdhws1 || mdews1) // The '2' workspaces must match because of the checks above { this->doMDComparison(w1, w2); return; } - MatrixWorkspace_const_sptr ws1, ws2; - ws1 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w1); - ws2 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w2); + // ============================================================================== + // Event workspaces + // ============================================================================== - EventWorkspace_const_sptr ews1, ews2; - ews1 = boost::dynamic_pointer_cast<const EventWorkspace>(ws1); - ews2 = boost::dynamic_pointer_cast<const EventWorkspace>(ws2); - if (checkType) + // These casts must succeed or there's a logical problem in the code + MatrixWorkspace_const_sptr ws1 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w1); + MatrixWorkspace_const_sptr ws2 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w2); + + EventWorkspace_const_sptr ews1 = boost::dynamic_pointer_cast<const EventWorkspace>(ws1); + EventWorkspace_const_sptr ews2 = boost::dynamic_pointer_cast<const EventWorkspace>(ws2); + if ( getProperty("CheckType") ) { if ((ews1 && !ews2) ||(!ews1 && ews2)) { @@ -398,51 +286,7 @@ void CheckWorkspacesMatch::doComparison() { prog = new Progress(this, 0.0, 1.0, numhist*5); - // Both will end up sorted anyway - ews1->sortAll(PULSETIMETOF_SORT, prog); - ews2->sortAll(PULSETIMETOF_SORT, prog); - - if (ews1->getNumberHistograms() != ews2->getNumberHistograms()) - { - result = "Mismatched number of histograms."; - return; - } - - // determine the tolerance for "tof" attribute of events - double ToleranceTOF = Tolerance; - // actual time-of flight is 50 nanoseconds - if ((ws1->getAxis(0)->unit()->label() == "microsecond") - || (ws2->getAxis(0)->unit()->label() == "microsecond")) - ToleranceTOF = 0.05; - - bool mismatchedEvent = false; - int mismatchedEventWI = 0; - //PARALLEL_FOR2(ews1, ews2) - for (int i=0; i<static_cast<int>(ews1->getNumberHistograms()); i++) - { - PARALLEL_START_INTERUPT_REGION - prog->report("EventLists"); - if (!mismatchedEvent) // This guard will avoid checking unnecessarily - { - const EventList &el1 = ews1->getEventList(i); - const EventList &el2 = ews2->getEventList(i); - if (!el1.equals(el2, ToleranceTOF, Tolerance, 1)) - { - mismatchedEvent = true; - mismatchedEventWI = i; - } - } - PARALLEL_END_INTERUPT_REGION - } - PARALLEL_CHECK_INTERUPT_REGION - - if ( mismatchedEvent) - { - std::ostringstream mess; - mess << "Mismatched event list at workspace index " << mismatchedEventWI; - result = mess.str(); - return; - } + if ( ! checkEventLists(ews1, ews2) ) return; } else { @@ -450,6 +294,9 @@ void CheckWorkspacesMatch::doComparison() prog = new Progress(this, 0.0, 1.0, numhist*2); } + // ============================================================================== + // Matrix workspaces (Event & 2D) + // ============================================================================== // First check the data - always do this if ( ! checkData(ws1,ws2) ) return; @@ -473,11 +320,63 @@ void CheckWorkspacesMatch::doComparison() return; } -/// Checks that the data matches -/// @param ws1 :: the first workspace -/// @param ws2 :: the second workspace -/// @retval true The data matches -/// @retval false The data does not matches +bool CheckWorkspacesMatch::checkEventLists(DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2) +{ + // Both will end up sorted anyway + ews1->sortAll(PULSETIMETOF_SORT, prog); + ews2->sortAll(PULSETIMETOF_SORT, prog); + + if (ews1->getNumberHistograms() != ews2->getNumberHistograms()) + { + result = "Mismatched number of histograms."; + return false; + } + + // determine the tolerance for "tof" attribute of events + double ToleranceTOF = Tolerance; + // actual time-of flight is 50 nanoseconds + if ((ews1->getAxis(0)->unit()->label() == "microsecond") + || (ews2->getAxis(0)->unit()->label() == "microsecond")) + ToleranceTOF = 0.05; + + bool mismatchedEvent = false; + int mismatchedEventWI = 0; + //PARALLEL_FOR2(ews1, ews2) + for (int i=0; i<static_cast<int>(ews1->getNumberHistograms()); i++) + { + PARALLEL_START_INTERUPT_REGION + prog->report("EventLists"); + if (!mismatchedEvent) // This guard will avoid checking unnecessarily + { + const EventList &el1 = ews1->getEventList(i); + const EventList &el2 = ews2->getEventList(i); + if (!el1.equals(el2, ToleranceTOF, Tolerance, 1)) + { + mismatchedEvent = true; + mismatchedEventWI = i; + } + } + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + + if ( mismatchedEvent) + { + std::ostringstream mess; + mess << "Mismatched event list at workspace index " << mismatchedEventWI; + result = mess.str(); + return false; + } + + return true; +} + +/** Checks that the data matches + * @param ws1 :: the first workspace + * @param ws2 :: the second workspace + * @retval true The data matches + * @retval false The data does not matches + */ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2) { // Cache a few things for later use @@ -522,7 +421,7 @@ bool CheckWorkspacesMatch::checkData(API::MatrixWorkspace_const_sptr ws1, API::M const MantidVec& Y2 = ws2->readY(i); const MantidVec& E2 = ws2->readE(i); - bool RelErr = m_ErrorIsRelative; + bool RelErr = getProperty("ToleranceRelErr"); for ( int j = 0; j < static_cast<int>(numBins); ++j ) { bool err; @@ -852,6 +751,185 @@ bool CheckWorkspacesMatch::checkRunProperties(const API::Run& run1, const API::R return true; } +void CheckWorkspacesMatch::doPeaksComparison(API::IPeaksWorkspace_sptr tws1, API::IPeaksWorkspace_sptr tws2) +{ + // Check some table-based stuff + if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) + { + result = "Mismatched number of rows."; + return; + } + if (tws1->columnCount() != tws2->columnCount()) + { + result = "Mismatched number of columns."; + return; + } + + // sort the workspaces before comparing + { + auto sortPeaks = createChildAlgorithm("SortPeaksWorkspace"); + sortPeaks->setProperty("InputWorkspace", tws1); + sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing"); + sortPeaks->setProperty("SortAscending", true); + sortPeaks->executeAsChildAlg(); + tws1 = sortPeaks->getProperty("OutputWorkspace"); + + sortPeaks = createChildAlgorithm("SortPeaksWorkspace"); + sortPeaks->setProperty("InputWorkspace", tws2); + sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing"); + sortPeaks->setProperty("SortAscending", true); + sortPeaks->executeAsChildAlg(); + tws2 = sortPeaks->getProperty("OutputWorkspace"); + } + + const double tolerance = getProperty("Tolerance"); + for (int i =0; i<tws1->getNumberPeaks(); i++) + { + const IPeak & peak1 = tws1->getPeak(i); + const IPeak & peak2 = tws2->getPeak(i); + for (size_t j =0; j<tws1->columnCount(); j++) + { + boost::shared_ptr<const API::Column> col = tws1->getColumn(j); + std::string name = col->name(); + double s1 = 0.0; + double s2 = 0.0; + if (name == "runnumber") + { + s1 = double(peak1.getRunNumber()); + s2 = double(peak2.getRunNumber()); + } + else if (name == "detid") + { + s1 = double(peak1.getDetectorID()); + s2 = double(peak2.getDetectorID()); + } + else if (name == "h") + { + s1 = peak1.getH(); + s2 = peak2.getH(); + } + else if (name == "k") + { + s1 = peak1.getK(); + s2 = peak2.getK(); + } + else if (name == "l") + { + s1 = peak1.getL(); + s2 = peak2.getL(); + } + else if (name == "wavelength") + { + s1 = peak1.getWavelength(); + s2 = peak2.getWavelength(); + } + else if (name == "energy") + { + s1 = peak1.getInitialEnergy(); + s2 = peak2.getInitialEnergy(); + } + else if (name == "tof") + { + s1 = peak1.getTOF(); + s2 = peak2.getTOF(); + } + else if (name == "dspacing") + { + s1 = peak1.getDSpacing(); + s2 = peak2.getDSpacing(); + } + else if (name == "intens") + { + s1 = peak1.getIntensity(); + s2 = peak2.getIntensity(); + } + else if (name == "sigint") + { + s1 = peak1.getSigmaIntensity(); + s2 = peak2.getSigmaIntensity(); + } + else if (name == "bincount") + { + s1 = peak1.getBinCount(); + s2 = peak2.getBinCount(); + } + else if (name == "row") + { + s1 = peak1.getRow(); + s2 = peak2.getRow(); + } + else if (name == "col") + { + s1 = peak1.getCol(); + s2 = peak2.getCol(); + } + if (std::fabs(s1 - s2) > tolerance) + { + g_log.debug() << "Data mismatch at cell (row#,col#): (" << i << "," << j << ")\n"; + result = "Data mismatch"; + return; + } + } + } + return; +} + +void CheckWorkspacesMatch::doTableComparison(API::ITableWorkspace_const_sptr tws1, API::ITableWorkspace_const_sptr tws2) +{ + // First the easy things + const auto numCols = tws1->columnCount(); + if ( numCols != tws2->columnCount() ) + { + g_log.debug() << "Number of columns mismatch (" << numCols << " vs " << tws2->columnCount() << ")\n"; + result = "Number of columns mismatch"; + return; + } + const auto numRows = tws1->rowCount(); + if ( numRows != tws2->rowCount() ) + { + g_log.debug() << "Number of rows mismatch (" << numRows << " vs " << tws2->rowCount() << ")\n"; + result = "Number of rows mismatch"; + return; + } + + for (size_t i = 0; i < numCols; ++i) + { + auto c1 = tws1->getColumn(i); + auto c2 = tws2->getColumn(i); + + if ( c1->name() != c2->name() ) + { + g_log.debug() << "Column name mismatch at column " << i << " (" << c1->name() << " vs " << c2->name() << ")\n"; + result = "Column name mismatch"; + return; + } + if ( c1->type() != c2->type() ) + { + g_log.debug() << "Column type mismatch at column " << i << " (" << c1->type() << " vs " << c2->type() << ")\n"; + result = "Column type mismatch"; + return; + } + } + + const bool checkAllData = getProperty("CheckAllData"); + + for (size_t i = 0; i < numRows; ++i) + { + const TableRow r1 = boost::const_pointer_cast<ITableWorkspace>(tws1)->getRow(i); + const TableRow r2 = boost::const_pointer_cast<ITableWorkspace>(tws2)->getRow(i); + // Easiest, if not the fastest, way to compare is via strings + std::stringstream r1s, r2s; + r1s << r1; + r2s << r2; + if ( r1s.str() != r2s.str() ) + { + g_log.debug() << "Table data mismatch at row " << i << " (" << r1s << " vs " << r2s << ")\n"; + result = "Table data mismatch"; + if ( !checkAllData ) return; + } + } // loop over columns +} + void CheckWorkspacesMatch::doMDComparison(Workspace_sptr w1, Workspace_sptr w2) { IMDWorkspace_sptr mdws1, mdws2; diff --git a/Code/Mantid/Framework/Algorithms/src/CopySample.cpp b/Code/Mantid/Framework/Algorithms/src/CopySample.cpp index 71d06d4c0e683fb58db6b08f4d770b85fca2d92a..922fe6df593d07547d1b0f95a6fb4f9e34736dec 100644 --- a/Code/Mantid/Framework/Algorithms/src/CopySample.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CopySample.cpp @@ -9,6 +9,7 @@ The following information can be copied: * Shape * Oriented lattice +One can copy the orientation matrix only. To do this, select both CopyLattice and CopyOrientationOnly. If only CopyOrientationOnly is true, the algorithm will throw an error. *WIKI*/ #include "MantidAlgorithms/CopySample.h" @@ -16,7 +17,7 @@ The following information can be copied: #include "MantidAPI/IMDEventWorkspace.h" #include "MantidAPI/SampleEnvironment.h" #include "MantidGeometry/Crystal/OrientedLattice.h" - +#include "MantidKernel/EnabledWhenProperty.h" namespace Mantid { namespace Algorithms @@ -64,10 +65,25 @@ namespace Algorithms declareProperty(new PropertyWithValue<bool>("CopyEnvironment",true,Direction::Input),"Copy the sample environment" ); declareProperty(new PropertyWithValue<bool>("CopyShape",true,Direction::Input),"Copy the sample shape" ); declareProperty(new PropertyWithValue<bool>("CopyLattice",true,Direction::Input),"Copy the sample oriented lattice" ); + declareProperty(new PropertyWithValue<bool>("CopyOrientationOnly",false,Direction::Input),"Copy the U matrix only, if both origin and destination have oriented lattices" ); + setPropertySettings("CopyOrientationOnly",new Kernel::EnabledWhenProperty("CopyLattice",IS_EQUAL_TO,"1")); declareProperty(new PropertyWithValue<int>("MDInputSampleNumber",0,Direction::Input),"The number of the sample to be copied from, for an MD workspace (starting from 0)" ); declareProperty(new PropertyWithValue<int>("MDOutputSampleNumber",EMPTY_INT(),Direction::Input),"The number of the sample to be copied to for an MD workspace (starting from 0). No number, or negative number, means that it will copy to all samples" ); } + + std::map<std::string, std::string> CopySample::validateInputs() + { + std::map<std::string, std::string> result; + const bool copyLattice = getProperty("CopyLattice"); + const bool copyOrientationOnly = getProperty("CopyOrientationOnly"); + if (copyOrientationOnly && !copyLattice) + { + result["CopyLattice"] = "Need to check CopyLattice if CopyOrientationOnly is checked"; + } + return result; + } + //---------------------------------------------------------------------------------------------- /** Execute the algorithm. */ @@ -106,6 +122,7 @@ namespace Algorithms bool copyEnvironment=getProperty("CopyEnvironment"); bool copyShape=getProperty("CopyShape"); bool copyLattice=getProperty("CopyLattice"); + bool copyOrientation=getProperty("CopyOrientationOnly"); //Sample copy; @@ -116,7 +133,7 @@ namespace Algorithms if ((outputSampleNumber==EMPTY_INT()) || (outputSampleNumber<0)) //copy to all samples { for(uint16_t i=0;i<outMDWS->getNumExperimentInfo();i++) - copyParameters(sample,outMDWS->getExperimentInfo(i)->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice); + copyParameters(sample,outMDWS->getExperimentInfo(i)->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice, copyOrientation); } else //copy to a single sample { @@ -125,19 +142,19 @@ namespace Algorithms g_log.warning()<<"Number greater than the number of last sample in the workspace ("<<(outMDWS->getNumExperimentInfo()-1)<<"). Will use sample number 0 instead\n"; outputSampleNumber=0; } - copyParameters(sample,outMDWS->getExperimentInfo(static_cast<uint16_t>(outputSampleNumber))->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice); + copyParameters(sample,outMDWS->getExperimentInfo(static_cast<uint16_t>(outputSampleNumber))->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice, copyOrientation); } } else //peaks workspace or matrix workspace { ExperimentInfo_sptr ei=boost::dynamic_pointer_cast<ExperimentInfo>(outWS); if (!ei) throw std::invalid_argument("Wrong type of output workspace"); - copyParameters(sample,ei->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice); + copyParameters(sample,ei->mutableSample(),copyName,copyMaterial,copyEnvironment,copyShape,copyLattice, copyOrientation); } this->setProperty("OutputWorkspace",outWS); } - void CopySample::copyParameters(Sample& from,Sample& to,bool nameFlag,bool materialFlag, bool environmentFlag, bool shapeFlag,bool latticeFlag) + void CopySample::copyParameters(Sample& from,Sample& to,bool nameFlag,bool materialFlag, bool environmentFlag, bool shapeFlag,bool latticeFlag, bool orientationOnlyFlag) { if (nameFlag) to.setName(from.getName()); if (materialFlag) to.setMaterial(from.getMaterial()); @@ -150,7 +167,18 @@ namespace Algorithms to.setThickness(from.getThickness()); to.setWidth(from.getWidth()); } - if ((latticeFlag) && from.hasOrientedLattice()) to.setOrientedLattice(new Geometry::OrientedLattice(from.getOrientedLattice())); + if ((latticeFlag) && from.hasOrientedLattice()) + { + if (to.hasOrientedLattice() && orientationOnlyFlag) + { + to.getOrientedLattice().setU(from.getOrientedLattice().getU()); + } + else + { + to.setOrientedLattice(new Geometry::OrientedLattice(from.getOrientedLattice())); + } + } + } diff --git a/Code/Mantid/Framework/Algorithms/src/FlatBackground.cpp b/Code/Mantid/Framework/Algorithms/src/FlatBackground.cpp deleted file mode 100644 index d092aaa5b9e44755b6653b01af3283dcf83ea568..0000000000000000000000000000000000000000 --- a/Code/Mantid/Framework/Algorithms/src/FlatBackground.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/*WIKI* - -This algorithm takes a list of spectra and for each spectrum calculates an average count rate in the given region, usually a region when there are only background neutrons. This count rate is then subtracted from the counts in all the spectrum's bins. However, no bin will take a negative value as bins with count rates less than the background are set to zero (and their error is set to the backgound value). - -The average background count rate is estimated in one of two ways. When Mode is set to 'Mean' it is the sum of the values in the bins in the background region divided by the width of the X range. Selecting 'Linear Fit' sets the background value to the height in the centre of the background region of a line of best fit through that region. - -The error on the background value is only calculated when 'Mean' is used. It is the errors in all the bins in the background region summed in quadrature divided by the number of bins. This background error value is added in quadrature to the errors in each bin. - -====ChildAlgorithms used==== -The [[Linear]] algorithm is used when the Mode = Linear Fit. From the resulting line of best fit a constant value taken as the value of the line at the centre of the fitted range. - - -*WIKI*/ -//---------------------------------------------------------------------- -// Includes -//---------------------------------------------------------------------- -#include "MantidAlgorithms/FlatBackground.h" -#include "MantidAPI/WorkspaceValidators.h" -#include "MantidAPI/WorkspaceOpOverloads.h" -#include "MantidKernel/ArrayProperty.h" -#include "MantidKernel/VectorHelper.h" -#include <algorithm> -#include <climits> -#include "MantidKernel/ListValidator.h" -#include "MantidKernel/MandatoryValidator.h" - -namespace Mantid -{ -namespace Algorithms -{ - -// Register the algorithm into the AlgorithmFactory -DECLARE_ALGORITHM(FlatBackground) - -/// Sets documentation strings for this algorithm -void FlatBackground::initDocs() -{ - this->setWikiSummary("Finds a constant value fit to an appropriate range of each desired spectrum and subtracts that value from the entire spectrum. "); - this->setOptionalMessage("Finds a constant value fit to an appropriate range of each desired spectrum and subtracts that value from the entire spectrum."); -} - - -using namespace Kernel; -using namespace API; - -FlatBackground::FlatBackground() : API::Algorithm(), m_convertedFromRawCounts(false), m_progress(NULL) -{ - this->useAlgorithm("CalculateFlatBackground"); - this->deprecatedDate("2013-05-21"); -} - -void FlatBackground::init() -{ - declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input, - boost::make_shared<HistogramValidator>() ), - "The input workspace must either have constant width bins or is a distribution\n" - "workspace. It is also assumed that all spectra have the same X bin boundaries"); - declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output ), - "Name to use for the output workspace."); - auto mustHaveValue = boost::make_shared<MandatoryValidator<double> >(); - - declareProperty("StartX", Mantid::EMPTY_DBL(), mustHaveValue, - "The X value at which to start the background fit"); - declareProperty("EndX", Mantid::EMPTY_DBL(), mustHaveValue, - "The X value at which to end the background fit"); - declareProperty(new ArrayProperty<int>("WorkspaceIndexList"), - "Indices of the spectra that will have their background removed\n" - "default: modify all spectra"); - std::vector<std::string> modeOptions; - modeOptions.push_back("Linear Fit"); - modeOptions.push_back("Mean"); - declareProperty("Mode","Linear Fit",boost::make_shared<StringListValidator>(modeOptions), - "The background count rate is estimated either by taking a mean or doing a\n" - "linear fit (default: Linear Fit)"); - // Property to determine whether we subtract the background or just return the background. - std::vector<std::string> outputOptions; - outputOptions.push_back("Subtract Background"); - outputOptions.push_back("Return Background"); - declareProperty("OutputMode", "Subtract Background", boost::make_shared<StringListValidator>(outputOptions), - "Once the background has been determined it can either be subtracted from \n" - "the InputWorkspace and returned or just returned (default: Subtract Background)"); -} - -void FlatBackground::exec() -{ - // Retrieve the input workspace - MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); - // Copy over all the data - const int numHists = static_cast<int>(inputWS->getNumberHistograms()); - const int blocksize = static_cast<int>(inputWS->blocksize()); - - // Get the required X range - double startX,endX; - this->checkRange(startX,endX); - - std::vector<int> specInds = getProperty("WorkspaceIndexList"); - // check if the user passed an empty list, if so all of spec will be processed - this->getSpecInds(specInds, numHists); - - // Are we removing the background? - const bool removeBackground = - std::string(getProperty("outputMode")) == "Subtract Background"; - - // Initialise the progress reporting object - m_progress = new Progress(this,0.0,0.2,numHists); - - MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); - // If input and output workspaces are not the same, create a new workspace for the output - if (outputWS != inputWS ) - { - outputWS = WorkspaceFactory::Instance().create(inputWS); - PARALLEL_FOR2(inputWS,outputWS) - for (int i = 0; i < numHists; ++i) - { - PARALLEL_START_INTERUPT_REGION - outputWS->dataX(i) = inputWS->readX(i); - outputWS->dataY(i) = inputWS->readY(i); - outputWS->dataE(i) = inputWS->readE(i); - m_progress->report(); - PARALLEL_END_INTERUPT_REGION - } - PARALLEL_CHECK_INTERUPT_REGION - } - - convertToDistribution(outputWS); - - // these are used to report information to the user, one progress update for each percent and a report on the size of the background found - double prg(0.2), backgroundTotal(0); - const double toFitsize(static_cast<double>(specInds.size())); - const int progStep(static_cast<int>(ceil(toFitsize/80.0))); - - // Now loop over the required spectra - std::vector<int>::const_iterator specIt; - for (specIt = specInds.begin(); specIt != specInds.end(); ++specIt) - { - const int currentSpec = *specIt; - try - { - // Only if Mean() is called will variance be changed - double variance = -1; - - // Now call the function the user selected to calculate the background - const double background = std::string(getProperty("mode")) == "Mean" ? - this->Mean(outputWS, currentSpec, startX, endX, variance) : - this->LinearFit(outputWS, currentSpec, startX, endX); - - if (background < 0) - { - g_log.warning() << "Problem with calculating the background number of counts spectrum with index " - << currentSpec << ". The spectrum has been left unchanged.\n"; - g_log.debug() << "The background for spectra index " << currentSpec - << "was calculated to be " << background << std::endl; - continue; - } - else - {// only used for the logging that gets done at the end - backgroundTotal += background; - } - - MantidVec &E = outputWS->dataE(currentSpec); - // only the Mean() function calculates the variance - if ( variance > 0 ) - { - // adjust the errors using the variance (variance = error^2) - std::transform(E.begin(), E.end(), E.begin(), - std::bind2nd(VectorHelper::AddVariance<double>(), variance )); - } - // Get references to the current spectrum - MantidVec &Y = outputWS->dataY(currentSpec); - // Now subtract the background from the data - for (int j=0; j < blocksize; ++j) - { - if (removeBackground) - { - Y[j] -= background; - } - else - { - Y[j] = background; - } - //remove negative values - if (Y[j] < 0.0) - { - Y[j]=0; - // The error estimate must go up in this nonideal situation and the value of background is a good estimate for it. However, don't reduce the error if it was already more than that - E[j] = E[j]>background ? E[j] : background; - } - } - } - catch (std::exception &) - { - g_log.error() << "Error processing the spectrum with index " << currentSpec << std::endl; - throw; - } - - // make regular progress reports and check for cancelling the algorithm - if ( static_cast<int>( specInds.end()-specInds.begin() ) % progStep == 0 ) - { - interruption_point(); - prg+=(progStep*0.7/toFitsize); - progress(prg); - } - } // Loop over spectra to be fitted - - - g_log.debug() << toFitsize << " spectra corrected\n"; - if ( ! m_convertedFromRawCounts ) - { - g_log.information() << "The mean background over the spectra region was " << backgroundTotal/toFitsize << " per bin\n"; - } - else - { - g_log.information() << "Background corrected in uneven bin sized workspace\n"; - } - - restoreDistributionState(outputWS); - - - // Assign the output workspace to its property - setProperty("OutputWorkspace",outputWS); -} -/** Converts only if the workspace requires it: workspaces that are distributions or have constant width bins -* aren't affected. A flag is set if there was a change allowing the workspace to be converted back -* @param workspace the workspace to check and possibly convert -*/ -void FlatBackground::convertToDistribution(API::MatrixWorkspace_sptr workspace) -{ - if (workspace->isDistribution()) - { - return; - } - - bool variationFound(false); - // the number of spectra we need to check to assess if the bin widths are all the same - const size_t total = WorkspaceHelpers::commonBoundaries(workspace) ? - 1 : workspace->getNumberHistograms(); - - MantidVec adjacents(workspace->readX(0).size()-1); - for ( std::size_t i = 0; i < total; ++i) - { - MantidVec X = workspace->readX(i); - // Calculate bin widths - std::adjacent_difference(X.begin()+1, X.end(), adjacents.begin()); - // the first entry from adjacent difference is just a copy of the fisrt entry in the input vector, ignore this. The histogram validator for this algorithm ensures that X.size() > 1 - MantidVec widths( adjacents.begin()+1, adjacents.end() ); - if ( ! VectorHelper::isConstantValue(widths) ) - { - variationFound = true; - break; - } - } - - if (variationFound) - { - // after all the above checks the conclusion is we need the conversion - WorkspaceHelpers::makeDistribution(workspace, true); - m_convertedFromRawCounts = true; - } -} -/** Converts the workspace to a raw counts workspace if the flag m_convertedFromRawCounts -* is set -* @param workspace the workspace to, possibly, convert -*/ -void FlatBackground::restoreDistributionState(API::MatrixWorkspace_sptr workspace) -{ - if (m_convertedFromRawCounts) - { - WorkspaceHelpers::makeDistribution(workspace, false); - m_convertedFromRawCounts = false; - } -} -/** Checks that the range parameters have been set correctly - * @param startX :: The starting point - * @param endX :: The ending point - * @throw std::invalid_argument If XMin or XMax are not set, or XMax is less than XMin - */ -void FlatBackground::checkRange(double& startX, double& endX) -{ - //use the overloaded operator =() to get the X value stored in each property - startX = getProperty("StartX"); - endX = getProperty("EndX"); - - if (startX > endX) - { - const std::string failure("XMax must be greater than XMin."); - g_log.error(failure); - throw std::invalid_argument(failure); - } -} - -/** checks if the array is empty and if so fills it with all the index numbers -* in the workspace. Non-empty arrays are left untouched -* @param output :: the array to be checked -* @param workspaceTotal :: required to be the total number of spectra in the workspace -*/ -void FlatBackground::getSpecInds(std::vector<int> &output, const int workspaceTotal) -{ - if ( output.size() > 0 ) - { - return; - } - - output.resize(workspaceTotal); - for ( int i = 0; i < workspaceTotal; ++i ) - { - output[i] = i; - } -} -/** Gets the mean number of counts in each bin the background region and the variance (error^2) of that -* number -* @param WS :: points to the input workspace -* @param specInd :: index of the spectrum to process -* @param startX :: a X-value in the first bin that will be considered, must not be greater endX -* @param endX :: a X-value in the last bin that will be considered, must not less than startX -* @param variance :: will be set to the number of counts divided by the number of bins squared (= error^2) -* @return the mean number of counts in each bin the background region -* @throw out_of_range if either startX or endX are out of the range of X-values in the specified spectrum -* @throw invalid_argument if endX has the value of first X-value one of the spectra -*/ -double FlatBackground::Mean(const API::MatrixWorkspace_const_sptr WS, const int specInd, const double startX, const double endX, double &variance) const -{ - const MantidVec &XS = WS->readX(specInd), &YS = WS->readY(specInd); - const MantidVec &ES = WS->readE(specInd); - // the function checkRange should already have checked that startX <= endX, but we still need to check values weren't out side the ranges - if ( endX > XS.back() || startX < XS.front() ) - { - throw std::out_of_range("Either the property startX or endX is outside the range of X-values present in one of the specified spectra"); - } - // Get the index of the first bin contains the X-value, which means this is an inclusive sum. The minus one is because lower_bound() returns index past the last index pointing to a lower value. For example if startX has a higher X value than the first bin boundary but lower than the second lower_bound returns 1, which is the index of the second bin boundary - ptrdiff_t startInd = std::lower_bound(XS.begin(),XS.end(),startX) - XS.begin() - 1; - if ( startInd == -1 ) - {// happens if startX is the first X-value, e.g. the first X-value is zero and the user selects zero - startInd = 0; - } - - // the -1 matches definition of startIn, see the comment above that statement - const ptrdiff_t endInd = std::lower_bound(XS.begin()+startInd,XS.end(),endX) -XS.begin() -1; - if ( endInd == -1 ) - {// - throw std::invalid_argument("EndX was set to the start of one of the spectra, it must greater than the first X-value in any of the specified spectra"); - } - - // the +1 is because this is an inclusive sum (includes each bin that contains each X-value). Hence if startInd == endInd we are still analysising one bin - const double numBins = static_cast<double>(1 + endInd - startInd); - // the +1 here is because the accumulate() stops one before the location of the last iterator - double background = - std::accumulate( YS.begin()+startInd, YS.begin()+endInd+1, 0.0 )/numBins; - // The error on the total number of background counts in the background region is taken as the sqrt the total number counts. To get the the error on the counts in each bin just divide this by the number of bins. The variance = error^2 that is the total variance divide by the number of bins _squared_. - variance = - std::accumulate( ES.begin()+startInd, ES.begin()+endInd+1, 0.0, VectorHelper::SumSquares<double>())/(numBins*numBins); - // return mean number of counts in each bin, the sum of the number of counts in all the bins divided by the number of bins used in that sum - return background; -} -/// Calls Linear as a Child Algorithm to do the fitting -double FlatBackground::LinearFit(API::MatrixWorkspace_sptr WS, int spectrum, double startX, double endX) -{ - IAlgorithm_sptr childAlg = createChildAlgorithm("Linear"); - childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", WS); - childAlg->setProperty<int>("WorkspaceIndex",spectrum); - childAlg->setProperty<double>("StartX",startX); - childAlg->setProperty<double>("EndX",endX); - childAlg->executeAsChildAlg(); - - std::string fitStatus = childAlg->getProperty("FitStatus"); - if ( fitStatus != "success" ) - { - g_log.warning("Unable to successfully fit the data"); - return -1.0; - } - - // Calculate the value of the flat background by taking the value at the centre point of the fit - const double c = childAlg->getProperty("FitIntercept"); - const double m = childAlg->getProperty("FitSlope"); - const double centre = (startX+endX)/2.0; - const double background = m*centre + c; - - return background; -} - - -} // namespace Algorithms -} // namespace Mantid diff --git a/Code/Mantid/Framework/Algorithms/test/CheckWorkspacesMatchTest.h b/Code/Mantid/Framework/Algorithms/test/CheckWorkspacesMatchTest.h index 96bfc5ca2e201f5aad5663037cb3f46e0732ccb2..cc64c202e0ecbca74ccd244ddd90c4ab6624cac1 100644 --- a/Code/Mantid/Framework/Algorithms/test/CheckWorkspacesMatchTest.h +++ b/Code/Mantid/Framework/Algorithms/test/CheckWorkspacesMatchTest.h @@ -16,6 +16,7 @@ #include "MantidAPI/MatrixWorkspace.h" #include "MantidGeometry/Instrument.h" #include "MantidMDEvents/MDBoxBase.h" +#include "MantidKernel/V3D.h" using namespace Mantid::Algorithms; using namespace Mantid::API; @@ -764,18 +765,164 @@ public: cleanupGroup(groupTwo); } - void test_tableworkspaces() + void test_empty_tableworkspaces_match() { - Workspace_sptr table = WorkspaceFactory::Instance().createTable(); + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", WorkspaceFactory::Instance().createTable()) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", WorkspaceFactory::Instance().createTable()) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Success!" ); + } + + void test_tableworkspace_different_number_of_columns_fails() + { + auto table1 = WorkspaceFactory::Instance().createTable(); + auto table2 = WorkspaceFactory::Instance().createTable(); + table1->addColumns("int","aColumn",2); + table2->addColumns("int","aColumn",3); + + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Number of columns mismatch" ); + } + + void test_tableworkspace_different_number_of_rows_fails() + { + auto table1 = WorkspaceFactory::Instance().createTable(); + auto table2 = WorkspaceFactory::Instance().createTable(); + table1->addColumn("double","aColumn"); + table1->appendRow(); + table1->appendRow(); + table2->addColumn("double","aColumn"); + table2->appendRow(); + + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Number of rows mismatch" ); + } + + void test_tableworkspace_matches_itself() + { + auto table = setupTableWorkspace(); Mantid::Algorithms::CheckWorkspacesMatch alg; alg.initialize(); TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table) ); TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table) ); - TS_ASSERT( ! alg.execute() ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Success!" ); + } + + void test_tableworkspace_different_column_names_fails() + { + auto table1 = setupTableWorkspace(); + table1->getColumn(5)->setName("SomethingElse"); + auto table2 = setupTableWorkspace(); + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Column name mismatch" ); + } + + void test_tableworkspace_different_column_types_fails() + { + auto table1 = setupTableWorkspace(); + auto table2 = setupTableWorkspace(); + table2->removeColumn("V3D"); + table2->addColumn("int","V3D"); + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Column type mismatch" ); + } + + void test_tableworkspace_different_data_fails() + { + auto table1 = setupTableWorkspace(); + auto table2 = setupTableWorkspace(); + table2->cell<size_t>(1,3) = 123; + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Table data mismatch" ); + + table2 = setupTableWorkspace(); + table1->cell<std::string>(2,7) = "?"; + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Table data mismatch" ); + + table1 = setupTableWorkspace(); + table2->cell<Mantid::Kernel::V3D>(0,8) = Mantid::Kernel::V3D(9.9,8.8,7.7); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", table1) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", table2) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "Table data mismatch" ); + } + + void test_mixing_peaks_and_table_workspaces_fails() + { + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", WorkspaceFactory::Instance().createTable()) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", WorkspaceFactory::Instance().createPeaks()) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "One workspace is a PeaksWorkspace and the other is not." ); + } + + void test_mixing_matrix_and_table_workspaces_fails() + { + Mantid::Algorithms::CheckWorkspacesMatch alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace1", WorkspaceFactory::Instance().createTable()) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("Workspace2", WorkspaceFactory::Instance().create("Workspace2D",1,1,1)) ); + TS_ASSERT( alg.execute() ); + TS_ASSERT_EQUALS( alg.getPropertyValue("Result"), "One workspace is a TableWorkspace and the other is not." ); } private: + ITableWorkspace_sptr setupTableWorkspace() + { + auto table = WorkspaceFactory::Instance().createTable(); + // One column of each type + table->addColumn("int","int"); + table->addColumn("int32_t","int32"); + table->addColumn("long64","int64"); + table->addColumn("size_t","uint"); + table->addColumn("float","float"); + table->addColumn("double","double"); + table->addColumn("bool","bool"); + table->addColumn("str","string"); + table->addColumn("V3D","V3D"); + + // A few rows + TableRow row1 = table->appendRow(); + row1 << -1 << static_cast<int32_t>(0) << static_cast<int64_t>(1) << static_cast<size_t>(10) + << 5.5f << -9.9 << true << "Hello" << Mantid::Kernel::V3D(); + TableRow row2 = table->appendRow(); + row2 << 1 << static_cast<int32_t>(-2) << static_cast<int64_t>(-2) << static_cast<size_t>(100) + << 0.0f << 101.0 << false << "World" << Mantid::Kernel::V3D(-1,3,4); + TableRow row3 = table->appendRow(); + row3 << 6 << static_cast<int32_t>(3) << static_cast<int64_t>(0) << static_cast<size_t>(0) + << -99.0f << 0.0 << false << "!" << Mantid::Kernel::V3D(1,6,10); + + return table; + } + void doGroupTest(const std::string & inputWSOne, const std::string & inputWSTwo, const std::string & expectedResult, const std::map<std::string,std::string> & otherProps = std::map<std::string,std::string>(), diff --git a/Code/Mantid/Framework/Algorithms/test/CopySampleTest.h b/Code/Mantid/Framework/Algorithms/test/CopySampleTest.h index d289e67a25eff10eb0e2c991b95ae8755e245ab4..3732f6e47d1e909e379db0f941977e9751a7e462 100644 --- a/Code/Mantid/Framework/Algorithms/test/CopySampleTest.h +++ b/Code/Mantid/Framework/Algorithms/test/CopySampleTest.h @@ -170,6 +170,69 @@ public: AnalysisDataService::Instance().remove(inWSName); AnalysisDataService::Instance().remove(outWSName); } + + + void test_orientation() + { + WorkspaceSingleValue_sptr ws1(new WorkspaceSingleValue(1,1)); + WorkspaceSingleValue_sptr ws2(new WorkspaceSingleValue(4,2)); + Sample s=createsample(); + ws1->mutableSample()=s; + + // Name of the output workspace. + std::string inWSName("CopySampleTest_InputWS"); + std::string outWSName("CopySampleTest_OutputWS"); + AnalysisDataService::Instance().add(inWSName, ws1); + AnalysisDataService::Instance().add(outWSName, ws2); + + CopySample alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("InputWorkspace", inWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyName", "0") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyMaterial", "0") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyEnvironment", "0") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyShape", "0") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyLattice", "1") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("CopyOrientationOnly", "1") ); + + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + + // Retrieve the workspace from data service. + MatrixWorkspace_sptr ws; + TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName) ); + TS_ASSERT(ws); + if (!ws) return; + + // Check the results + Sample copy=ws->mutableSample(); + TS_ASSERT(copy.hasOrientedLattice()); + TS_ASSERT_EQUALS(copy.getOrientedLattice().getUB(), s.getOrientedLattice().getUB()); + + //modify the first unit cell, both U and B + s.getOrientedLattice().setUFromVectors(V3D(1,1,0),V3D(1,-1,0)); + s.getOrientedLattice().seta(1.1); + ws1->mutableSample()=s; + TS_ASSERT_THROWS_NOTHING( alg.execute(); ); + TS_ASSERT( alg.isExecuted() ); + // Retrieve the workspace from data service. + TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName) ); + TS_ASSERT(ws); + if (!ws) return; + + // Check the results + copy=ws->mutableSample(); + TS_ASSERT(copy.hasOrientedLattice()); + TS_ASSERT_DIFFERS(copy.getOrientedLattice().a(), s.getOrientedLattice().a()); //different B matrix + TS_ASSERT_EQUALS(copy.getOrientedLattice().getU(), s.getOrientedLattice().getU());//same U + // Remove workspace from the data service. + AnalysisDataService::Instance().remove(inWSName); + AnalysisDataService::Instance().remove(outWSName); + } + + void test_MDcopy() { IMDEventWorkspace_sptr ew(new MDEventWorkspace<MDEvent<3>, 3>()); diff --git a/Code/Mantid/Framework/Algorithms/test/FlatBackgroundTest.h b/Code/Mantid/Framework/Algorithms/test/FlatBackgroundTest.h deleted file mode 100644 index b00402c4153167e01adc035792c3f627ebcfa003..0000000000000000000000000000000000000000 --- a/Code/Mantid/Framework/Algorithms/test/FlatBackgroundTest.h +++ /dev/null @@ -1,264 +0,0 @@ -#ifndef FLATBACKGROUNDTEST_H_ -#define FLATBACKGROUNDTEST_H_ - -#include <cxxtest/TestSuite.h> -#include "MantidAlgorithms/FlatBackground.h" -#include "MantidDataObjects/Workspace2D.h" -#include "MantidCurveFitting/Linear.h" -#include "MantidKernel/MersenneTwister.h" -#include "MantidAPI/FrameworkManager.h" -#include <boost/lexical_cast.hpp> -#include <cmath> - -using namespace Mantid::API; -using namespace Mantid::Kernel; - -static const int NUMBINS = 31; -static const int NUMSPECS = 4; - -class FlatBackgroundTest : public CxxTest::TestSuite -{ -public: - static FlatBackgroundTest *createSuite() { return new FlatBackgroundTest(); } - static void destroySuite(FlatBackgroundTest *suite) { delete suite; } - - FlatBackgroundTest() - { - FrameworkManager::Instance(); - - bg = 100.0; - Mantid::DataObjects::Workspace2D_sptr WS(new Mantid::DataObjects::Workspace2D); - WS->initialize(1,NUMBINS+1,NUMBINS); - const size_t seed(12345); - const double lower(-1.0), upper(1.0); - MersenneTwister randGen(seed, lower, upper); - - for (int i = 0; i < NUMBINS; ++i) - { - WS->dataX(0)[i] = i; - WS->dataY(0)[i] = bg + randGen.nextValue(); - WS->dataE(0)[i] = 0.05*WS->dataY(0)[i]; - } - WS->dataX(0)[NUMBINS] = NUMBINS; - - AnalysisDataService::Instance().add("flatBG",WS); - - //create another test wrokspace - Mantid::DataObjects::Workspace2D_sptr WS2D(new Mantid::DataObjects::Workspace2D); - WS2D->initialize(NUMSPECS,NUMBINS+1,NUMBINS); - - for (int j = 0; j < NUMSPECS; ++j) - { - for (int i = 0; i < NUMBINS; ++i) - { - WS2D->dataX(j)[i] = i; - // any function that means the calculation is non-trival - WS2D->dataY(j)[i] = j+4*(i+1)-(i*i)/10; - WS2D->dataE(j)[i] = 2*i; - } - WS2D->dataX(j)[NUMBINS] = NUMBINS; - } - - AnalysisDataService::Instance().add("flatbackgroundtest_ramp",WS2D); - } - - ~FlatBackgroundTest() - { - AnalysisDataService::Instance().remove("flatbackgroundtest_ramp"); - } - - void testStatics() - { - Mantid::Algorithms::FlatBackground flatBG; - TS_ASSERT_EQUALS( flatBG.name(), "FlatBackground" ) - TS_ASSERT_EQUALS( flatBG.version(), 1 ) - } - - void testExec() - { - Mantid::Algorithms::FlatBackground flatBG; - TS_ASSERT_THROWS_NOTHING( flatBG.initialize() ) - TS_ASSERT( flatBG.isInitialized() ) - - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("InputWorkspace","flatBG") ) - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("OutputWorkspace","Removed") ) - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("WorkspaceIndexList","0") ) - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("StartX","9.5") ) - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("EndX","20.5") ) - TS_ASSERT_THROWS_NOTHING( flatBG.setPropertyValue("Mode","Linear Fit") ) - - TS_ASSERT_THROWS_NOTHING( flatBG.execute() ) - TS_ASSERT( flatBG.isExecuted() ) - - MatrixWorkspace_sptr inputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatBG"); - MatrixWorkspace_sptr outputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("Removed"); - // The X vectors should be the same - TS_ASSERT_EQUALS( inputWS->readX(0), outputWS->readX(0) ) - // Just do a spot-check on Y & E - const Mantid::MantidVec &Y = outputWS->readY(0); - for (unsigned int i=0; i<Y.size(); ++i) - { - TS_ASSERT_LESS_THAN( Y[i], 1.5 ) - } - } - - void testMeanFirst() - { - Mantid::Algorithms::FlatBackground back; - TS_ASSERT_THROWS_NOTHING( back.initialize() ) - TS_ASSERT( back.isInitialized() ) - - back.setPropertyValue("InputWorkspace","flatbackgroundtest_ramp"); - back.setPropertyValue("OutputWorkspace","flatbackgroundtest_first"); - back.setPropertyValue("WorkspaceIndexList",""); - back.setPropertyValue("Mode","Mean"); - // remove the first half of the spectrum - back.setPropertyValue("StartX","0"); - back.setPropertyValue("EndX","15"); - - TS_ASSERT_THROWS_NOTHING( back.execute() ) - TS_ASSERT( back.isExecuted() ) - - MatrixWorkspace_sptr inputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatbackgroundtest_ramp"); - MatrixWorkspace_sptr outputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatbackgroundtest_first"); - // The X vectors should be the same - TS_ASSERT_EQUALS( inputWS->readX(0), outputWS->readX(0) ) - - for (int j = 0; j < NUMSPECS; ++j) - { - const Mantid::MantidVec &YIn = inputWS->readY(j); - const Mantid::MantidVec &EIn = inputWS->readE(j); - const Mantid::MantidVec &YOut = outputWS->readY(j); - const Mantid::MantidVec &EOut = outputWS->readE(j); - // do our own calculation of the background and its error to check with later - double background = 0, backError = 0; - for( int k = 0; k < 15; ++k) - { - background += YIn[k]; - backError += EIn[k]*EIn[k]; - } - background /= 15.0; - backError = std::sqrt(backError)/15.0; - for (int i = 0; i < NUMBINS; ++i) - { - double correct = ( YIn[i] - background ) > 0 ? YIn[i]-background : 0; - TS_ASSERT_EQUALS( YOut[i], correct ) - - if ( YIn[i] - background < 0 ) - { - TS_ASSERT_EQUALS(EOut[i], background) - } - else - { - TS_ASSERT_EQUALS(EOut[i], std::sqrt((EIn[i]*EIn[i])+(backError*backError)) ) - } - } - } - } - - void testMeanSecond() - { - Mantid::Algorithms::FlatBackground back; - TS_ASSERT_THROWS_NOTHING( back.initialize() ) - TS_ASSERT( back.isInitialized() ) - - back.setPropertyValue("InputWorkspace","flatbackgroundtest_ramp"); - back.setPropertyValue("OutputWorkspace","flatbackgroundtest_second"); - back.setPropertyValue("WorkspaceIndexList",""); - back.setPropertyValue("Mode","Mean"); - // remove the last half of the spectrum - back.setProperty("StartX", 2*double(NUMBINS)/3); - back.setProperty("EndX", double(NUMBINS)); - - TS_ASSERT_THROWS_NOTHING( back.execute() ) - TS_ASSERT( back.isExecuted() ) - - MatrixWorkspace_sptr inputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatbackgroundtest_ramp"); - MatrixWorkspace_sptr outputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatbackgroundtest_second"); - // The X vectors should be the same - TS_ASSERT_EQUALS( inputWS->readX(0), outputWS->readX(0) ) - - for (int j = 0; j < NUMSPECS; ++j) - { - const Mantid::MantidVec &YIn = inputWS->readY(j); - const Mantid::MantidVec &EIn = inputWS->readE(j); - const Mantid::MantidVec &YOut = outputWS->readY(j); - const Mantid::MantidVec &EOut = outputWS->readE(j); - // do our own calculation of the background and its error to check with later - double background = 0, backError = 0, numSummed = 0; - // 2*NUMBINS/3 makes use of the truncation of integer division - for( int k = 2*NUMBINS/3; k < NUMBINS; ++k) - { - background += YIn[k]; - backError += EIn[k]*EIn[k]; - numSummed++; - } - background /= numSummed ; - backError = std::sqrt(backError)/numSummed ; - for (int i = 0; i < NUMBINS; ++i) - { - double correct = ( YIn[i] - background ) > 0 ? YIn[i]-background : 0; - TS_ASSERT_EQUALS( YOut[i], correct ) - - if ( YIn[i] - background < 0 && EIn[i] < background ) - { - TS_ASSERT_EQUALS(EOut[i], background) - } - else - { - TS_ASSERT_EQUALS(EOut[i], std::sqrt((EIn[i]*EIn[i])+(backError*backError)) ) - } - } - } - } - - void testVariedWidths() - { - const double YVALUE = 100.0; - Mantid::DataObjects::Workspace2D_sptr WS(new Mantid::DataObjects::Workspace2D); - WS->initialize(1,NUMBINS+1,NUMBINS); - - for (int i = 0; i < NUMBINS; ++i) - { - WS->dataX(0)[i] = 2*i; - WS->dataY(0)[i] = YVALUE; - WS->dataE(0)[i] = YVALUE/3.0; - } - WS->dataX(0)[NUMBINS] = 2*(NUMBINS-1)+4.0; - - - Mantid::Algorithms::FlatBackground back; - back.initialize(); - - back.setProperty("InputWorkspace", boost::static_pointer_cast<Mantid::API::MatrixWorkspace>(WS)); - back.setPropertyValue("OutputWorkspace","flatbackgroundtest_third"); - back.setPropertyValue("WorkspaceIndexList",""); - back.setPropertyValue("Mode","Mean"); - // sample the background from the last (wider) bin only - back.setProperty("StartX", 2.0*NUMBINS+1); - back.setProperty("EndX", 2.0*(NUMBINS+1)); - - back.execute(); - TS_ASSERT( back.isExecuted() ) - - MatrixWorkspace_sptr outputWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("flatbackgroundtest_third"); - // The X vectors should be the same - TS_ASSERT_EQUALS( WS->readX(0), outputWS->readX(0) ) - - const Mantid::MantidVec &YOut = outputWS->readY(0); - const Mantid::MantidVec &EOut = outputWS->readE(0); - - TS_ASSERT_EQUALS( YOut[5], 50.0 ) - TS_ASSERT_EQUALS( YOut[25], 50.0 ) - TS_ASSERT_EQUALS( YOut[NUMBINS-1], 0.0 ) - - TS_ASSERT_DELTA( EOut[10], 37.2677, 0.001 ) - TS_ASSERT_DELTA( EOut[20], 37.2677, 0.001 ) - } - - -private: - double bg; -}; - -#endif /*FlatBackgroundTest_H_*/ diff --git a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp index 191b361b226d7968a9e1e908ab2f6d3a08fe0b78..a1a880f77c931b0f4c0f8ff720ff297d315acabe 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp @@ -198,6 +198,12 @@ namespace Crystal double rho = sampleMaterial.numberDensity(); if (smu == EMPTY_DBL()) smu = sampleMaterial.totalScatterXSection(NeutronAtom::ReferenceLambda) * rho; if (amu == EMPTY_DBL()) amu = sampleMaterial.absorbXSection(NeutronAtom::ReferenceLambda) * rho; + g_log.notice() << "Sample number density = " << rho << " atoms/Angstrom^3\n"; + g_log.notice() << "Cross sections for wavelength = " << NeutronAtom::ReferenceLambda << "Angstroms\n" + << " Coherent = " << sampleMaterial.cohScatterXSection() << " barns\n" + << " Incoherent = " << sampleMaterial.incohScatterXSection() << " barns\n" + << " Total = " << sampleMaterial.totalScatterXSection() << " barns\n" + << " Absorption = " << sampleMaterial.absorbXSection() << " barns\n"; } else //Save input in Sample with wrong atomic number and name { @@ -206,6 +212,10 @@ namespace Crystal Material mat("SetInAnvredCorrection", neutron, 1.0); ws->mutableSample().setMaterial(mat); } + g_log.notice() << "LinearScatteringCoef = " << smu << " 1/cm\n" + << "LinearAbsorptionCoef = " << amu << " 1/cm\n" + << "Radius = " << radius << " cm\n" + << "Power Lorentz corrections = " << power_th << " \n"; API::Run & run = ws->mutableRun(); if ( run.hasProperty("Radius") ) { diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 569fe596729eded9b9316a235d333908ab1935b1..67ef1cd2f029573e244ab61589790f77c92f98eb 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -1,6 +1,7 @@ set ( SRC_FILES src/AppendGeometryToSNSNexus.cpp src/CompressEvents.cpp + src/ConvertFullprofToXML.cpp src/CreateChopperModel.cpp src/CreateModeratorModel.cpp src/CreateSampleShape.cpp @@ -134,6 +135,7 @@ set ( SRC_FILES set ( INC_FILES inc/MantidDataHandling/AppendGeometryToSNSNexus.h inc/MantidDataHandling/CompressEvents.h + inc/MantidDataHandling/ConvertFullprofToXML.h inc/MantidDataHandling/CreateChopperModel.h inc/MantidDataHandling/CreateModeratorModel.h inc/MantidDataHandling/CreateSampleShape.h @@ -268,6 +270,7 @@ set ( TEST_FILES #LoadSNSNexusTest.h # TODO has no active tests in it AppendGeometryToSNSNexusTest.h CompressEventsTest.h + ConvertFullprofToXMLTest.h CreateChopperModelTest.h CreateModeratorModelTest.h CreateSampleShapeTest.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ConvertFullprofToXML.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ConvertFullprofToXML.h new file mode 100644 index 0000000000000000000000000000000000000000..34c4223c17516d19ce0e5da1feaad91c6eb45be9 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/ConvertFullprofToXML.h @@ -0,0 +1,89 @@ +#ifndef MANTID_DATAHANDLING_CONVERTFULLPROFTOXML_H_ +#define MANTID_DATAHANDLING_CONVERTFULLPROFTOXML_H_ + +#include "MantidAPI/Algorithm.h" +#include "MantidAPI/ITableWorkspace.h" + +#include <Poco/DOM/Element.h> + +namespace Mantid +{ +namespace DataHandling +{ + + /** ConvertFullprofToXML : Convert a fullprof resolution file to an instrument parameter file + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <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 ConvertFullprofToXML : public API::Algorithm + { + public: + ConvertFullprofToXML(); + virtual ~ConvertFullprofToXML(); + + /// Algorithm's name for identification overriding a virtual method + virtual const std::string name() const { return "ConvertFullprofToXML";} + + /// Algorithm's version for identification overriding a virtual method + virtual int version() const { return 1;} + + /// Algorithm's category for identification overriding a virtual method + virtual const std::string category() const { return "Diffraction";} + + private: + /// Sets documentation strings for this algorithm + virtual void initDocs(); + /// Implement abstract Algorithm methods + void init(); + /// Implement abstract Algorithm methods + void exec(); + + /// Load file to a vector of strings + void loadFile(std::string filename, std::vector<std::string>& lines); + + /// Add an ALFBE parameter + void addALFBEParameter(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent, const std::string& paramName); + + /// Add set of Sigma parameters + void addSigmaParameters(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent ); + + /// Add set of Gamma parameters + void addGammaParameters(const API::Column_const_sptr, Poco::XML::Document* mDoc, Poco::XML::Element* parent ); + + /// Get value for XML eq attribute for parameter + std::string getXMLEqValue( const API::Column_const_sptr, const std::string& name ); + + // Translate a parameter name from as it appears in the table workspace to its name in the XML file + std::string getXMLParameterName( const std::string& name ); + + /// Get row numbers of the parameters in the table workspace + void getTableRowNumbers(const API::ITableWorkspace_sptr & tablews, std::map<std::string, size_t>& parammap); + + /// Place to store the row numbers + std::map<std::string, size_t> m_rowNumbers; + + }; + + +} // namespace DataHandling +} // namespace Mantid + +#endif /* MANTID_DATAHANDLING_CONVERTFULLPROFTOXML_H_ */ diff --git a/Code/Mantid/Framework/DataHandling/src/ConvertFullprofToXML.cpp b/Code/Mantid/Framework/DataHandling/src/ConvertFullprofToXML.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d4d44e35591c811463ab34e21e043d4b8ba586b --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/src/ConvertFullprofToXML.cpp @@ -0,0 +1,319 @@ +/*WIKI* + +Convert the initial fitting parameters in a Fullprof file to XML format in an [[InstrumentParameterFile]]. + +*WIKI*/ +#include "MantidDataHandling/ConvertFullprofToXML.h" +#include "MantidDataHandling/LoadFullprofResolution.h" +#include "MantidKernel/MandatoryValidator.h" +#include "MantidAPI/FileProperty.h" +#include "MantidAPI/TableRow.h" + +#include <fstream> + +// Needed for writing the XML file (will be moved to a child algorithm) +#include <Poco/DOM/Document.h> +#include <Poco/DOM/DOMWriter.h> +#include <Poco/DOM/Element.h> +#include <Poco/DOM/AutoPtr.h> + +#include <boost/lexical_cast.hpp> + + +namespace Mantid +{ +namespace DataHandling +{ + using namespace API; + using namespace Kernel; + using namespace Poco::XML; + + DECLARE_ALGORITHM(ConvertFullprofToXML) + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + ConvertFullprofToXML::ConvertFullprofToXML() + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + ConvertFullprofToXML::~ConvertFullprofToXML() + { + } + + //---------------------------------------------------------------------------------------------- + /** Sets documentation strings for this algorithm + */ + void ConvertFullprofToXML::initDocs() + { + setWikiSummary("Convert the initial fitting parameters in a Fullprof file to XML format in an Instrument Parameter File"); + setOptionalMessage("Convert the initial fitting parameters in a Fullprof file to XML format in an Instrument Parameter File"); + + return; + } + + //---------------------------------------------------------------------------------------------- + /** Implement abstract Algorithm methods + */ + void ConvertFullprofToXML::init() + { + // Input file name + std::vector<std::string> exts; + exts.push_back(".irf"); + exts.push_back(".prf"); + declareProperty(new FileProperty("InputFilename", "", FileProperty::Load, exts), + "Path to an Fullprof file to load."); + + // Instrument name + declareProperty("InstrumentName", "",boost::make_shared<MandatoryValidator<std::string>>(), "Name of instrument for the input file" ); + + // Output file + std::vector<std::string> extso; + extso.push_back(".xml"); + declareProperty(new FileProperty("OutputFilename", "", FileProperty::Save, extso), + "The name to give to the parameter file."); + + return; + } + + //---------------------------------------------------------------------------------------------- + /** Implement abstract Algorithm methods + */ + void ConvertFullprofToXML::exec() + { + // Get input + std::string datafile = getProperty("InputFilename"); + + // Get instrument + std::string instrumentName = getProperty("InstrumentName"); + + // Get Output + std::string paramfile = getProperty("OutputFilename"); + + + // We need the instrument name because it is not extracted by LoadFullprofResolution and is + // needed by fitting despite also being available in the IDF. + if ( instrumentName.empty() ) + throw std::runtime_error("The InstrumentName property must be set."); + + // Load with LoadFullprofResolution + auto loader = createChildAlgorithm("LoadFullprofResolution"); + loader->setProperty("Filename",datafile); + loader->executeAsChildAlg(); + + // Write into Parameter File + // This code will later go into a child algorithm to enable it to be used by other algorithms + + // Set up access to table workspace ParamTable + API::ITableWorkspace_sptr paramTable = loader->getProperty("OutputWorkspace"); + // get the table workspace row numbers of the parameters and store them for later use + getTableRowNumbers( paramTable, m_rowNumbers); + + // Set up access to Output file + std::ofstream outFile(paramfile.c_str()); + if (!outFile) + { + throw Mantid::Kernel::Exception::FileError("Unable to open file:", paramfile); + } + + // Set up writer to Paremeter file + DOMWriter writer; + writer.setNewLine("\n"); + writer.setOptions(XMLWriter::PRETTY_PRINT); + + // Get current time + Kernel::DateAndTime date = Kernel::DateAndTime::getCurrentTime(); + std::string ISOdate = date.toISO8601String(); + std::string ISOdateShort = ISOdate.substr(0,19); // Remove fraction of seconds + + // Create document + AutoPtr<Document> mDoc = new Document(); + AutoPtr<Element> rootElem = mDoc->createElement("parameter-file"); + rootElem->setAttribute("date", ISOdateShort); + mDoc->appendChild(rootElem); + + // Add instrument + AutoPtr<Element> instrumentElem = mDoc->createElement("component-link"); + instrumentElem->setAttribute("name",instrumentName); + rootElem->appendChild(instrumentElem); + API::Column_const_sptr column1 = paramTable->getColumn( 1 ); + addALFBEParameter( column1, mDoc, instrumentElem, "Alph0"); + addALFBEParameter( column1, mDoc, instrumentElem, "Beta0"); + addALFBEParameter( column1, mDoc, instrumentElem, "Alph1"); + addALFBEParameter( column1, mDoc, instrumentElem, "Beta1"); + + // Add banks + if(paramTable->columnCount() < 2){ + throw std::runtime_error("No banks found"); + } + size_t num_banks = paramTable->columnCount()-1; + + for( size_t i=0; i<num_banks; ++i) + { + API::Column_const_sptr column = paramTable->getColumn( i+1 ); + const double bankNumber = column->cell<double>(0); + std::ostringstream bankName; + bankName << "bank" << bankNumber; + AutoPtr<Element> bankElem = mDoc->createElement("component-link"); + bankElem->setAttribute("name",bankName.str()); + addSigmaParameters( column, mDoc, bankElem ); + addGammaParameters( column, mDoc, bankElem ); + rootElem->appendChild(bankElem); + } + + + // Write document structure into file + writer.writeNode(outFile, mDoc); + + return; + } + + /* Add an ALFBE parameter to the XML document according to the table workspace + * + * paramName is the name of the parameter as it appears in the table workspace + */ + void ConvertFullprofToXML::addALFBEParameter(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Element* parent, const std::string& paramName) + { + AutoPtr<Element> parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", getXMLParameterName(paramName)); + parameterElem->setAttribute("type","fitting"); + + AutoPtr<Element> formulaElem = mDoc->createElement("formula"); + formulaElem->setAttribute("eq",getXMLEqValue(column, paramName)); + if(paramName != "Beta1") formulaElem->setAttribute("result-unit","TOF"); + parameterElem->appendChild(formulaElem); + + AutoPtr<Element> fixedElem = mDoc->createElement("fixed"); + parameterElem->appendChild(fixedElem); + + parent->appendChild(parameterElem); + } + + /* Add a set of SIGMA paraters to the XML document according to the table workspace + * for the bank at the given column of the table workspace + */ + void ConvertFullprofToXML::addSigmaParameters(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Poco::XML::Element* parent ) + { + AutoPtr<Element> parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", "IkedaCarpenterPV:SigmaSquared"); + parameterElem->setAttribute("type","fitting"); + + AutoPtr<Element> formulaElem = mDoc->createElement("formula"); + std::string eqValue = getXMLEqValue(column, "Sig1")+"*centre^2+"+getXMLEqValue(column, "Sig0"); + formulaElem->setAttribute("eq", eqValue); + formulaElem->setAttribute("unit","dSpacing"); + formulaElem->setAttribute("result-unit","TOF^2"); + parameterElem->appendChild(formulaElem); + + parent->appendChild(parameterElem); + } + + /* Add a set of GAMMA paraters to the XML document according to the table workspace + * for the bank at the given column of the table workspace + */ + void ConvertFullprofToXML::addGammaParameters(const API::Column_const_sptr column, Poco::XML::Document* mDoc, Poco::XML::Element* parent ) + { + AutoPtr<Element> parameterElem = mDoc->createElement("parameter"); + parameterElem->setAttribute("name", "IkedaCarpenterPV:Gamma"); + parameterElem->setAttribute("type","fitting"); + + AutoPtr<Element> formulaElem = mDoc->createElement("formula"); + std::string eqValue = getXMLEqValue(column, "Gam1" )+"*centre"; + formulaElem->setAttribute("eq", eqValue); + formulaElem->setAttribute("unit","dSpacing"); + formulaElem->setAttribute("result-unit","TOF"); + parameterElem->appendChild(formulaElem); + + parent->appendChild(parameterElem); + } + + + + /* + * Get the XML name of a parameter given its Table Workspace name + */ + std::string ConvertFullprofToXML::getXMLParameterName( const std::string& name ) + { + // Only used for ALFBE parameters + std::string prefix = "IkedaCarpenterPV:"; + if(name == "Alph0") return prefix+"Alpha0"; + if(name == "Beta0") return prefix+"Beta0"; + if(name == "Alph1") return prefix+"Alpha1"; + if(name == "Beta1") return prefix+"Kappa"; + return "?"+name; + } + + /* + * Get the value string to put in the XML eq attribute of the formula element of the paramenter element + * given the name of the parameter in the table workspace. + */ + std::string ConvertFullprofToXML::getXMLEqValue( const API::Column_const_sptr column, const std::string& name ) + { + size_t paramNumber = m_rowNumbers[name]; + //API::Column_const_sptr column = tablews->getColumn( columnIndex ); + double eqValue = column->cell<double>(paramNumber); + if(name.substr(0,3) == "Sig") eqValue = eqValue*eqValue; // Square the sigma values + return boost::lexical_cast<std::string>(eqValue); + } + + /* This function fills in a list of the row numbers starting 0 of the parameters + in the table workspace, so one can find the position in a column of + the value of the given parameter. + */ + void ConvertFullprofToXML::getTableRowNumbers(const API::ITableWorkspace_sptr & tablews, std::map<std::string, size_t>& parammap) + { + parammap.clear(); + + size_t numrows = tablews->rowCount(); + for (size_t i = 0; i < numrows; ++i) + { + TableRow row = tablews->getRow(i); + std::string name; + row >> name; + parammap.insert(std::make_pair(name, i)); + } + + return; + } + +} // namespace DataHandling +} // namespace Mantid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp index a95bcb97b847690f2eb7255bc7fe65b3547ab5ad..be495a0e6709058c6d8d8b38935e948ff7de2818 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadFullprofResolution.cpp @@ -74,7 +74,7 @@ namespace DataHandling "Path to an Fullprof .irf file to load."); // Output workspace - auto wsprop = new WorkspaceProperty<TableWorkspace>("OutputWorkspace", "", Direction::Output); + auto wsprop = new WorkspaceProperty<API::ITableWorkspace>("OutputWorkspace", "", Direction::Output); declareProperty(wsprop, "Name of the output TableWorkspace containing profile parameters or bank information. "); // Bank to import @@ -171,7 +171,7 @@ namespace DataHandling } // Generate output table workspace - TableWorkspace_sptr outws = genTableWorkspace(bankparammap); + API::ITableWorkspace_sptr outws = genTableWorkspace(bankparammap); // 6. Output setProperty("OutputWorkspace", outws); @@ -296,12 +296,20 @@ namespace DataHandling double cwl; int tmpbankid; parseBankLine(bankline, cwl, tmpbankid); - g_log.debug() << "Found CWL = " << cwl << ", Bank ID = " << tmpbankid << "\n"; + if(tmpbankid != -1) + { + g_log.debug() << "Found CWL = " << cwl << ", Bank ID = " << tmpbankid << "\n"; + } + else + { + g_log.warning() << "No CWL found for bank " << bankid; + tmpbankid = bankid; + } if (bankid != tmpbankid) { stringstream errss; errss << "Input bank ID (" << bankid << ") is not same as the bank ID (" << tmpbankid - << ") found in the specified region from input. "; + << ") found in the specified region from input. "; throw runtime_error(errss.str()); } parammap["CWL"] = cwl; @@ -542,6 +550,11 @@ namespace DataHandling tempdb = atof(terms[4].c_str()); parammap["Beta1t"] = tempdb; } + } // "ALFBT" + else if (boost::starts_with(line,"END")) + { + // Ignore END line + g_log.debug() << "END line of bank"; } else { diff --git a/Code/Mantid/Framework/DataHandling/src/LoadISISNexus2.cpp b/Code/Mantid/Framework/DataHandling/src/LoadISISNexus2.cpp index 6a9b4aef99d75deeb34bc8245558b2cf427b6f57..847564735b807979f059bc1dc1dac03132d399a6 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadISISNexus2.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadISISNexus2.cpp @@ -202,8 +202,8 @@ namespace Mantid } catch(std::exception & ) { // No valid instrument and sample section found parameterString="not found"; } + local_workspace->updateSpectraUsing(SpectrumDetectorMapping(spec(),udet(),udet.dim0())); if( parameterString == "not found") { - local_workspace->updateSpectraUsing(SpectrumDetectorMapping(spec(),udet(),udet.dim0())); runLoadInstrument(local_workspace); } else { // Use parameters got from instrument section of Nexus file local_workspace->readParameterMap(parameterString); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp index c3d998adc9afb126df4df6705c3945e64adba5cf..f79f227b0f30b9afd130038f7203d31a7ccf70f8 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadInstrument.cpp @@ -148,15 +148,17 @@ namespace Mantid } } - if (!m_filename.empty()) + if ( m_filename.empty() ) { - // Remove the path from the filename for use with the InstrumentDataService - const std::string::size_type stripPath = m_filename.find_last_of("\\/"); - std::string instrumentFile = m_filename.substr(stripPath+1,m_filename.size()); - // Strip off "_Definition.xml" - m_instName = instrumentFile.substr(0,instrumentFile.find("_Def")); + throw Exception::NotFoundError("Unable to find an Instrument Definition File for",m_instName); } + // Remove the path from the filename for use with the InstrumentDataService + const std::string::size_type stripPath = m_filename.find_last_of("\\/"); + std::string instrumentFile = m_filename.substr(stripPath+1,m_filename.size()); + // Strip off "_Definition.xml" + m_instName = instrumentFile.substr(0,instrumentFile.find("_Def")); + // Initialize the parser with the the XML text loaded from the IDF file parser.initialize(m_filename, m_instName, Strings::loadFile(m_filename)); } @@ -168,8 +170,8 @@ namespace Mantid // Check whether the instrument is already in the InstrumentDataService if ( InstrumentDataService::Instance().doesExist(instrumentNameMangled) ) { - // If it does, just use the one from the one stored there - instrument = InstrumentDataService::Instance().retrieve(instrumentNameMangled); + // If it does, just use the one from the one stored there + instrument = InstrumentDataService::Instance().retrieve(instrumentNameMangled); } else { diff --git a/Code/Mantid/Framework/DataHandling/test/ConvertFullprofToXMLTest.h b/Code/Mantid/Framework/DataHandling/test/ConvertFullprofToXMLTest.h new file mode 100644 index 0000000000000000000000000000000000000000..7f5c09811d85d6bd4d6e8ebf0337d8e022c038b4 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/test/ConvertFullprofToXMLTest.h @@ -0,0 +1,357 @@ +#ifndef MANTID_DATAHANDLING_CONVERTFULLPROFTOXMLTEST_H_ +#define MANTID_DATAHANDLING_CONVERTFULLPROFTOXMLTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidDataHandling/ConvertFullprofToXML.h" +#include <fstream> +#include <Poco/File.h> + +#include <Poco/DOM/Document.h> +#include <Poco/DOM/DOMParser.h> +#include <Poco/DOM/Element.h> +#include <Poco/DOM/NodeList.h> +#include <Poco/DOM/AutoPtr.h> + +using Mantid::DataHandling::ConvertFullprofToXML; + +using namespace Mantid; +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace Poco::XML; + +using namespace std; + +class ConvertFullprofToXMLTest : public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static ConvertFullprofToXMLTest *createSuite() { return new ConvertFullprofToXMLTest(); } + static void destroySuite( ConvertFullprofToXMLTest *suite ) { delete suite; } + + //---------------------------------------------------------------------------------------------- + /** Test conversion + */ + void testInit() + { + + // Init LoadFullprofResolution + ConvertFullprofToXML alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + + return; + } + + //---------------------------------------------------------------------------------------------- + /** Test conversion + */ + void testExec() + { + // Generate file + string inputFilename("TestConvertFullprofToXMLInput.irf"); + string outputFilename("TestConvertFullprofToXMLOutput.xml"); + generate2BankIrfFile(inputFilename); + + // Init LoadFullprofResolution + ConvertFullprofToXML alg; + alg.initialize(); + + // Set up + alg.setProperty("InputFilename", inputFilename); + alg.setProperty("InstrumentName","POWGEN"); + alg.setProperty("OutputFileName", outputFilename); + + // Execute + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(alg.isExecuted()); + + // has the algorithm written a file to disk? + outputFilename = alg.getPropertyValue("outputFilename"); //Get absolute path + TS_ASSERT( Poco::File(outputFilename).exists() ); + + // Check output file + std::string xmlText = Strings::loadFile(outputFilename); + Poco::XML::DOMParser pParser; + AutoPtr<Document> doc; + TS_ASSERT_THROWS_NOTHING(doc = pParser.parseString(xmlText)); + TS_ASSERT(doc); + if(doc) + { + Element *rootElem = doc->documentElement(); + TS_ASSERT(rootElem->hasChildNodes()); + AutoPtr<NodeList> componentLinkNodeList = rootElem->getElementsByTagName("component-link");; // get component-link elements + size_t numComponentLinks = componentLinkNodeList->length(); + TS_ASSERT_EQUALS(numComponentLinks,3); // Three component-link elements expected + if( numComponentLinks == 3) // We only check the component-links if there are the expected number of them. + { + // Whole Instrument + Poco::XML::Element* componentLinkElem1 = static_cast<Poco::XML::Element*>(componentLinkNodeList->item(0)); + TS_ASSERT(componentLinkElem1); + if(componentLinkElem1) + { + TS_ASSERT_EQUALS(componentLinkElem1->getAttribute("name"),"POWGEN"); + + AutoPtr<NodeList> parameterNodeList = componentLinkElem1->getElementsByTagName("parameter"); // get parameter elements + size_t numParameters = parameterNodeList->length(); + TS_ASSERT_EQUALS(numParameters,4); // Four parameter elements expected + + if( numParameters == 4) // We only check parameters if there are the expected number of them. + { + Poco::XML::Element* paramElem1 = static_cast<Poco::XML::Element*>(parameterNodeList->item(0)); + do_test_paramemeter( paramElem1, "IkedaCarpenterPV:Alpha0", 0.000008, 0.0,"TOF", "", true ); + + //TS_FAIL("About to get Beta0"); + Poco::XML::Element* paramElem2 = static_cast<Poco::XML::Element*>(parameterNodeList->item(1)); + //TS_FAIL("Got Beta0"); + do_test_paramemeter( paramElem2, "IkedaCarpenterPV:Beta0", 6.251096, 0.0, "TOF", "", true ); + + Poco::XML::Element* paramElem3 = static_cast<Poco::XML::Element*>(parameterNodeList->item(2)); + do_test_paramemeter( paramElem3, "IkedaCarpenterPV:Alpha1", 0.1, 0.0, "TOF", "", true ); + + Poco::XML::Element* paramElem4 = static_cast<Poco::XML::Element*>(parameterNodeList->item(3)); + do_test_paramemeter( paramElem4, "IkedaCarpenterPV:Kappa", -0.1, 0.0, "", "", true ); + } + + //parameterNodeList->release(); // Finished with parameter list + } + + // Bank1 + Poco::XML::Element* componentLinkElem2 = static_cast<Poco::XML::Element*>(componentLinkNodeList->item(1)); + TS_ASSERT(componentLinkElem2); + if(componentLinkElem2) + { + TS_ASSERT_EQUALS(componentLinkElem2->getAttribute("name"),"bank1"); + + AutoPtr<NodeList> parameterNodeList = componentLinkElem2->getElementsByTagName("parameter"); // get parameter elements + size_t numParameters = parameterNodeList->length(); + TS_ASSERT_EQUALS(numParameters,2); // Two parameter elements expected + + if(numParameters== 2) // We only check parameters if there are the expected number of them. + { + Poco::XML::Element* paramElem1 = static_cast<Poco::XML::Element*>(parameterNodeList->item(0)); + do_test_paramemeter( paramElem1, "IkedaCarpenterPV:SigmaSquared", 0.00044, 0.355, "TOF^2", "dSpacing", false ); + + Poco::XML::Element* paramElem2 = static_cast<Poco::XML::Element*>(parameterNodeList->item(1)); + do_test_paramemeter( paramElem2, "IkedaCarpenterPV:Gamma", 0.0, 0.0, "TOF", "dSpacing", false ); + } + + //parameterNodeList->release(); // Finished with parameter list + } + + // Bank3 + Poco::XML::Element* componentLinkElem3 = static_cast<Poco::XML::Element*>(componentLinkNodeList->item(2)); + TS_ASSERT(componentLinkElem3); + if(componentLinkElem3) + { + TS_ASSERT_EQUALS(componentLinkElem3->getAttribute("name"),"bank3"); + + AutoPtr<NodeList> parameterNodeList = componentLinkElem3->getElementsByTagName("parameter"); // get parameter elements + size_t numParameters = parameterNodeList->length(); + TS_ASSERT_EQUALS(numParameters,2); // Two parameter elements expected + + if(numParameters== 2) // We only check parameters if there are the expected number of them. + { + Poco::XML::Element* paramElem1 = static_cast<Poco::XML::Element*>(parameterNodeList->item(0)); + do_test_paramemeter( paramElem1, "IkedaCarpenterPV:SigmaSquared", 10.0, 0.0, "TOF^2", "dSpacing", false ); + + Poco::XML::Element* paramElem2 = static_cast<Poco::XML::Element*>(parameterNodeList->item(1)); + do_test_paramemeter( paramElem2, "IkedaCarpenterPV:Gamma", 2.742, 0.0, "TOF", "dSpacing", false ); + } + } + } + } + + //Clean up + Poco::File(inputFilename).remove(); + Poco::File(outputFilename).remove(); + + return; + } + + //--------------------------------------------------------------------------------------------- + /** Test missing instrument parameter + */ + void testMissingInstrument() + { + // Generate file + string inputFilename("TestConvertFullprofToXMLInput.irf"); + string outputFilename("TestConvertFullprofToXMLMissingInstrumentOutput.xml"); + generate2BankIrfFile(inputFilename); + + // Init LoadFullprofResolution + ConvertFullprofToXML alg; + alg.initialize(); + + // Set up + alg.setProperty("InputFilename", inputFilename); + TS_ASSERT_THROWS(alg.setProperty("InstrumentName",""), std::invalid_argument); + alg.setProperty("OutputFileName", outputFilename); + + //Clean up + Poco::File(inputFilename).remove(); + } + + //---------------------------------------------------------------------------------------------- + /** Do test on a parameter element + ** parameElem: parameter element to be tested + ** name: expected name of parameter element to be tested + ** eq1: expected value of first double + ** eq2: expected value of second double, if expected + ** resultUnit: expected value of result-unit + ** unit: expected value of unit + ** fixed: true if parameter is expected to be fixed + */ + void do_test_paramemeter(const Poco::XML::Element* paramElem, const std::string& name, const double eq1, const double eq2, const std::string& resultUnit, const std::string& unit, bool fixed ) + { + TS_ASSERT(paramElem); + if(paramElem) + { + TS_ASSERT_EQUALS(paramElem->getAttribute("type"),"fitting"); + TS_ASSERT_EQUALS(paramElem->getAttribute("name"),name); + Poco::XML::Element* formulaElem = paramElem->getChildElement("formula"); + TS_ASSERT(formulaElem); + if(formulaElem) + { + std::string eqString = formulaElem->getAttribute("eq"); + do_test_eq_value (eqString, name, eq1, eq2 ); + TS_ASSERT_EQUALS(formulaElem->getAttribute("result-unit"),resultUnit); + TS_ASSERT_EQUALS(formulaElem->getAttribute("unit"),unit); + } + Poco::XML::Element* fixedElem = paramElem->getChildElement("fixed"); + if(fixed) + { + TS_ASSERT(fixedElem); + } + else + { + TS_ASSERT(!fixedElem); + } + } + } + + //---------------------------------------------------------------------------------------------- + /** Do test on the eq value of given parameter element. + ** eqValue: value to be tested + ** name: name of parameter element to be tested (determines format of eqValue) + ** eq1: expected value of first double in eqValue + ** eq2: expected value of second double in eqValue, if expected + */ + void do_test_eq_value (const std::string& eqValue, const std::string& name, const double eq1, const double eq2) + { + if(name == "IkedaCarpenterPV:SigmaSquared") + { + // eqValue string expected to be something like "0.00043999999999999996*centre^2+0.35499999999999993" + size_t endEq1 = eqValue.find("*centre^2+",1); + if(endEq1 == std::string::npos) TS_FAIL("'*centre^2+' not found in the value of 'eq' for Sigma squared."); + else + { + std::string eq1Value = eqValue.substr(0,endEq1); + std::string eq2Value = eqValue.substr(endEq1+10,std::string::npos); + double eq1v = parse_double(eq1Value); + TS_ASSERT_DELTA( eq1v, eq1, 0.0000001); + double eq2v = parse_double(eq2Value); + TS_ASSERT_DELTA( eq2v, eq2, 0.0000001); + } + } + else if (name == "IkedaCarpenterPV:Gamma") + { + // eqValue string expected to be something like "2.742*centre" + size_t endEq1 = eqValue.find("*centre",1); + if(endEq1 == std::string::npos) TS_FAIL("'*centre' not found in the value of 'eq' for Gamma."); + else + { + std::string eq1Value = eqValue.substr(0,endEq1); + double eq1v = parse_double(eq1Value); + TS_ASSERT_DELTA( eq1v, eq1, 0.0000001) + } + } + else + { + // eqValue string expected to be just a double + double eqv = parse_double(eqValue); + TS_ASSERT_DELTA( eqv, eq1, 0.0000001) + } + } + + //---------------------------------------------------------------------------------------------- + /** Read a double value from a string and test success of this + */ + double parse_double ( const std::string& value ) + { + try + { + return boost::lexical_cast<double>( value ) ; + } + catch(boost::bad_lexical_cast&) + { + std::string errorMessage = "Can't read double from '"+value+"'."; + TS_FAIL(errorMessage); + return 0.0; + } + } + + //---------------------------------------------------------------------------------------------- + /** Generate a 2 bank .irf file + */ + void generate2BankIrfFile(string filename) + { + ofstream ofile; + ofile.open(filename.c_str()); + + if (ofile.is_open()) + { + ofile << " Instrumental resolution function for POWGEN/SNS A Huq 2013-12-03 ireso: 6 \n"; + ofile << "! For use in testing ConvertFullprofToXML (Res=6) \n"; + ofile << "! ---------------------------------------------- Bank 1 CWL = 0.5330A \n"; + ofile << "! Type of profile function: back-to-back exponentials * pseudo-Voigt \n"; + ofile << "! Tof-min(us) step Tof-max(us) \n"; + ofile << "TOFRG 5000.2300 4.0002 51000.0000 \n"; + ofile << "! Zero Dtt1 \n"; + ofile << "ZD2TOF -1.00 22580.59157 \n"; + ofile << "! Zerot Dtt1t Dtt2t x-cross Width \n"; + ofile << "ZD2TOT 933.50214 22275.21084 1.0290 0.0000002 5.0957 \n"; + ofile << "! TOF-TWOTH of the bank \n"; + ofile << "TWOTH 90.00 \n"; + ofile << "! Sig-2 Sig-1 Sig-0 \n"; + ofile << "SIGMA 514.546 0.00044 0.355 \n"; + ofile << "! Gam-2 Gam-1 Gam-0 \n"; + ofile << "GAMMA 0.000 0.000 0.000 \n"; + ofile << "! alph0 beta0 alph1 beta1 \n"; + ofile << "ALFBE 0.000008 6.251096 0.100000 -0.100000 \n"; + ofile << "! alph0t beta0t alph1t beta1t \n"; + ofile << "ALFBT 0.010156 85.918922 0.000000 0.000000 \n"; + ofile << "END \n"; + ofile << "! ---------------------------------------------- Bank 3 \n"; + ofile << "! Type of profile function: back-to-back exponentials * pseudo-Voigt \n"; + ofile << "! Tof-min(us) step Tof-max(us) \n"; + ofile << "TOFRG 9800.0000 5.0000 86000.0000 \n"; + ofile << "! Zero Dtt1 \n"; + ofile << "ZD2TOF 0.00 22586.10156 \n"; + ofile << "! Zerot Dtt1t Dtt2t x-cross Width \n"; + ofile << "ZD2TOT -42.76068 22622.76953 0.30 0.3560 2.4135 \n"; + ofile << "! TOF-TWOTH of the bank \n"; + ofile << "TWOTH 90.000 \n"; + ofile << "! Sig-2 Sig-1 Sig-0 \n"; + ofile << "SIGMA 72.366 10.000 0.000 \n"; + ofile << "! Gam-2 Gam-1 Gam-0 \n"; + ofile << "GAMMA 0.000 2.742 0.000 \n"; + ofile << "! alph0 beta0 alph1 beta1 \n"; + ofile << "ALFBE 0.000008 6.251096 0.100000 -0.100000 \n"; + ofile << "! alph0t beta0t alph1t beta1t \n"; + ofile << "ALFBT 86.059 96.487 13.445 3.435 \n"; + + ofile.close(); + } + else + { + throw runtime_error("Unable to open file to write."); + } + + return; + } + +}; + + +#endif /* MANTID_DATAHANDLING_CONVERTFULLPROFTOXMLTEST_H_ */ diff --git a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h index d9807889ea26b9c21a6e20ee1dee171c5709345e..54a9ab7953969df73acbaa469375e6d23a1c0422 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadFullprofResolutionTest.h @@ -47,16 +47,20 @@ public: TS_ASSERT(alg.isExecuted()); TableWorkspace_sptr outws = boost::dynamic_pointer_cast<TableWorkspace>( - AnalysisDataService::Instance().retrieve("TestBank1Table")); + AnalysisDataService::Instance().retrieve("TestBank1Table")); TS_ASSERT(outws); TS_ASSERT_EQUALS(outws->columnCount(), 2); TS_ASSERT_EQUALS(outws->rowCount(), 28); - // 3. Verify value + // 3. Verify name and value map<string, double> parammap; parseTableWorkspace(outws, parammap); + TS_ASSERT_EQUALS(parammap.count("Zero"),1); + TS_ASSERT_EQUALS(parammap.count("Sig2"),1); + TS_ASSERT_EQUALS(parammap.count("Beta0t"),1); + TS_ASSERT_DELTA(parammap["Zero"], -1.00, 0.0001); TS_ASSERT_DELTA(parammap["Sig2"], sqrt(514.546), 0.0001); TS_ASSERT_DELTA(parammap["Beta0t"], 85.918922, 0.00001); @@ -95,9 +99,12 @@ public: TS_ASSERT_EQUALS(outws->columnCount(), 2); TS_ASSERT_EQUALS(outws->rowCount(), 28); - // 3. Verify value + // 3. Verify name and value map<string, double> parammap; parseTableWorkspace(outws, parammap); + TS_ASSERT_EQUALS(parammap.count("Dtt1"),1); + TS_ASSERT_EQUALS(parammap.count("Sig1"),1); + TS_ASSERT_EQUALS(parammap.count("Alph0t"),1); TS_ASSERT_DELTA(parammap["Dtt1"], 22586.10156, 0.0001); TS_ASSERT_DELTA(parammap["Sig1"], sqrt(10.00), 0.0001); @@ -140,15 +147,17 @@ public: TS_ASSERT_EQUALS(outws->columnCount(), 3); TS_ASSERT_EQUALS(outws->rowCount(), 28); - // Verify value + // Verify value (including bank number) map<string, double> parammap1; parseTableWorkspace(outws, parammap1); + TS_ASSERT_DELTA(parammap1["BANK"], 1.0, 0.0001); TS_ASSERT_DELTA(parammap1["Dtt1"], 22580.59157, 0.0001); TS_ASSERT_DELTA(parammap1["Sig1"], sqrt(0.00044), 0.0001); TS_ASSERT_DELTA(parammap1["Alph0t"], 0.010156, 0.00001); map<string, double> parammap2; parseTableWorkspace2(outws, parammap2); + TS_ASSERT_DELTA(parammap2["BANK"], 3.0, 0.0001); TS_ASSERT_DELTA(parammap2["Dtt1"], 22586.10156, 0.0001); TS_ASSERT_DELTA(parammap2["Sig1"], sqrt(10.00), 0.0001); TS_ASSERT_DELTA(parammap2["Alph0t"], 86.059, 0.00001); @@ -207,6 +216,57 @@ public: return; } + //---------------------------------------------------------------------------------------------- + /** Test import of ALFBE, GAMMA and SIGMA parameters + * and check they are given their expected names. + * ConvertFullprofToXML relies on features tested here. + */ + void test_ags_parameters() + { + // 1. Generate file + string filename("TestAGS.irf"); + generate1BankIrfFile(filename); + + // 2. Load + LoadFullprofResolution alg; + alg.initialize(); + + alg.setProperty("Filename", filename); + alg.setPropertyValue("Banks", "1"); + alg.setProperty("OutputWorkspace", "TestAGSTable"); + + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(alg.isExecuted()); + + TableWorkspace_sptr outws = boost::dynamic_pointer_cast<TableWorkspace>( + AnalysisDataService::Instance().retrieve("TestAGSTable")); + TS_ASSERT(outws); + + // 3. Verify names + map<string, double> parammap; + parseTableWorkspace(outws, parammap); + + // 3a. ALFBE + TS_ASSERT_EQUALS(parammap.count("Alph0"),1); + TS_ASSERT_EQUALS(parammap.count("Beta0"),1); + TS_ASSERT_EQUALS(parammap.count("Alph1"),1); + TS_ASSERT_EQUALS(parammap.count("Beta1"),1); + // 3b. GAMMA + TS_ASSERT_EQUALS(parammap.count("Gam2"),1); + TS_ASSERT_EQUALS(parammap.count("Gam1"),1); + TS_ASSERT_EQUALS(parammap.count("Gam0"),1); + // 3c. SIGMA + TS_ASSERT_EQUALS(parammap.count("Sig2"),1); + TS_ASSERT_EQUALS(parammap.count("Sig1"),1); + TS_ASSERT_EQUALS(parammap.count("Sig0"),1); + + // 4. Clean + AnalysisDataService::Instance().remove("TestAGSTable"); + Poco::File("TestAGS.irf").remove(); + + return; + } + //---------------------------------------------------------------------------------------------- /** Test Exception */ diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Objects/ShapeFactory.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Objects/ShapeFactory.h index ee3f56dedbf4c88a789f7338200aa9d712d9cecc..5c5000480bc5c8d963c5893ca5d78d6ecc368624 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Objects/ShapeFactory.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Objects/ShapeFactory.h @@ -87,6 +87,7 @@ namespace Mantid std::string parseSliceOfCylinderRing(Poco::XML::Element* pElem, std::map<int, Surface*>& prim, int& l_id); Poco::XML::Element* getShapeElement(Poco::XML::Element* pElem, const std::string& name); + Poco::XML::Element* getOptionalShapeElement(Poco::XML::Element* pElem, const std::string& name); double getDoubleAttribute(Poco::XML::Element* pElem, const std::string& name); Kernel::V3D parsePosition(Poco::XML::Element* pElem); void createGeometryHandler(Poco::XML::Element*,boost::shared_ptr<Object>); diff --git a/Code/Mantid/Framework/Geometry/src/Objects/ShapeFactory.cpp b/Code/Mantid/Framework/Geometry/src/Objects/ShapeFactory.cpp index fbae805e63fdbe688f572b2b635b767c4cc2f05e..5f7197ba6baf7927ccb4d241f37ff9e9dfc863cb 100644 --- a/Code/Mantid/Framework/Geometry/src/Objects/ShapeFactory.cpp +++ b/Code/Mantid/Framework/Geometry/src/Objects/ShapeFactory.cpp @@ -332,7 +332,7 @@ boost::shared_ptr<Object> ShapeFactory::createShape(Poco::XML::Element* pElem) */ std::string ShapeFactory::parseSphere(Poco::XML::Element* pElem, std::map<int, Surface*>& prim, int& l_id) { - Element* pElemCentre = getShapeElement(pElem, "centre"); + Element* pElemCentre = getOptionalShapeElement(pElem, "centre"); Element* pElemRadius = getShapeElement(pElem, "radius"); // getDoubleAttribute can throw - put the calls above any new @@ -340,7 +340,10 @@ std::string ShapeFactory::parseSphere(Poco::XML::Element* pElem, std::map<int, S // create sphere Sphere* pSphere = new Sphere; - pSphere->setCentre(parsePosition(pElemCentre)); + if( pElemCentre ) + pSphere->setCentre(parsePosition(pElemCentre)); + else + pSphere->setCentre(V3D(0, 0, 0)); pSphere->setRadius(radius); prim[l_id] = pSphere; @@ -942,6 +945,31 @@ Poco::XML::Element* ShapeFactory::getShapeElement(Poco::XML::Element* pElem, con } +/** + * Return a subelement of an XML element. The subelement is optional so it may not exist, but + * we also check that there is never more than one. + * + * @param pElem :: XML from instrument definition file. + * @param name :: Name of the subelement. + * @return The subelement, or a null pointer if it does not exist. + * + * @throw std::invalid_argument if XML string is invalid. + */ +Poco::XML::Element* ShapeFactory::getOptionalShapeElement(Poco::XML::Element* pElem, const std::string& name) +{ + // Allow zero or one occurances of subelements with the given name. + Poco::AutoPtr<NodeList> pNL = pElem->getElementsByTagName(name); + if ( pNL->length() == 0) + return NULL; + else if ( pNL->length() > 1) + throw std::invalid_argument("XML element: <" + pElem->tagName() + + "> may contain at most one sub-element with name: <" + name + ">."); + + Element* retVal = static_cast<Element*>(pNL->item(0)); + return retVal; +} + + /** Return value of attribute to XML element. It is an extension of poco's getAttribute method, which * in addition check that this attribute exists and if not throws an error. * @@ -1037,9 +1065,12 @@ void ShapeFactory::createGeometryHandler(Poco::XML::Element* pElem,boost::shared { boost::shared_ptr<GeometryHandler> handler(new GluGeometryHandler(Obj)); Obj->setGeometryHandler(handler); - Element* pElemCentre = getShapeElement(pElem, "centre"); + Element* pElemCentre = getOptionalShapeElement(pElem, "centre"); Element* pElemRadius = getShapeElement(pElem, "radius"); - ((GluGeometryHandler*)(handler.get()))->setSphere(parsePosition(pElemCentre),atof( (pElemRadius->getAttribute("val")).c_str() )); + V3D centre; + if( pElemCentre ) + centre = parsePosition(pElemCentre); + ((GluGeometryHandler*)(handler.get()))->setSphere(centre,atof( (pElemRadius->getAttribute("val")).c_str() )); } else if(pElem->tagName()=="cylinder") { diff --git a/Code/Mantid/Framework/Geometry/test/ShapeFactoryTest.h b/Code/Mantid/Framework/Geometry/test/ShapeFactoryTest.h index 1ad6d8a50c516d50a13b59d73485b7bd3b5ff9e1..49146a015bc318b9d77f185c5b2df387df767412 100644 --- a/Code/Mantid/Framework/Geometry/test/ShapeFactoryTest.h +++ b/Code/Mantid/Framework/Geometry/test/ShapeFactoryTest.h @@ -173,6 +173,30 @@ public: TS_ASSERT( !shape_sptr->isValid(V3D(7.1,2.1,9.1)) ); } + void testSphereWithDefaultCentre() + { + std::string xmlShape = "<sphere id=\"shape\"> "; + xmlShape += "<radius val=\"1.0\" /> " ; + xmlShape += "</sphere>"; + xmlShape += "<algebra val=\"shape\" /> "; + + boost::shared_ptr<Object> shape_sptr = getObject(xmlShape); + + TS_ASSERT( shape_sptr->isValid(V3D( 1.0, 0.0, 0.0)) ); + TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 1.0, 0.0)) ); + TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 0.0, 1.0)) ); + TS_ASSERT( shape_sptr->isValid(V3D(-1.0, 0.0, 0.0)) ); + TS_ASSERT( shape_sptr->isValid(V3D( 0.0,-1.0, 0.0)) ); + TS_ASSERT( shape_sptr->isValid(V3D( 0.0, 0.0,-1.0)) ); + + TS_ASSERT( !shape_sptr->isValid(V3D( 1.1, 0.0, 0.0)) ); + TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 1.1, 0.0)) ); + TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 0.0, 1.1)) ); + TS_ASSERT( !shape_sptr->isValid(V3D(-1.1, 0.0, 0.0)) ); + TS_ASSERT( !shape_sptr->isValid(V3D( 0.0,-1.1, 0.0)) ); + TS_ASSERT( !shape_sptr->isValid(V3D( 0.0, 0.0,-1.1)) ); + } + void testCylinder() { //algebra line is essential diff --git a/Code/Mantid/Framework/Kernel/CMakeLists.txt b/Code/Mantid/Framework/Kernel/CMakeLists.txt index f6ad0d8cd4484ef3f8574d9a87e078f665369270..ea186ce2d30b3e4319ed5c12dd885b67de5805c5 100644 --- a/Code/Mantid/Framework/Kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/Kernel/CMakeLists.txt @@ -367,7 +367,6 @@ add_subdirectory ( test ) # determine it from git and the file already exists. This makes sure the # version number is correct when building off the source tarball -include (PatchVersionNumber) if ( NOT NOT_GIT_REPO OR NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/MantidVersion.cpp ) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/src/MantidVersion.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/MantidVersion.cpp diff --git a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/FileEventDataListener.h b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/FileEventDataListener.h index de7dbdb675d9158f36c22e3ebc767e934f204e6a..7ee42efba3f49c7ad4513743e8c124cabc2f81b0 100644 --- a/Code/Mantid/Framework/LiveData/inc/MantidLiveData/FileEventDataListener.h +++ b/Code/Mantid/Framework/LiveData/inc/MantidLiveData/FileEventDataListener.h @@ -58,15 +58,18 @@ namespace Mantid ILiveListener::RunStatus runStatus(); private: - const std::string m_filename; ///< The file to read + std::string m_filename; ///< The file to read std::string m_tempWSname; ///< The name of the hidden workspace that holds the next chunk int m_numChunks; ///< The number of pieces to divide the file into int m_nextChunk; ///< The number of the next chunk to be loaded + std::string m_filePropName; ///< The file property name for the loader + std::string m_loaderName; ///< The loader that will do the work + bool m_canLoadMonitors; ///< A flag to turn off monitor loading for loaders that can /// Future that holds the result of the latest call to LoadEventPreNexus Poco::ActiveResult<bool> * m_chunkload; void loadChunk(); - /// Shared pointer to the LoadEventPreNexus instance - it needs to be kept alive. + /// Shared pointer to the correct file loader instance - it needs to be kept alive. API::Algorithm_sptr m_loader; /// Flag indicating whether we're using LoadPreNexus (true) or LoadEventPreNexus (false) bool m_preNexus; diff --git a/Code/Mantid/Framework/LiveData/src/FileEventDataListener.cpp b/Code/Mantid/Framework/LiveData/src/FileEventDataListener.cpp index 92d3632d5a443a81962344c819b32b7896e15508..5f021aaf854a1a9f942cafdad8e567cfc6e04ac1 100644 --- a/Code/Mantid/Framework/LiveData/src/FileEventDataListener.cpp +++ b/Code/Mantid/Framework/LiveData/src/FileEventDataListener.cpp @@ -1,6 +1,8 @@ #include "MantidLiveData/FileEventDataListener.h" #include "MantidAPI/LiveListenerFactory.h" #include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/FileFinder.h" +#include "MantidAPI/FileLoaderRegistry.h" #include "MantidKernel/ConfigService.h" using namespace Mantid::Kernel; @@ -17,14 +19,43 @@ namespace LiveData /// Constructor FileEventDataListener::FileEventDataListener() : ILiveListener(), - m_filename(ConfigService::Instance().getString("fileeventdatalistener.filename")), - m_tempWSname("__filelistenerchunk"), m_nextChunk(1), m_chunkload(NULL), m_preNexus(false) + m_tempWSname("__filelistenerchunk"), m_nextChunk(1), m_filePropName("Filename"), + m_loaderName(""), m_canLoadMonitors(true), m_chunkload(NULL) { - if ( m_filename.empty() ) g_log.error("Configuration property fileeventdatalistener.filename not found. The algorithm will fail!"); - if ( m_filename.find("runinfo") != std::string::npos ) + std::string tfilename = ConfigService::Instance().getString("fileeventdatalistener.filename"); + if ( tfilename.empty() ) { - m_preNexus = true; - g_log.information() << "Using LoadPreNexus on file " << m_filename << std::endl; + g_log.error("Configuration property fileeventdatalistener.filename not found. The algorithm will fail!"); + } + else + { + // If passed a filename with no path, find it. Otherwise, same file + // will be found. + m_filename = FileFinder::Instance().getFullPath(tfilename); + if ( m_filename.empty() ) + { + g_log.error("Cannot find " + tfilename + ". The algorithm will fail."); + } + else + { + auto loader = FileLoaderRegistry::Instance().chooseLoader(m_filename); + m_loaderName = loader->name(); + if (m_loaderName.find("Nexus") != std::string::npos && + (m_loaderName.find("Pre") != std::string::npos || + m_loaderName.find("Event") != std::string::npos)) + { + if (m_loaderName.find("Pre") != std::string::npos && + m_loaderName.find("Event") != std::string::npos) + { + m_filePropName = "EventFilename"; + m_canLoadMonitors = false; + } + } + else + { + g_log.error("No loader for " + m_filename + " that supports chunking. The algorithm will fail."); + } + } } if ( ! ConfigService::Instance().getValue("fileeventdatalistener.chunks",m_numChunks) ) @@ -45,9 +76,15 @@ namespace LiveData FileEventDataListener::~FileEventDataListener() { // Don't disappear until any running job has finished or bad things happen! - if ( m_chunkload ) m_chunkload->wait(); + if ( m_chunkload ) + { + m_chunkload->wait(); + } // Clean up the hidden workspace if necessary - if ( AnalysisDataService::Instance().doesExist(m_tempWSname) ) AnalysisDataService::Instance().remove(m_tempWSname); + if ( AnalysisDataService::Instance().doesExist(m_tempWSname) ) + { + AnalysisDataService::Instance().remove(m_tempWSname); + } // Don't leak memory delete m_chunkload; } @@ -66,11 +103,20 @@ namespace LiveData ILiveListener::RunStatus FileEventDataListener::runStatus() { // Say we're outside a run if this is called before start is - if ( m_nextChunk == 1 ) return NoRun; + if ( m_nextChunk == 1 ) + { + return NoRun; + } // This means the first chunk is being/has just been loaded - else if ( m_nextChunk == 2 ) return BeginRun; + else if ( m_nextChunk == 2 ) + { + return BeginRun; + } // This means we've read the whole file - else if ( m_chunkload == NULL ) return EndRun; + else if ( m_chunkload == NULL ) + { + return EndRun; + } // Otherwise we're in the run else return Running; } @@ -86,11 +132,17 @@ namespace LiveData { // Once the end of the file is reached, this method throws to stop the calling algorithm. // This is equivalent to the end of the run - which we still need to figure out how to handle. - if ( m_chunkload == NULL ) throw std::runtime_error("The whole file has been read!"); + if ( m_chunkload == NULL ) + { + throw std::runtime_error("The whole file has been read!"); + } // If the loading of the chunk isn't finished, then we need to wait m_chunkload->wait(); - if ( ! m_chunkload->data() ) throw std::runtime_error("LoadEventPreNexus failed for some reason."); + if ( ! m_chunkload->data() ) + { + throw std::runtime_error("LoadEventPreNexus failed for some reason."); + } // The loading succeeded: get the workspace from the ADS. MatrixWorkspace_sptr chunk = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(m_tempWSname); // Remove the workspace from the ADS now we've extracted it @@ -114,27 +166,18 @@ namespace LiveData /// Load the next chunk of data. Calls Algorithm::executeAsync to do it in another thread. void FileEventDataListener::loadChunk() { - std::string loadingAlg, fileProp; - if ( m_preNexus ) - { - loadingAlg = "LoadPreNexus"; - fileProp = "Filename"; - } - else - { - loadingAlg = "LoadEventPreNexus"; - fileProp = "EventFilename"; - } - - m_loader = AlgorithmManager::Instance().createUnmanaged(loadingAlg); + m_loader = AlgorithmManager::Instance().createUnmanaged(m_loaderName); m_loader->initialize(); // loader->setChild(true); // It can't be a child because the output needs to go in the ADS m_loader->setLogging(false); - m_loader->setPropertyValue(fileProp,m_filename); - m_loader->setProperty("ChunkNumber",m_nextChunk++); // post-increment - m_loader->setProperty("TotalChunks",m_numChunks); - if ( m_preNexus ) m_loader->setProperty("LoadMonitors",false); - m_loader->setPropertyValue("OutputWorkspace",m_tempWSname); // Goes into 'hidden' workspace + m_loader->setPropertyValue(m_filePropName, m_filename); + m_loader->setProperty("ChunkNumber", m_nextChunk++); // post-increment + m_loader->setProperty("TotalChunks", m_numChunks); + if ( m_canLoadMonitors ) + { + m_loader->setProperty("LoadMonitors", false); + } + m_loader->setPropertyValue("OutputWorkspace", m_tempWSname); // Goes into 'hidden' workspace m_chunkload = new Poco::ActiveResult<bool>(m_loader->executeAsync()); } diff --git a/Code/Mantid/Framework/LiveData/src/LiveDataAlgorithm.cpp b/Code/Mantid/Framework/LiveData/src/LiveDataAlgorithm.cpp index 507fdcb3a62f4ab344b9bca913ed40923f3ee7fc..be6cadb5ec8f97ab4550fbc0ed1308dedc463c0d 100644 --- a/Code/Mantid/Framework/LiveData/src/LiveDataAlgorithm.cpp +++ b/Code/Mantid/Framework/LiveData/src/LiveDataAlgorithm.cpp @@ -49,9 +49,11 @@ namespace LiveData instruments.push_back( it->name() ); } } - // TEMPORARY: Add all the listeners by hand while this is all under development +#ifndef NDEBUG + // Debug builds only: Add all the listeners by hand for development testing purposes std::vector<std::string> listeners = Mantid::API::LiveListenerFactory::Instance().getKeys(); instruments.insert( instruments.end(), listeners.begin(), listeners.end() ); +#endif declareProperty(new PropertyWithValue<std::string>("Instrument","", boost::make_shared<StringListValidator>(instruments)), "Name of the instrument to monitor."); diff --git a/Code/Mantid/Framework/LiveData/test/LiveDataAlgorithmTest.h b/Code/Mantid/Framework/LiveData/test/LiveDataAlgorithmTest.h index 3a0412b84f41a4f89d6092c80c73c04221050ab7..2e1f1c52001a910037f6463994dbc52b672d7f1c 100644 --- a/Code/Mantid/Framework/LiveData/test/LiveDataAlgorithmTest.h +++ b/Code/Mantid/Framework/LiveData/test/LiveDataAlgorithmTest.h @@ -8,6 +8,7 @@ #include <iomanip> #include "MantidLiveData/LiveDataAlgorithm.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidTestHelpers/FacilityHelper.h" #include "MantidDataObjects/Workspace2D.h" #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/FrameworkManager.h" @@ -25,8 +26,8 @@ class LiveDataAlgorithmImpl : public LiveDataAlgorithm // Make all the members public so I can test them. friend class LiveDataAlgorithmTest; public: - virtual const std::string name() const { return "LiveDataAlgorithmImpl";}; - virtual int version() const { return 1;}; + virtual const std::string name() const { return "LiveDataAlgorithmImpl";} + virtual int version() const { return 1;} virtual const std::string category() const { return "Testing";} void init() { this->initProps(); } @@ -66,6 +67,8 @@ public: void test_validateInputs() { + FacilityHelper::ScopedFacilities loadTESTFacility("IDFs_for_UNIT_TESTING/UnitTestFacilities.xml", "TEST"); + LiveDataAlgorithmImpl alg; TS_ASSERT_THROWS_NOTHING( alg.initialize() ) TS_ASSERT( alg.isInitialized() ) @@ -87,7 +90,7 @@ public: alg.setPropertyValue("AccumulationWorkspace", "out_ws"); TSM_ASSERT("AccumulationWorkspace == OutputWorkspace", !alg.validateInputs()["AccumulationWorkspace"].empty() ); - alg.setPropertyValue("Instrument", "ISISHistoDataListener"); + alg.setPropertyValue("Instrument", "TESTHISTOLISTENER"); alg.setPropertyValue("AccumulationMethod","Add"); TSM_ASSERT("Shouldn't add histograms", !alg.validateInputs()["AccumulationMethod"].empty() ); } diff --git a/Code/Mantid/Framework/LiveData/test/LoadLiveDataTest.h b/Code/Mantid/Framework/LiveData/test/LoadLiveDataTest.h index 610e29ff673ec32e0339530d91c616b1235d13f5..53216193727bf4d1ee2dc2443a3f636f965a4ba7 100644 --- a/Code/Mantid/Framework/LiveData/test/LoadLiveDataTest.h +++ b/Code/Mantid/Framework/LiveData/test/LoadLiveDataTest.h @@ -12,6 +12,7 @@ #include "MantidDataObjects/Workspace2D.h" #include "MantidKernel/ConfigService.h" #include "MantidAPI/LiveListenerFactory.h" +#include "MantidTestHelpers/FacilityHelper.h" using namespace Mantid; using namespace Mantid::LiveData; @@ -19,12 +20,6 @@ using namespace Mantid::DataObjects; using namespace Mantid::API; using namespace Mantid::Kernel; -class LoadLiveDataImpl : public LoadLiveData -{ -public: -// void store() { Algorithm::store(); } -}; - class LoadLiveDataTest : public CxxTest::TestSuite { public: @@ -64,27 +59,29 @@ public: bool makeThrow = false ) { - std::auto_ptr<LoadLiveDataImpl> alg(new LoadLiveDataImpl); - TS_ASSERT_THROWS_NOTHING( alg->initialize() ) - TS_ASSERT( alg->isInitialized() ) - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("Instrument", "TestDataListener") ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("AccumulationMethod", AccumulationMethod) ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("ProcessingAlgorithm", ProcessingAlgorithm) ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("ProcessingProperties", ProcessingProperties) ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("PostProcessingAlgorithm", PostProcessingAlgorithm) ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("PostProcessingProperties", PostProcessingProperties) ); - TS_ASSERT_THROWS_NOTHING( alg->setProperty("PreserveEvents", PreserveEvents) ); + FacilityHelper::ScopedFacilities loadTESTFacility("IDFs_for_UNIT_TESTING/UnitTestFacilities.xml", "TEST"); + + LoadLiveData alg; + TS_ASSERT_THROWS_NOTHING( alg.initialize() ) + TS_ASSERT( alg.isInitialized() ) + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Instrument", "TestDataListener") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("AccumulationMethod", AccumulationMethod) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("ProcessingAlgorithm", ProcessingAlgorithm) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("ProcessingProperties", ProcessingProperties) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("PostProcessingAlgorithm", PostProcessingAlgorithm) ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("PostProcessingProperties", PostProcessingProperties) ); + TS_ASSERT_THROWS_NOTHING( alg.setProperty("PreserveEvents", PreserveEvents) ); if (!PostProcessingAlgorithm.empty()) - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("AccumulationWorkspace", "fake_accum") ); - TS_ASSERT_THROWS_NOTHING( alg->setPropertyValue("OutputWorkspace", "fake") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("AccumulationWorkspace", "fake_accum") ); + TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", "fake") ); if (listener) - alg->setLiveListener(listener); + alg.setLiveListener(listener); if (!makeThrow) - { TS_ASSERT_THROWS_NOTHING( alg->execute(); ); } + { TS_ASSERT_THROWS_NOTHING( alg.execute(); ); } else - alg->exec(); - TS_ASSERT( alg->isExecuted() ); + alg.exec(); + TS_ASSERT( alg.isExecuted() ); // Retrieve the workspace from data service. boost::shared_ptr<TYPE> ws; diff --git a/Code/Mantid/Framework/LiveData/test/MonitorLiveDataTest.h b/Code/Mantid/Framework/LiveData/test/MonitorLiveDataTest.h index 6239460739137f31c0b5f66aaf7e97c5f0e84652..72871fca393aa272966e274ce137430a1c177bf8 100644 --- a/Code/Mantid/Framework/LiveData/test/MonitorLiveDataTest.h +++ b/Code/Mantid/Framework/LiveData/test/MonitorLiveDataTest.h @@ -13,6 +13,7 @@ #include "MantidDataObjects/EventWorkspace.h" #include "MantidKernel/ConfigService.h" #include "MantidAPI/FrameworkManager.h" +#include "MantidTestHelpers/FacilityHelper.h" using namespace Mantid; using namespace Mantid::LiveData; @@ -22,12 +23,18 @@ using namespace Mantid::Kernel; class MonitorLiveDataTest : public CxxTest::TestSuite { +private: + FacilityHelper::ScopedFacilities loadTESTFacility; + public: // This pair of boilerplate methods prevent the suite being created statically // This means the constructor isn't called when running other tests static MonitorLiveDataTest *createSuite() { return new MonitorLiveDataTest(); } static void destroySuite( MonitorLiveDataTest *suite ) { delete suite; } + MonitorLiveDataTest() : loadTESTFacility("IDFs_for_UNIT_TESTING/UnitTestFacilities.xml", "TEST") + {} + void setUp() { // Register algorithms diff --git a/Code/Mantid/Framework/LiveData/test/StartLiveDataTest.h b/Code/Mantid/Framework/LiveData/test/StartLiveDataTest.h index 11cad6f54033aadc591d851bdbf1d47354a3c925..3b2f20075de223ee1e70adba39ad639be2e9e120 100644 --- a/Code/Mantid/Framework/LiveData/test/StartLiveDataTest.h +++ b/Code/Mantid/Framework/LiveData/test/StartLiveDataTest.h @@ -12,6 +12,7 @@ #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/FrameworkManager.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" +#include "MantidTestHelpers/FacilityHelper.h" using namespace Mantid; using namespace Mantid::LiveData; @@ -21,12 +22,17 @@ using namespace Mantid::Kernel; class StartLiveDataTest : public CxxTest::TestSuite { +private: + FacilityHelper::ScopedFacilities loadTESTFacility; + public: // This pair of boilerplate methods prevent the suite being created statically // This means the constructor isn't called when running other tests static StartLiveDataTest *createSuite() { return new StartLiveDataTest(); } static void destroySuite( StartLiveDataTest *suite ) { delete suite; } + StartLiveDataTest() : loadTESTFacility("IDFs_for_UNIT_TESTING/UnitTestFacilities.xml", "TEST") + {} void test_Init() { diff --git a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD.cpp index e3bc44f96ed08da2ceb0464f1eb83a0e9895ad3f..05c8d82ef8d779ff85568da3395716e727e5d539 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/IntegratePeaksMD.cpp @@ -230,6 +230,9 @@ namespace MDAlgorithms size_t numSteps = 0; bool cylinderBool = getProperty("Cylinder"); bool adaptiveQRadius = getProperty("AdaptiveQRadius"); + std::vector<double> PeakRadiusVector(peakWS->getNumberPeaks(),PeakRadius); + std::vector<double> BackgroundInnerRadiusVector(peakWS->getNumberPeaks(),BackgroundInnerRadius); + std::vector<double> BackgroundOuterRadiusVector(peakWS->getNumberPeaks(),BackgroundOuterRadius); if (cylinderBool) { numSteps = 100; @@ -351,6 +354,9 @@ namespace MDAlgorithms } lenQpeak = std::sqrt(lenQpeak); } + PeakRadiusVector[i] = lenQpeak*PeakRadius; + BackgroundInnerRadiusVector[i] = lenQpeak*BackgroundInnerRadius; + BackgroundOuterRadiusVector[i] = lenQpeak*BackgroundOuterRadius; CoordTransformDistance sphere(nd, center, dimensionsUsed); // Perform the integration into whatever box is contained within. @@ -622,9 +628,9 @@ namespace MDAlgorithms // This flag is used by the PeaksWorkspace to evaluate whether it has been integrated. peakWS->mutableRun().addProperty("PeaksIntegrated", 1, true); // These flags are specific to the algorithm. - peakWS->mutableRun().addProperty("PeakRadius", PeakRadius, true); - peakWS->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadius, true); - peakWS->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadius, true); + peakWS->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true); + peakWS->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadiusVector, true); + peakWS->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadiusVector, true); // save profiles in peaks file const std::string outfile = getProperty("ProfilesFile"); diff --git a/Code/Mantid/Framework/MDEvents/src/IntegrateEllipsoids.cpp b/Code/Mantid/Framework/MDEvents/src/IntegrateEllipsoids.cpp index 5b2b44a7bc9dde3bf6bc94d4d35e829598e647fd..78d361d75451a6703d0dca7abce16af73a549687 100644 --- a/Code/Mantid/Framework/MDEvents/src/IntegrateEllipsoids.cpp +++ b/Code/Mantid/Framework/MDEvents/src/IntegrateEllipsoids.cpp @@ -280,6 +280,9 @@ namespace MDEvents double peak_radius = getProperty( "PeakSize" ); double back_inner_radius = getProperty( "BackgroundInnerSize" ); double back_outer_radius = getProperty( "BackgroundOuterSize" ); + std::vector<double> PeakRadiusVector(n_peaks,peak_radius); + std::vector<double> BackgroundInnerRadiusVector(n_peaks,back_inner_radius); + std::vector<double> BackgroundOuterRadiusVector(n_peaks,back_outer_radius); if ( specify_size ) { if ( back_outer_radius > radius ) @@ -380,10 +383,9 @@ namespace MDEvents // This flag is used by the PeaksWorkspace to evaluate whether it has been integrated. peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true); // These flags are specific to the algorithm. - peak_ws->mutableRun().addProperty("PeakRadius", peak_radius, true); - peak_ws->mutableRun().addProperty("BackgroundInnerRadius", back_inner_radius, true); - peak_ws->mutableRun().addProperty("BackgroundOuterRadius", back_outer_radius, true); - + peak_ws->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true); + peak_ws->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadiusVector, true); + peak_ws->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadiusVector, true); setProperty("OutputWorkspace", peak_ws); } diff --git a/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp index 94f278abe9b90713feeac982d8ae898db5f9469e..604d786b71a237137879274d17ac3c2c66145ffc 100644 --- a/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp +++ b/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp @@ -264,6 +264,15 @@ namespace MDEvents output->cell<double>(rowCounter, cellIndex++) = it->getNormalizedError(); output->cell<int>(rowCounter, cellIndex++) = int(it->getNumEvents()); VMD center = it->getCenter(); + const size_t numberOriginal = input->numOriginalWorkspaces(); + if(numberOriginal > 0) + { + const size_t index = numberOriginal -1; + CoordTransform * transform = input->getTransformToOriginal(index); + VMD temp = transform->applyVMD(center); + center = temp; + } + for(size_t index = 0; index < ndims; ++index) { output->cell<double>(rowCounter, cellIndex++) = center[index]; diff --git a/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h b/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h index 9f5766663a0c31dd2338f584d4e9bd3c867a37b3..e512e94cc596399c51c67a3af22f320cb409be36 100644 --- a/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h +++ b/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h @@ -11,6 +11,8 @@ #include "MantidMDEvents/QueryMDWorkspace.h" #include "MantidAPI/ITableWorkspace.h" #include "MantidDataObjects/TableWorkspace.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/AlgorithmManager.h" using namespace Mantid; using namespace Mantid::MDEvents; @@ -25,6 +27,10 @@ public: static QueryMDWorkspaceTest *createSuite() { return new QueryMDWorkspaceTest(); } static void destroySuite( QueryMDWorkspaceTest *suite ) { delete suite; } + QueryMDWorkspaceTest() + { + FrameworkManager::Instance(); + } void checkInputs(std::string strNormalisation) { @@ -193,10 +199,62 @@ public: TSM_ASSERT("Workspace output is not an ITableWorkspace", table !=NULL); size_t expectedCount = 3 + in_ws->getNumDims(); //3 fixed columns are Signal, Error, nEvents - TSM_ASSERT_EQUALS("Six columns expected", expectedCount, table->columnCount()); + TSM_ASSERT_EQUALS("Five columns expected", expectedCount, table->columnCount()); TSM_ASSERT_EQUALS("Wrong number of rows", 3, table->rowCount()); } + void testOnSlice() + { + auto in_ws = MDEventsTestHelper::makeMDEW<2>(2, -10.0, 10, 3); + + // Create a line slice at 45 degrees to the original workspace. + IAlgorithm_sptr binMDAlg = AlgorithmManager::Instance().create("BinMD"); + binMDAlg->setRethrows(true); + binMDAlg->initialize(); + binMDAlg->setChild(true); + binMDAlg->setProperty("InputWorkspace", in_ws); + binMDAlg->setProperty("AxisAligned", false); + binMDAlg->setPropertyValue("BasisVector0", "X,units,0.7071,0.7071"); // cos 45 to in_ws x-axis (consistent with a 45 degree anti-clockwise rotation) + binMDAlg->setPropertyValue("BasisVector1", "Y,units,-0.7071,0.7071"); // cos 45 to in_ws y-axis (consistent with a 45 degree anti-clockwise rotation) + binMDAlg->setPropertyValue("OutputExtents", "0,28.284,-1,1"); // 0 to sqrt((-10-10)^2 + (-10-10)^2), -1 to 1 (in new coordinate axes) + binMDAlg->setPropertyValue("OutputBins", "10,1"); + binMDAlg->setPropertyValue("OutputWorkspace", "temp"); + binMDAlg->execute(); + Workspace_sptr temp = binMDAlg->getProperty("OutputWorkspace"); + auto slice = boost::dynamic_pointer_cast<IMDWorkspace>(temp); + + QueryMDWorkspace query; + query.setRethrows(true); + query.setChild(true); + query.initialize(); + query.setProperty("InputWorkspace", slice); + query.setPropertyValue("OutputWorkspace", "QueryWS"); + query.execute(); + ITableWorkspace_sptr table = query.getProperty("OutputWorkspace"); + + TSM_ASSERT("Workspace output is not an ITableWorkspace", table !=NULL); + size_t expectedCount = 3 + in_ws->getNumDims(); //3 fixed columns are Signal, Error, nEvents + TSM_ASSERT_EQUALS("Six columns expected", expectedCount, table->columnCount()); + TSM_ASSERT_EQUALS("Wrong number of rows", 10, table->rowCount()); + + /* + Note that what we do in the following is to check that the y and x coordinates are the same. They will ONLY be the same in the + original coordinate system owing to the way that they have been rotated. If we were displaying the results in the new coordinate system + then y == 0 and x would increment from 0 to sqrt((-10-10)^2 + (-10-10)^2). + */ + for(size_t i =0; i < table->rowCount(); ++i) + { + auto xColumn = table->getColumn(3); + auto yColumn = table->getColumn(4); + double x = xColumn->toDouble(i); + double y = yColumn->toDouble(i); + std::stringstream messageBuffer; + messageBuffer << "X and Y should be equal at row index: " << i; + TSM_ASSERT_DELTA(messageBuffer.str(), x, y, 1e-3); + } + + } + }; diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp index aa569269f9bd159febe1fcab888727ec1df3f9b3..0bb985354ae007642f061f31c140d411ee839008 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp @@ -77,7 +77,7 @@ void export_AnalysisDataService() class_<AnalysisDataServiceImpl,boost::noncopyable>("AnalysisDataServiceImpl", no_init) .def("add", &AnalysisDataServiceImpl::add, "Adds the given object to the service with the given name. If the name/object exists it will raise an error.") - .def("addOrReplace", &AnalysisDataServiceImpl::add, "Adds the given object to the service with the given name. The the name exists the object is replaced.") + .def("addOrReplace", &AnalysisDataServiceImpl::addOrReplace, "Adds the given object to the service with the given name. The the name exists the object is replaced.") .def("doesExist", &AnalysisDataServiceImpl::doesExist, "Returns True if the object is found in the service.") .def("retrieve", &retrieveAsWeakPtr, return_value_policy<Policies::DowncastReturnedValue>(), "Retrieve the named object. Raises an exception if the name does not exist") diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Exports/ConfigService.cpp b/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Exports/ConfigService.cpp index 5b23f35fa780854e1b179dfbe683ac3ac5dc6e92..7377bf3e03662e2c7a59c985ed950cf8a6806901 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Exports/ConfigService.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/kernel/src/Exports/ConfigService.cpp @@ -64,7 +64,9 @@ void export_ConfigService() (arg("facilityName")), return_value_policy<reference_existing_object>(), "Returns the named facility. Raises an RuntimeError if it does not exist") - .def("setFacility", &ConfigServiceImpl::setString, (arg("facilityName")), "Sets the current facility to the given name") + .def("setFacility", &ConfigServiceImpl::setFacility, "Sets the current facility to the given name") + + .def("updateFacilities", &ConfigServiceImpl::updateFacilities, "Loads facility information from a provided file") .def("getInstrument", &ConfigServiceImpl::getInstrument, getInstrument_Overload("Returns the named instrument. If name = \"\" then the default.instrument is returned", diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1D.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1D.py index bd2bf1d9801de51729657684c9ccd8ca8dd57635..868b841379e3cea70c71fb90f34666c483027ba5 100644 --- a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1D.py +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1D.py @@ -26,7 +26,7 @@ class Stitch1D(PythonAlgorithm): self.declareProperty(name="StartOverlap", defaultValue=-1.0, validator=overlap_validator, doc="Overlap in Q.") self.declareProperty(name="EndOverlap", defaultValue=-1.0, validator=overlap_validator, doc="End overlap in Q.") - self.declareProperty(name="Params", defaultValue="0.1", doc="Rebinning Parameters. See Rebin for format.") + self.declareProperty(FloatArrayProperty(name="Params", values=[0.1]), doc="Rebinning Parameters. See Rebin for format.") self.declareProperty(name="ScaleRHSWorkspace", defaultValue=True, doc="Scaling either with respect to workspace 1 or workspace 2.") self.declareProperty(name="UseManualScaleFactor", defaultValue=False, doc="True to use a provided value for the scale factor.") self.declareProperty(name="ManualScaleFactor", defaultValue=1.0, doc="Provided value for the scale factor.") @@ -38,9 +38,10 @@ class Stitch1D(PythonAlgorithm): return count > 0 def PyExec(self): + rangeTolerance = 1e-9 # Just forward the other properties on. - startOverlap = self.getProperty('StartOverlap').value - endOverlap = self.getProperty('EndOverlap').value + startOverlap = self.getProperty('StartOverlap').value - rangeTolerance + endOverlap = self.getProperty('EndOverlap').value + rangeTolerance scaleRHSWorkspace = self.getProperty('ScaleRHSWorkspace').value useManualScaleFactor = self.getProperty('UseManualScaleFactor').value manualScaleFactor = self.getProperty('ManualScaleFactor').value diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1DMany.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1DMany.py new file mode 100644 index 0000000000000000000000000000000000000000..221757658462f3ee382c0a338985722d31f1bbda --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/Stitch1DMany.py @@ -0,0 +1,90 @@ +"""*WIKI* + +Stitches single histogram [[MatrixWorkspace|Matrix Workspaces]] together outputing a stitched Matrix Workspace. This algorithm is a wrapper over [[Stitch1DMD]]. + +The algorithm expects pairs of StartOverlaps and EndOverlaps values. The order in which these are provided determines the pairing. +There should be N entries in each of these StartOverlaps and EndOverlaps lists, where N = 1 -(No of workspaces to stitch). +StartOverlaps and EndOverlaps are in the same units as the X-axis for the workspace. + +*WIKI*""" +#from mantid.simpleapi import * + +from mantid.simpleapi import * +from mantid.api import * +from mantid.kernel import * +import numpy as np + +class Stitch1DMany(PythonAlgorithm): + + def category(self): + return "Reflectometry\\ISIS;PythonAlgorithms" + + def name(self): + return "Stitch1D" + + def PyInit(self): + + input_validator = StringMandatoryValidator() + + self.declareProperty(name="InputWorkspaces", defaultValue="", direction=Direction.Input, validator=input_validator, doc="Input workspaces") + self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output), "Output stitched workspace") + + overlap_validator = FloatArrayMandatoryValidator() + + self.declareProperty(FloatArrayProperty(name="StartOverlaps", values=[], validator=overlap_validator), doc="Overlap in Q.") + self.declareProperty(FloatArrayProperty(name="EndOverlaps", values=[], validator=overlap_validator), doc="End overlap in Q.") + self.declareProperty(FloatArrayProperty(name="Params", values=[0.1]), doc="Rebinning Parameters. See Rebin for format.") + self.declareProperty(name="ScaleRHSWorkspace", defaultValue=True, doc="Scaling either with respect to workspace 1 or workspace 2.") + self.declareProperty(name="UseManualScaleFactor", defaultValue=False, doc="True to use a provided value for the scale factor.") + self.declareProperty(name="ManualScaleFactor", defaultValue=1.0, doc="Provided value for the scale factor.") + self.declareProperty(name="OutScaleFactor", defaultValue=-2.0, direction = Direction.Output, doc="The actual used value for the scaling factor.") + + def __workspace_from_split_name(self, list_of_names, index): + return mtd[list_of_names[index].strip()] + + def PyExec(self): + + inputWorkspaces = self.getProperty("InputWorkspaces").value + # Just forward the other properties on. + startOverlaps = self.getProperty('StartOverlaps').value + endOverlaps = self.getProperty('EndOverlaps').value + scaleRHSWorkspace = self.getProperty('ScaleRHSWorkspace').value + useManualScaleFactor = self.getProperty('UseManualScaleFactor').value + manualScaleFactor = self.getProperty('ManualScaleFactor').value + params = self.getProperty("Params").value + + inputWorkspaces = inputWorkspaces.split(',') + numberOfWorkspaces = len(inputWorkspaces) + if not numberOfWorkspaces > 1: + raise ValueError("Too few workspaces to stitch") + if not (len(startOverlaps) == len(endOverlaps)): + raise ValueError("StartOverlaps and EndOverlaps are different lengths") + if not (len(startOverlaps) == (numberOfWorkspaces- 1)): + raise ValueError("Wrong number of StartOverlaps, should be %i not %i" % (numberOfWorkspaces - 1, startOverlaps)) + + scaleFactor = None + + # Iterate forward through the workspaces + if scaleRHSWorkspace: + lhsWS = self.__workspace_from_split_name(inputWorkspaces, 0) + for i in range(1, numberOfWorkspaces, 1): + rhsWS = self.__workspace_from_split_name(inputWorkspaces, i) + lhsWS, scaleFactor = Stitch1D(LHSWorkspace=lhsWS, RHSWorkspace=rhsWS, StartOverlap=startOverlaps[i-1], EndOverlap=endOverlaps[i-1], Params=params, ScaleRHSWorkspace=scaleRHSWorkspace, UseManualScaleFactor=useManualScaleFactor, ManualScaleFactor=manualScaleFactor) + self.setProperty('OutputWorkspace', lhsWS) + DeleteWorkspace(lhsWS) + # Iterate backwards through the workspaces. + else: + rhsWS = self.__workspace_from_split_name(inputWorkspaces, -1) + for i in range(0, numberOfWorkspaces-1, 1): + lhsWS = self.__workspace_from_split_name(inputWorkspaces, i) + rhsWS, scaleFactor = Stitch1D(LHSWorkspace=lhsWS, RHSWorkspace=rhsWS, StartOverlap=startOverlaps[i-1], EndOverlap=endOverlaps[i-1], Params=params, ScaleRHSWorkspace=scaleRHSWorkspace, UseManualScaleFactor=useManualScaleFactor, ManualScaleFactor=manualScaleFactor) + self.setProperty('OutputWorkspace', rhsWS) + DeleteWorkspace(rhsWS) + + self.setProperty('OutScaleFactor', scaleFactor) + return None + + +############################################################################################# + +AlgorithmFactory.subscribe(Stitch1DMany) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AnalysisDataServiceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AnalysisDataServiceTest.py index cb26c34ea0b65927503d35bced853dc7b002089b..1d52d3b78a6fc665ae8cef6223b8f01c024b8c9a 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AnalysisDataServiceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/AnalysisDataServiceTest.py @@ -51,6 +51,18 @@ class AnalysisDataServiceTest(unittest.TestCase): AnalysisDataService.addOrReplace(name, ws) self.assertRaises(RuntimeError, AnalysisDataService.add, name, ws) AnalysisDataService.remove(name) + + def test_addOrReplace_replaces_workspace_with_existing_name(self): + data = [1.0,2.0,3.0] + alg = run_algorithm('CreateWorkspace',DataX=data,DataY=data,NSpec=1,UnitX='Wavelength', child=True) + name = "testws" + ws = alg.getProperty("OutputWorkspace").value + AnalysisDataService.add(name, ws) + len_before = len(AnalysisDataService) + AnalysisDataService.addOrReplace(name, ws) + len_after = len(AnalysisDataService) + self.assertEquals(len_after, len_before) + AnalysisDataService.remove(name) def do_check_for_matrix_workspace_type(self, workspace): self.assertTrue(isinstance(workspace, MatrixWorkspace)) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/kernel/ConfigServiceTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/kernel/ConfigServiceTest.py index edbe56ec0883c66406c11751aec977dc9e980b41..0975c52f82a0a2ac1ee0955ba2a204b470ad71dc 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/kernel/ConfigServiceTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/kernel/ConfigServiceTest.py @@ -42,6 +42,13 @@ class ConfigServiceTest(unittest.TestCase): for i in range(len(names)): self.assertEquals(names[i],facilities[i].name()) + def test_update_and_set_facility(self): + self.assertFalse("TEST" in config.getFacilityNames()) + ConfigService.updateFacilities(os.path.join(ConfigService.getInstrumentDirectory(),"IDFs_for_UNIT_TESTING/UnitTestFacilities.xml")) + ConfigService.setFacility("TEST") + self.assertEquals(config.getFacility().name(), "TEST") + self.assertRaises(RuntimeError, config.getFacility, "SNS") + def test_getInstrumentReturns_A_InstrumentInfo_Object(self): self.assertTrue(isinstance(config.getInstrument("WISH"), InstrumentInfo)) self.assertRaises(RuntimeError, config.getInstrument, "MadeUpInstrument") diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index d0e61e3a763f1afa246c9310eb8a721ebb777fd9..4cc816c505b023d22add1f37190a1aa0f5f4c2c5 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -20,6 +20,7 @@ set ( TEST_PY_FILES SANSWideAngleCorrectionTest.py SortXAxisTest.py Stitch1DTest.py + Stitch1DManyTest.py SuggestTibCNCSTest.py SuggestTibHYSPECTest.py UpdatePeakParameterTableValueTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/LoadLiveDataTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/LoadLiveDataTest.py index e278ec25ac35eebca62bcf8fd2d0434fa8e64aed..192600b9df4664d12e010450e9ae3f3510572571 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/LoadLiveDataTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/LoadLiveDataTest.py @@ -12,6 +12,8 @@ class LoadLiveDataTest(unittest.TestCase): def setUp(self): FrameworkManager.clearData() + ConfigService.updateFacilities(os.path.join(ConfigService.getInstrumentDirectory(),"IDFs_for_UNIT_TESTING/UnitTestFacilities.xml")) + ConfigService.setFacility("TEST") pass diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/Stitch1DManyTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/Stitch1DManyTest.py new file mode 100644 index 0000000000000000000000000000000000000000..e041b5b380e4070de0b78585224335614f3b848c --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/Stitch1DManyTest.py @@ -0,0 +1,99 @@ +import unittest +import numpy +from mantid.simpleapi import * +from mantid.kernel import * +from mantid.api import * + +class Stitch1DManyTest(unittest.TestCase): + + a = None + b = None + c = None + x = None + e = None + + def setUp(self): + x = numpy.arange(-1, 1.2, 0.2) + e = numpy.arange(-1, 1, 0.2) + e.fill(0) + self.e = e + self.x = x + a = CreateWorkspace(UnitX="1/q", DataX=x, DataY=[0.0,0.0,0.0,3.0,3.0,3.0,3.0,3.0,3.0,3.0], NSpec=1, DataE=e) + b = CreateWorkspace(UnitX="1/q", DataX=x, DataY=[2.0,2.0,2.0,2.0,2.0,2.0,2.0,0.0,0.0,0.0], NSpec=1, DataE=e) + self.a = a + self.b = b + + def tearDown(self): + # Cleanup + DeleteWorkspace(self.a) + DeleteWorkspace(self.b) + + def test_stitch_throws_with_too_few_workspaces(self): + try: + stitched = Stitch1DMany(InputWorkspaces='a', StartOverlaps=[-0.5], EndOverlaps=[0.5], Params=[0.1]) + self.fail("Only one workspace. Should have thrown.") + except RuntimeError: + pass + + def test_stitch_throws_with_wrong_number_of_Start_overlaps(self): + try: + stitched = Stitch1DMany(InputWorkspaces='a, b', StartOverlaps=[-0.5, -0.6], EndOverlaps=[0.5], Params=[0.1]) + self.fail("Two start overlaps, but only two workspaces. Should have thrown.") + except RuntimeError: + pass + + def test_stitch_throws_with_wrong_number_of_End_overlaps(self): + try: + stitched = Stitch1DMany(InputWorkspaces='a, b', StartOverlaps=[-0.5], EndOverlaps=[0.5, 0.6], Params=[0.1]) + self.fail("Two end overlaps, but only two workspaces. Should have thrown.") + except RuntimeError: + pass + + + def do_check_ydata(self, expectedYData, targetWS): + yDataRounded = [ round(elem, 4) for elem in targetWS.readY(0) ] + same = all([(x == y) for x,y in zip(yDataRounded, expectedYData)]) + self.assertTrue(same) + + ''' + Cross-check that the result of using Stitch1DMany with two workspaces is the same as using Stitch1D. + ''' + def test_stitches_two(self): + stitchedViaStitchMany, scaleFactorMany = Stitch1DMany(InputWorkspaces='a, b', StartOverlaps=[-0.4], EndOverlaps=[0.4], Params=[0.2]) + stitchedViaStitchTwo, scaleFactorTwo = Stitch1D(LHSWorkspace=self.a, RHSWorkspace=self.b, StartOverlap=-0.4, EndOverlap=0.4, Params=[0.2]) + self.assertEquals(scaleFactorTwo, scaleFactorMany) + + expectedYData = [0,0,0,3,3,3,3,0,0,0] + self.do_check_ydata(expectedYData, stitchedViaStitchMany) + + # Do cross compare + isSuccess = CheckWorkspacesMatch(Workspace1=stitchedViaStitchMany, Workspace2=stitchedViaStitchTwo) + self.assertEquals("Success!", isSuccess); + + DeleteWorkspace(stitchedViaStitchMany) + DeleteWorkspace(stitchedViaStitchTwo) + + def test_stitches_three(self): + ws1 = CreateWorkspace(UnitX="1/q", DataX=self.x, DataY=[3.0, 3.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], NSpec=1, DataE=self.e) + ws2 = CreateWorkspace(UnitX="1/q", DataX=self.x, DataY=[0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0], NSpec=1, DataE=self.e) + ws3 = CreateWorkspace(UnitX="1/q", DataX=self.x, DataY=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0], NSpec=1, DataE=self.e) + stitchedViaStitchMany, sf = Stitch1DMany(InputWorkspaces='ws1, ws2, ws3', StartOverlaps=[-0.4,0.2], EndOverlaps=[-0.2,0.4], Params=[0.2]) + + expectedYData = [3,3,3,3,3,3,3,3,3,3] + self.do_check_ydata(expectedYData, stitchedViaStitchMany) + self.assertEquals(3.0, round(sf, 6)) + + DeleteWorkspace(ws1) + DeleteWorkspace(ws2) + DeleteWorkspace(ws3) + DeleteWorkspace(stitchedViaStitchMany) + + def test_stitches_using_manual_scaling(self): + stitchedViaStitchMany, sf = Stitch1DMany(InputWorkspaces='a, b', StartOverlaps=[-0.4], EndOverlaps=[0.4], Params=[0.2], UseManualScaleFactor=True, ManualScaleFactor=2.0) + + self.assertEquals(2.0, round(sf, 6)) + DeleteWorkspace(stitchedViaStitchMany) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/AlignAndFocusPowder.h b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/AlignAndFocusPowder.h index eeed812c9aba2c122650d0df3b8f28d9ea87d05a..ccaae6a81dc0f3173306d5dc01242b2610131825 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/AlignAndFocusPowder.h +++ b/Code/Mantid/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/AlignAndFocusPowder.h @@ -58,15 +58,15 @@ namespace Mantid { public: /// Empty Constructor - AlignAndFocusPowder() : API::Algorithm() {} + AlignAndFocusPowder(); /// Destructor - virtual ~AlignAndFocusPowder() {} + virtual ~AlignAndFocusPowder(); /// Algorithm's name for identification overriding a virtual method - virtual const std::string name() const { return "AlignAndFocusPowder";} + virtual const std::string name() const; /// Algorithm's version for identification overriding a virtual method - virtual int version() const { return 1;} + virtual int version() const; /// Algorithm's category for identification overriding a virtual method - virtual const std::string category() const { return "Workflow\\Diffraction";} + virtual const std::string category() const; private: /// Sets documentation strings for this algorithm @@ -98,7 +98,7 @@ namespace Mantid DataObjects::OffsetsWorkspace_sptr m_offsetsWS; API::MatrixWorkspace_sptr m_maskWS; DataObjects::GroupingWorkspace_sptr m_groupWS; - double l1; + double m_l1; std::vector<int32_t> specids; std::vector<double> l2s; std::vector<double> tths; @@ -128,6 +128,7 @@ namespace Mantid /// Offset to low resolution TOF spectra size_t m_lowResSpecOffset; + API::Progress* m_progress; ///< Progress reporting }; } // namespace WorkflowAlgorithm diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/AlignAndFocusPowder.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/AlignAndFocusPowder.cpp index b264cb5e2d2b64f20303797c4e5905233ecf85ce..ffd7fc08048b894f0a3598a176c57ca419ad4b41 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/AlignAndFocusPowder.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/AlignAndFocusPowder.cpp @@ -54,6 +54,31 @@ namespace WorkflowAlgorithms // Register the class into the algorithm factory DECLARE_ALGORITHM(AlignAndFocusPowder) + AlignAndFocusPowder::AlignAndFocusPowder() : + API::Algorithm(), m_progress(NULL) + {} + + AlignAndFocusPowder::~AlignAndFocusPowder() + { + if (m_progress) + delete m_progress; + } + + const std::string AlignAndFocusPowder::name() const + { + return "AlignAndFocusPowder"; + } + + int AlignAndFocusPowder::version() const + { + return 1; + } + + const std::string AlignAndFocusPowder::category() const + { + return "Workflow\\Diffraction"; + } + //---------------------------------------------------------------------------------------------- /** Sets documentation strings for this algorithm */ @@ -123,6 +148,41 @@ namespace WorkflowAlgorithms } + template <typename NumT> + void splitVectors(const std::vector<NumT> &orig, const size_t numVal, + const std::string &label, + std::vector<NumT> &left, std::vector<NumT> &right) + { + // clear the outputs + left.clear(); + right.clear(); + + // check that there is work to do + if (orig.empty()) + return; + + // do the spliting + if (orig.size() == numVal) + { + left.assign(orig.begin(), orig.end()); + right.assign(orig.begin(), orig.end()); + } + else if (orig.size() == 2*numVal) + { + left.assign(orig.begin(), orig.begin() + numVal); + right.assign(orig.begin() + numVal, orig.begin()); + } + else + { + std::stringstream msg; + msg << "Input number of " << label << " ids is not equal to " + << "the number of histograms or empty (" + << orig.size() << " != 0 or " << numVal + << " or " << (2*numVal) << ")"; + throw std::runtime_error(msg.str()); + } + } + //---------------------------------------------------------------------------------------------- /** Executes the algorithm * @throw Exception::FileError If the grouping file cannot be opened or read successfully @@ -139,7 +199,7 @@ namespace WorkflowAlgorithms m_offsetsWS = getProperty("OffsetsWorkspace"); m_maskWS = getProperty("MaskWorkspace"); m_groupWS = getProperty("GroupingWorkspace"); - l1 = getProperty("PrimaryFlightPath"); + m_l1 = getProperty("PrimaryFlightPath"); specids = getProperty("SpectrumIDs"); l2s = getProperty("L2"); tths = getProperty("Polar"); @@ -283,6 +343,9 @@ namespace WorkflowAlgorithms } } + // set up a progress bar with the "correct" number of steps + m_progress = new Progress(this, 0., 1., 21); + // filter the input events if appropriate if (m_inputEW) { @@ -299,6 +362,7 @@ namespace WorkflowAlgorithms m_outputW = filterPAlg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } + m_progress->report(); double tolerance = getProperty("CompressTolerance"); if (tolerance > 0.) @@ -318,6 +382,11 @@ namespace WorkflowAlgorithms g_log.information() << "Not compressing event list\n"; doSortEvents(m_outputW); // still sort to help some thing out } + m_progress->report(); + } + else + { + m_progress->reportIncrement(2); } if (xmin > 0. || xmax > 0.) @@ -328,40 +397,62 @@ namespace WorkflowAlgorithms } if (doCorrection) { + double tempmin; + double tempmax; + m_outputW->getXMinMax(tempmin, tempmax); + g_log.information() << "running CropWorkspace(Xmin=" << xmin << ", Xmax=" << xmax << ")\n" ; API::IAlgorithm_sptr cropAlg = createChildAlgorithm("CropWorkspace"); cropAlg->setProperty("InputWorkspace", m_outputW); cropAlg->setProperty("OutputWorkspace", m_outputW); - if (xmin > 0.)cropAlg->setProperty("Xmin", xmin); - if (xmax > 0.)cropAlg->setProperty("Xmax", xmax); + if ((xmin > 0.) && (xmin > tempmin)) + cropAlg->setProperty("Xmin", xmin); + if ((xmax > 0.) && (xmax < tempmax)) + cropAlg->setProperty("Xmax", xmax); cropAlg->executeAsChildAlg(); m_outputW = cropAlg->getProperty("OutputWorkspace"); } } + m_progress->report(); - g_log.information() << "running MaskDetectors\n"; - API::IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); - maskAlg->setProperty("Workspace", m_outputW); - maskAlg->setProperty("MaskedWorkspace", m_maskWS); - maskAlg->executeAsChildAlg(); - m_outputW = maskAlg->getProperty("Workspace"); + if (m_maskWS) + { + g_log.information() << "running MaskDetectors\n"; + API::IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); + maskAlg->setProperty("Workspace", m_outputW); + maskAlg->setProperty("MaskedWorkspace", m_maskWS); + maskAlg->executeAsChildAlg(); + m_outputW = maskAlg->getProperty("Workspace"); + } + m_progress->report(); if(!dspace) m_outputW = rebin(m_outputW); + m_progress->report(); - g_log.information() << "running AlignDetectors\n"; - API::IAlgorithm_sptr alignAlg = createChildAlgorithm("AlignDetectors"); - alignAlg->setProperty("InputWorkspace", m_outputW); - alignAlg->setProperty("OutputWorkspace", m_outputW); - alignAlg->setProperty("OffsetsWorkspace", m_offsetsWS); - alignAlg->executeAsChildAlg(); - m_outputW = alignAlg->getProperty("OutputWorkspace"); + + if (m_offsetsWS) + { + g_log.information() << "running AlignDetectors\n"; + API::IAlgorithm_sptr alignAlg = createChildAlgorithm("AlignDetectors"); + alignAlg->setProperty("InputWorkspace", m_outputW); + alignAlg->setProperty("OutputWorkspace", m_outputW); + alignAlg->setProperty("OffsetsWorkspace", m_offsetsWS); + alignAlg->executeAsChildAlg(); + m_outputW = alignAlg->getProperty("OutputWorkspace"); + } + else + { + m_outputW = convertUnits(m_outputW, "dSpacing"); + } + m_progress->report(); if(LRef > 0. || minwl > 0. || DIFCref > 0.) { m_outputW = convertUnits(m_outputW, "TOF"); } + m_progress->report(); // Beyond this point, low resolution TOF workspace is considered. if(LRef > 0.) @@ -377,6 +468,7 @@ namespace WorkflowAlgorithms removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); } + m_progress->report(); if(minwl > 0.) { @@ -423,6 +515,7 @@ namespace WorkflowAlgorithms if (m_processLowResTOF) m_lowResW = removeAlg->getProperty("LowResTOFWorkspace"); } + m_progress->report(); EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) @@ -437,8 +530,7 @@ namespace WorkflowAlgorithms << "Number of low TOF events = " << numlowevents << ".\n"; } } - - // FIXED - Refactor beyond this point! + m_progress->report(); // Convert units if(LRef > 0. || minwl > 0. || DIFCref > 0.) @@ -447,6 +539,7 @@ namespace WorkflowAlgorithms if (m_processLowResTOF) m_lowResW = convertUnits(m_lowResW, "dSpacing"); } + m_progress->report(); if(dspace) { @@ -454,19 +547,23 @@ namespace WorkflowAlgorithms if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } + m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); + m_progress->report(); // Diffraction focus m_outputW = diffractionFocus(m_outputW); if (m_processLowResTOF) m_lowResW = diffractionFocus(m_lowResW); + m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); + m_progress->report(); // this next call should probably be in for rebin as well // but it changes the system tests @@ -476,103 +573,64 @@ namespace WorkflowAlgorithms if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } + m_progress->report(); - if (l1 > 0) + // edit the instrument geometry + if (m_groupWS && (m_l1 > 0 || !tths.empty() || !l2s.empty() || !phis.empty())) { size_t numreg = m_outputW->getNumberHistograms(); - // Check size - if (tths.size() < numreg) - throw std::runtime_error("Input number of 2thetas is smaller than number of histogram."); - if (l2s.size() < numreg) - throw std::runtime_error("Input number of L2s is smaller than number of histogram."); - if (phis.size() < numreg) - throw std::runtime_error("Input number of azimuthals is smaller than number of histogram."); - - std::vector<int32_t> vec_specid_reg; - if (specids.size() >= numreg) - { - vec_specid_reg.resize(numreg, 0); - std::copy(specids.begin(), (specids.begin()+numreg), vec_specid_reg.begin()); - } - - std::vector<double> vec_polar_reg(numreg, 0.); - std::copy(tths.begin(), (tths.begin()+numreg), vec_polar_reg.begin()); - std::vector<double> vec_l2_reg(numreg, 0.); - std::copy(l2s.begin(), (l2s.begin()+numreg), vec_l2_reg.begin()); - std::vector<double> vec_azimuthal_reg(numreg, 0.); - std::copy(phis.begin(), (phis.begin()+numreg), vec_azimuthal_reg.begin()); + // set up the vectors for doing everything + std::vector<int32_t> specidsReg; + std::vector<int32_t> specidsLow; + splitVectors(specids, numreg, "specids", specidsReg, specidsLow); + std::vector<double> tthsReg; + std::vector<double> tthsLow; + splitVectors(tths, numreg, "two-theta", tthsReg, tthsLow); + std::vector<double> l2sReg; + std::vector<double> l2sLow; + splitVectors(l2s, numreg, "L2", l2sReg, l2sLow); + std::vector<double> phisReg; + std::vector<double> phisLow; + splitVectors(phis, numreg, "phi", phisReg, phisLow); // Edit instrument - m_outputW = editInstrument(m_outputW, vec_polar_reg, vec_specid_reg, vec_l2_reg, vec_azimuthal_reg); + m_outputW = editInstrument(m_outputW, tthsReg, specidsReg, l2sReg, phisReg); if (m_processLowResTOF) { - size_t numlow = m_lowResW->getNumberHistograms(); - // FIXME : There must be some bug in constructing the vectors for EditInstrumentGeometry - - // Check size - size_t numall = numreg+numlow; - g_log.information() << "[DBx931] Num-All = " << numall << ".\n"; - if (tths.size() != numall) - { - std::stringstream errss; - errss << "Input number of 2thetas (" << tths.size() << " is not equal to " - << "the number of normal and low resolution histograms " << numall << ".\n"; - for (size_t i = 0; i < tths.size(); ++i) - { - errss << "2theta[" << i << "] = " << tths[i] << "\n"; - } - g_log.error(errss.str()); - throw std::runtime_error(errss.str()); - } - if (l2s.size() != numall) - throw std::runtime_error("Input number of L2s is not equal to the number of low and high histograms."); - if (phis.size() != numall) - throw std::runtime_error("Input number of azimuthals is not equal to the number of low and high histograms."); - - std::vector<int32_t> vec_specid_low; - if (specids.size() == numall) - { - // vec_specid_low.resize(numlow, 0); - // std::copy((specids.begin()+numreg), specids.end(), vec_specid_low.begin()); - for (size_t i = 0; i < numlow; ++i) - { - vec_specid_low.push_back(specids[numreg+i]); - g_log.information() << i << " : " << vec_specid_low[i] << ".\n"; - } - } - else if (specids.size() == 0) - { - ; - } - else - { - std::stringstream errss; - errss << "SpecIDs has a weird size = " << specids.size() << ", OutputW's size = " << numreg - << ", LowResW's size = " << numlow << ".\n"; - } - - std::vector<double> vec_polar_low, vec_l2_low, vec_azimuthal_low; - for (size_t i = 0; i < numlow; ++i) - { - vec_polar_low.push_back(tths[numreg+i]); - vec_l2_low.push_back(l2s[numreg+i]); - vec_azimuthal_low.push_back(phis[numreg+i]); - } - - m_lowResW = editInstrument(m_lowResW, vec_polar_low, vec_specid_low, vec_l2_low, vec_azimuthal_low); + m_lowResW = editInstrument(m_lowResW, tthsLow, specidsLow, l2sLow, phisLow); } } + m_progress->report(); // Conjoin 2 workspaces if there is low resolution if (m_processLowResTOF) { m_outputW = conjoinWorkspaces(m_outputW, m_lowResW, m_lowResSpecOffset); } + m_progress->report(); // Convert units to TOF m_outputW = convertUnits(m_outputW, "TOF"); + m_progress->report(); + + // compress again if appropriate + double tolerance = getProperty("CompressTolerance"); + m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); + if ((m_outputEW) && (tolerance > 0.)) + { + g_log.information() << "running CompressEvents(Tolerance=" << tolerance << ")\n"; + API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents"); + compressAlg->setProperty("InputWorkspace", m_outputEW); + compressAlg->setProperty("OutputWorkspace", m_outputEW); + compressAlg->setProperty("OutputWorkspace", m_outputEW); + compressAlg->setProperty("Tolerance",tolerance); + compressAlg->executeAsChildAlg(); + m_outputEW = compressAlg->getProperty("OutputWorkspace"); + m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); + } + m_progress->report(); if ((!m_params.empty()) && (m_params.size() != 1)) { @@ -585,6 +643,7 @@ namespace WorkflowAlgorithms m_dmaxs.clear(); m_outputW = rebin(m_outputW); + m_progress->report(); // return the output workspace setProperty("OutputWorkspace",m_outputW); @@ -603,11 +662,16 @@ namespace WorkflowAlgorithms API::IAlgorithm_sptr editAlg = createChildAlgorithm("EditInstrumentGeometry"); editAlg->setProperty("Workspace", ws); - editAlg->setProperty("PrimaryFlightPath", l1); - editAlg->setProperty("Polar", polars); - editAlg->setProperty("SpectrumIDs", specids); - editAlg->setProperty("L2", l2s); - editAlg->setProperty("Azimuthal", phis); + if (m_l1 > 0.) + editAlg->setProperty("PrimaryFlightPath", m_l1); + if (!polars.empty()) + editAlg->setProperty("Polar", polars); + if (!specids.empty()) + editAlg->setProperty("SpectrumIDs", specids); + if (!l2s.empty()) + editAlg->setProperty("L2", l2s); + if (!phis.empty()) + editAlg->setProperty("Azimuthal", phis); editAlg->executeAsChildAlg(); ws = editAlg->getProperty("Workspace"); @@ -620,6 +684,12 @@ namespace WorkflowAlgorithms */ API::MatrixWorkspace_sptr AlignAndFocusPowder::diffractionFocus(API::MatrixWorkspace_sptr ws) { + if (!m_groupWS) + { + g_log.information() << "not focussing data\n"; + return ws; + } + g_log.information() << "running DiffractionFocussing. \n"; API::IAlgorithm_sptr focusAlg = createChildAlgorithm("DiffractionFocussing"); @@ -773,7 +843,7 @@ namespace WorkflowAlgorithms { // check if the workspaces exist with their canonical names so they are not reloaded for chunks - if (!m_groupWS) + if ((!m_groupWS) && (!calFileName.empty())) { try { @@ -783,7 +853,7 @@ namespace WorkflowAlgorithms ; // not noteworthy } } - if (!m_offsetsWS) + if ((!m_offsetsWS) && (!calFileName.empty())) { try { @@ -794,7 +864,7 @@ namespace WorkflowAlgorithms ; // not noteworthy } } - if (!m_maskWS) + if ((!m_maskWS) && (!calFileName.empty())) { try { @@ -810,6 +880,10 @@ namespace WorkflowAlgorithms if (m_groupWS && m_offsetsWS && m_maskWS) return; + // see if the calfile is specified + if (calFileName.empty()) + return; + g_log.information() << "Loading Calibration file \"" << calFileName << "\"\n"; // bunch of booleans to keep track of things diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 01842946d354e2210c8e50368ff325ca1f57ae55..7a32840c7a4ba8e40574f9f67e9e8dac7386ab19 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -9457,13 +9457,6 @@ void ApplicationWindow::dragMoveEvent( QDragMoveEvent* e ) void ApplicationWindow::closeEvent( QCloseEvent* ce ) { - // don't ask the closing sub-windows: the answer will be ignored - MDIWindowList windows = getAllWindows(); - foreach(MdiSubWindow* w,windows) - { - w->confirmClose(false); - } - if(scriptingWindow && scriptingWindow->isExecuting()) { if( ! QMessageBox::question(this, tr("MantidPlot"), "A script is still running, abort and quit application?", tr("Yes"), tr("No")) == 0 ) @@ -9487,6 +9480,14 @@ void ApplicationWindow::closeEvent( QCloseEvent* ce ) } } + // Close all the MDI windows + MDIWindowList windows = getAllWindows(); + foreach(MdiSubWindow* w,windows) + { + w->confirmClose(false); + w->close(); + } + mantidUI->shutdown(); if( scriptingWindow ) diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp index 44ce1b99fccb8e07db98bd42956268d3637c0393..f94b1a6c8d4670d5bec35e8b0770b97032725646 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp @@ -44,25 +44,25 @@ #include <limits> #include <boost/math/special_functions/fpclassify.hpp> - -using namespace Mantid; +//using namespace Mantid; using namespace Mantid::API; using namespace Mantid::Kernel; using namespace MantidQt::API; +using namespace Mantid::Geometry; MantidMatrix::MantidMatrix(Mantid::API::MatrixWorkspace_const_sptr ws, ApplicationWindow* parent, const QString& label, const QString& name, int start, int end) : MdiSubWindow(parent, label, name, 0), - WorkspaceObserver(), - m_appWindow(parent), - m_workspace(ws), - y_start(0.0),y_end(0.0), - m_histogram(false), - m_min(0),m_max(0), - m_are_min_max_set(false), - m_boundingRect(), - m_strName(name.toStdString()), - m_selectedRows(), - m_selectedCols() + WorkspaceObserver(), + m_appWindow(parent), + m_workspace(ws), + y_start(0.0),y_end(0.0), + m_histogram(false), + m_min(0),m_max(0), + m_are_min_max_set(false), + m_boundingRect(), + m_strName(name.toStdString()), + m_selectedRows(), + m_selectedCols() { setup(ws,start,end); setWindowTitle(name); @@ -73,21 +73,21 @@ MantidMatrix::MantidMatrix(Mantid::API::MatrixWorkspace_const_sptr ws, Applicati connectTableView(m_table_viewY,m_modelY); setColumnsWidth(0,MantidPreferences::MantidMatrixColumnWidthY()); setNumberFormat(0,MantidPreferences::MantidMatrixNumberFormatY(), - MantidPreferences::MantidMatrixNumberPrecisionY()); + MantidPreferences::MantidMatrixNumberPrecisionY()); m_modelX = new MantidMatrixModel(this,ws.get(),m_rows,m_cols,m_startRow,MantidMatrixModel::X); m_table_viewX = new QTableView(); connectTableView(m_table_viewX,m_modelX); setColumnsWidth(1,MantidPreferences::MantidMatrixColumnWidthX()); setNumberFormat(1,MantidPreferences::MantidMatrixNumberFormatX(), - MantidPreferences::MantidMatrixNumberPrecisionX()); + MantidPreferences::MantidMatrixNumberPrecisionX()); m_modelE = new MantidMatrixModel(this,ws.get(),m_rows,m_cols,m_startRow,MantidMatrixModel::E); m_table_viewE = new QTableView(); connectTableView(m_table_viewE,m_modelE); setColumnsWidth(2,MantidPreferences::MantidMatrixColumnWidthE()); setNumberFormat(2,MantidPreferences::MantidMatrixNumberFormatE(), - MantidPreferences::MantidMatrixNumberPrecisionE()); + MantidPreferences::MantidMatrixNumberPrecisionE()); m_YTabLabel = QString("Y values"); m_XTabLabel = QString("X values"); @@ -110,7 +110,7 @@ MantidMatrix::MantidMatrix(Mantid::API::MatrixWorkspace_const_sptr ws, Applicati connect(m_tabs,SIGNAL(currentChanged(int)),this,SLOT(viewChanged(int))); setGeometry(50, 50, QMIN(5, numCols())*m_table_viewY->horizontalHeader()->sectionSize(0) + 55, - (QMIN(10,numRows())+1)*m_table_viewY->verticalHeader()->sectionSize(0)+100); + (QMIN(10,numRows())+1)*m_table_viewY->verticalHeader()->sectionSize(0)+100); observeAfterReplace(); observePreDelete(); @@ -136,8 +136,8 @@ bool MantidMatrix::eventFilter(QObject *object, QEvent *e) } /** Called when switching between tabs - * @param index :: The index of the new active tab - */ +* @param index :: The index of the new active tab +*/ void MantidMatrix::viewChanged(int index) { // get the previous view and selection model @@ -235,8 +235,8 @@ QString MantidMatrix::text(int row, int col) } /** Sets new column width in a table view(s). - @param width :: New column width in pixels. All columns have the same width. - @param all :: If true the change will be applied to all three table views. +@param width :: New column width in pixels. All columns have the same width. +@param all :: If true the change will be applied to all three table views. */ void MantidMatrix::setColumnsWidth(int width, bool all) { @@ -274,8 +274,8 @@ void MantidMatrix::setColumnsWidth(int width, bool all) } /** Sets column width to one table view. - @param i :: ordinal number of the view. 0 - Y, 1 - X, 2 - Error - @param width :: New column width in pixels. All columns have the same width. +@param i :: ordinal number of the view. 0 - Y, 1 - X, 2 - Error +@param width :: New column width in pixels. All columns have the same width. */ void MantidMatrix::setColumnsWidth(int i,int width) { @@ -298,8 +298,8 @@ void MantidMatrix::setColumnsWidth(int i,int width) } /** Returns the width of a column. - @param i :: ordinal number of the view. 0 - Y, 1 - X, 2 - Error - @return The column width in pixels. All columns have the same width. +@param i :: ordinal number of the view. 0 - Y, 1 - X, 2 - Error +@return The column width in pixels. All columns have the same width. */ int MantidMatrix::columnsWidth(int i) { @@ -370,11 +370,11 @@ void MantidMatrix::copySelection() } /** Returns minimum and maximum values in the matrix. - If setRange(...) has not been called it returns the true smalles ang largest Y-values in the matrix, - otherwise the values set with setRange(...) are returned. These are needed in plotGraph2D to set - the range of the third, colour axis. - @param[out] min is set to the minumium value - @param[out] max is set to the maximum value +If setRange(...) has not been called it returns the true smalles ang largest Y-values in the matrix, +otherwise the values set with setRange(...) are returned. These are needed in plotGraph2D to set +the range of the third, colour axis. +@param[out] min is set to the minumium value +@param[out] max is set to the maximum value */ void MantidMatrix::range(double *min, double *max) { @@ -403,7 +403,7 @@ double** MantidMatrix::allocateMatrixData(int rows, int columns) double** data = (double **)malloc(rows * sizeof (double*)); if(!data){ QMessageBox::critical(0, tr("MantidPlot") + " - " + tr("Memory Allocation Error"), - tr("Not enough memory, operation aborted!")); + tr("Not enough memory, operation aborted!")); return NULL; } @@ -415,7 +415,7 @@ double** MantidMatrix::allocateMatrixData(int rows, int columns) free(data); QMessageBox::critical(0, tr("MantidPlot") + " - " + tr("Memory Allocation Error"), - tr("Not enough memory, operation aborted!")); + tr("Not enough memory, operation aborted!")); return NULL; } } @@ -616,44 +616,44 @@ Graph3D * MantidMatrix::plotGraph3D(int style) for(int i=0;i<numRows();i++) for(int j=0;j<numCols();j++) { - if (cell(i,j) < zMin) zMin = cell(i,j); - if (cell(i,j) > zMax) zMax = cell(i,j); - } + if (cell(i,j) < zMin) zMin = cell(i,j); + if (cell(i,j) > zMax) zMax = cell(i,j); + } - // Calculate xStart(), xEnd(), yStart(), yEnd() - boundingRect(); - - MantidMatrixFunction *fun = new MantidMatrixFunction(*this); - plot->addFunction(fun, xStart(), xEnd(), yStart(), yEnd(), zMin, zMax, numCols(), numRows() ); + // Calculate xStart(), xEnd(), yStart(), yEnd() + boundingRect(); - const Mantid::API::Axis* ax = m_workspace->getAxis(0); - std::string s; - if ( ax->unit() ) s = ax->unit()->caption() + " / " + ax->unit()->label(); - else - s = "X Axis"; - plot->setXAxisLabel(tr(s.c_str())); + MantidMatrixFunction *fun = new MantidMatrixFunction(*this); + plot->addFunction(fun, xStart(), xEnd(), yStart(), yEnd(), zMin, zMax, numCols(), numRows() ); - if ( m_workspace->axes() > 1 ) - { - ax = m_workspace->getAxis(1); - if (ax->isNumeric()) + const Mantid::API::Axis* ax = m_workspace->getAxis(0); + std::string s; + if ( ax->unit() ) s = ax->unit()->caption() + " / " + ax->unit()->label(); + else + s = "X Axis"; + plot->setXAxisLabel(tr(s.c_str())); + + if ( m_workspace->axes() > 1 ) { - if ( ax->unit() ) s = ax->unit()->caption() + " / " + ax->unit()->label(); + ax = m_workspace->getAxis(1); + if (ax->isNumeric()) + { + if ( ax->unit() ) s = ax->unit()->caption() + " / " + ax->unit()->label(); + else + s = "Y Axis"; + plot->setYAxisLabel(tr(s.c_str())); + } else - s = "Y Axis"; - plot->setYAxisLabel(tr(s.c_str())); + plot->setYAxisLabel(tr("Spectrum")); } - else - plot->setYAxisLabel(tr("Spectrum")); - } - plot->setZAxisLabel(tr(m_workspace->YUnitLabel().c_str())); + plot->setZAxisLabel(tr(m_workspace->YUnitLabel().c_str())); - a->initPlot3D(plot); - //plot->confirmClose(false); - QApplication::restoreOverrideCursor(); + a->initPlot3D(plot); + //plot->confirmClose(false); + QApplication::restoreOverrideCursor(); - return plot; + return plot; } void MantidMatrix::attachMultilayer(MultiLayer* ml) @@ -665,8 +665,8 @@ void MantidMatrix::attachMultilayer(MultiLayer* ml) /** Creates a MultiLayer graph and plots this MantidMatrix as a Spectrogram. - @param type :: The "curve" type. - @return Pointer to the created graph. +@param type :: The "curve" type. +@return Pointer to the created graph. */ MultiLayer* MantidMatrix::plotGraph2D(Graph::CurveType type) { @@ -685,7 +685,7 @@ MultiLayer* MantidMatrix::plotGraph2D(Graph::CurveType type) // a->connectMultilayerPlot(g); Graph* plot = g->activeGraph(); plotSpectrogram(plot,a,type,false,NULL); - // g->confirmClose(false); + // g->confirmClose(false); QApplication::restoreOverrideCursor(); return g; } @@ -781,9 +781,9 @@ const QList<int>& MantidMatrix::getSelectedRows() const } /** - * Sets the internal cache of selected rows. - * @return True if rows are selected, false otherwise - */ +* Sets the internal cache of selected rows. +* @return True if rows are selected, false otherwise +*/ bool MantidMatrix::setSelectedRows() { QTableView *tv = activeView(); @@ -808,15 +808,15 @@ const QList<int>& MantidMatrix::getSelectedColumns() const } /** - * Sets the internal cache of selected columns. - * @return True if columns are selected, false otherwise - */ +* Sets the internal cache of selected columns. +* @return True if columns are selected, false otherwise +*/ bool MantidMatrix::setSelectedColumns() { QTableView *tv = activeView(); QItemSelectionModel *selModel = tv->selectionModel(); if( !selModel || !selModel->hasSelection()) return false; - + m_selectedCols.clear(); const QModelIndexList cols = selModel->selectedColumns(); QModelIndexList::const_iterator it; @@ -848,21 +848,21 @@ void MantidMatrix::dependantClosed(MdiSubWindow* w) if (i >= 0)m_plots2D.remove(i); else {QMap<MultiLayer*,Table*>::iterator i = m_plots1D.find(dynamic_cast<MultiLayer*>(w)); - if (i != m_plots1D.end()) + if (i != m_plots1D.end()) + { + if (i.value() != 0) { - if (i.value() != 0) - { - i.value()->confirmClose(false); - i.value()->close(); - } - m_plots1D.erase(i); + i.value()->confirmClose(false); + i.value()->close(); } + m_plots1D.erase(i); + } } } } /** - Repaints all 1D and 2D plots attached to this MantidMatrix +Repaints all 1D and 2D plots attached to this MantidMatrix */ void MantidMatrix::repaintAll() { @@ -944,7 +944,7 @@ void MantidMatrix::afterReplaceHandle(const std::string& wsName,const boost::sha void MantidMatrix::changeWorkspace(Mantid::API::MatrixWorkspace_sptr ws) { if (m_cols != static_cast<int>(ws->blocksize()) || - m_workspaceTotalHist != static_cast<int>(ws->getNumberHistograms())) + m_workspaceTotalHist != static_cast<int>(ws->getNumberHistograms())) { closeDependants(); } @@ -1126,7 +1126,7 @@ QString MantidMatrix::saveToString(const QString &geometry, bool saveAsTemplate) } /** returns the workspace name - */ +*/ const std::string & MantidMatrix::getWorkspaceName() {return m_strName; } @@ -1134,13 +1134,13 @@ const std::string & MantidMatrix::getWorkspaceName() // ---------- MantidMatrixModel ------------------ // /** MantidMatrixModel constructor. - @param parent :: Pointer to the parent MantidMatrix - @param ws :: Underlying workspace - @param rows :: Number of rows in the workspace to be visible via MantidMatrixModel - @param cols :: Number of columns (time bins) - @param start :: Starting index - @param type :: Type of the data to display: Y, X, or E - */ +@param parent :: Pointer to the parent MantidMatrix +@param ws :: Underlying workspace +@param rows :: Number of rows in the workspace to be visible via MantidMatrixModel +@param cols :: Number of columns (time bins) +@param start :: Starting index +@param type :: Type of the data to display: Y, X, or E +*/ MantidMatrixModel::MantidMatrixModel(QObject *parent, const Mantid::API::MatrixWorkspace* ws, int rows, @@ -1148,7 +1148,7 @@ MantidMatrixModel::MantidMatrixModel(QObject *parent, int start, Type type): QAbstractTableModel(parent),m_type(type), -m_format('e'),m_prec(6) + m_format('e'),m_prec(6) { setup(ws,rows,cols,start); } @@ -1163,6 +1163,7 @@ void MantidMatrixModel::setup(const Mantid::API::MatrixWorkspace* ws, m_rows = rows; m_cols = cols; m_startRow = start >= 0? start : 0; + m_mon_color = QColor(255,255,204); if (ws->blocksize() != 0) m_colNumCorr = ws->isHistogramData() ? 1 : 0; else @@ -1214,10 +1215,10 @@ Qt::ItemFlags MantidMatrixModel::flags(const QModelIndex & index ) const } /** - @param f :: Number format: 'f' - fixed, 'e' - scientific. - @param prec :: New precision (number of digits after the decimal point) with which the data will - be shown in MantidMatrix. - */ +@param f :: Number format: 'f' - fixed, 'e' - scientific. +@param prec :: New precision (number of digits after the decimal point) with which the data will +be shown in MantidMatrix. +*/ void MantidMatrixModel::setFormat(const QChar& f,int prec) { QString formats = " ef"; @@ -1229,27 +1230,84 @@ void MantidMatrixModel::setFormat(const QChar& f,int prec) } QVariant MantidMatrixModel::data(const QModelIndex &index, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + { + double val = data(index.row(),index.column()); + return QVariant(m_locale.toString(val,m_format,m_prec)); + } + case Qt::BackgroundRole: + { + if (checkMontorCache(index.row())) + { + return m_mon_color; + } + else + { + return QVariant(); + } + } + default: + { + return QVariant(); + } + return QVariant(); + } +} + +/** Checks the row cache to see if the detector flag is stored, then returns it, otherwise it looks it up and adds it to the cache for quick lookup +@param row :: current row in the table that maps to a detector. +@return bool :: the value of if the detector is a monitor or not. +*/ +bool MantidMatrixModel::checkMontorCache(int row) const { - if (role != Qt::DisplayRole) return QVariant(); - double val = data(index.row(),index.column()); - return QVariant(m_locale.toString(val,m_format,m_prec)); + bool isMon = false; + if (m_monCache.contains(row)) + { + isMon = m_monCache.value(row); + } + else + { + try + { + size_t wsIndex = static_cast<size_t>(row); + IDetector_const_sptr det = m_workspace->getDetector(wsIndex); + if (det->isMonitor()) + { + isMon = true; + } + else + { + isMon = false; + } + m_monCache.insert(row, isMon); + } + catch (std::exception e) + { + m_monCache.insert(row,false); + isMon = false; + } + } + return isMon; } void findYRange(MatrixWorkspace_const_sptr ws, double &miny, double &maxy) { - //this is here to fill m_min and m_max with numbers that aren't nan - miny = std::numeric_limits<double>::max(); - maxy = -std::numeric_limits<double>::max(); + //this is here to fill m_min and m_max with numbers that aren't nan + miny = std::numeric_limits<double>::max(); + maxy = -std::numeric_limits<double>::max(); - if ( ws ) - { + if ( ws ) + { - PARALLEL_FOR1( ws ) + PARALLEL_FOR1( ws ) for (int wi=0; wi < static_cast<int>(ws->getNumberHistograms()); wi++) { double local_min, local_max; - const MantidVec & Y = ws->readY(wi); + const Mantid::MantidVec & Y = ws->readY(wi); local_min = std::numeric_limits<double>::max(); local_max = -std::numeric_limits<double>::max(); @@ -1277,11 +1335,11 @@ void findYRange(MatrixWorkspace_const_sptr ws, double &miny, double &maxy) miny = local_min; } } - } + } - // Make up some reasonable values if nothing was found - if (miny == std::numeric_limits<double>::max()) - miny = 0; - if (maxy == -std::numeric_limits<double>::max()) - maxy = miny + 1e6; + // Make up some reasonable values if nothing was found + if (miny == std::numeric_limits<double>::max()) + miny = 0; + if (maxy == -std::numeric_limits<double>::max()) + maxy = miny + 1e6; } diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.h b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.h index 995e5e8b6d5bfaa3b116ee7d38033bc8fb800f42..46222bf8b8878ef063e2a2f09a81aee54f4e2d27 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.h +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.h @@ -43,38 +43,38 @@ class UpdateDAEThread; class ProjectData; /** - * Find the minimum and maximum Y values in a matrix workspace. - * - * @param ws :: A matrix workspace. - * @param miny :: Variable to receive the minimum value. - * @param maxy :: Variable to receive the maximum value. - */ +* Find the minimum and maximum Y values in a matrix workspace. +* +* @param ws :: A matrix workspace. +* @param miny :: Variable to receive the minimum value. +* @param maxy :: Variable to receive the maximum value. +*/ void findYRange(Mantid::API::MatrixWorkspace_const_sptr ws, double &miny, double &maxy); /** MantidMatrix is the class that represents a Qtiplot window for displaying workspaces. - It has separate tabs for displaying spectrum values, bin boundaries, and errors. +It has separate tabs for displaying spectrum values, bin boundaries, and errors. - @author Roman Tolchenov, Tessella Support Services plc +@author Roman Tolchenov, Tessella Support Services plc - Copyright © 2007 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory +Copyright © 2007 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - This file is part of Mantid. +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 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. +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/>. +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> +File change history is stored at: <https://github.com/mantidproject/mantid>. +Code Documentation is available at: <http://doxygen.mantidproject.org> */ class MantidMatrix : public MdiSubWindow, MantidQt::API::WorkspaceObserver @@ -159,76 +159,76 @@ signals: void needToClose(); void needsUpdating(); -public slots: - - void changeWorkspace(Mantid::API::MatrixWorkspace_sptr ws); - void closeMatrix(); - - //! Return the width of all columns - int columnsWidth(int i=-1); - //! Set the width of all columns for all views (all==true) or the active view (all==false) - void setColumnsWidth(int width, bool all = true); - // Set the width of column in view i (0 - Y, 1 - X, 2 - E) - void setColumnsWidth(int i, int width); - - //! Return the content of the cell as a string - QString text(int row, int col); - //! Return the value of the cell as a double - double cell(int row, int col); - - //! Returns the X value corresponding to column 1 - double xStart(){return x_start;} - //! Returns the X value corresponding to the last column - double xEnd(){return x_end;} - //! Returns the Y value corresponding to row 1 - double yStart(){return y_start;} - //! Returns the Y value corresponding to the last row - double yEnd(){return y_end;} - - //! Returns the step of the X axis - double dx(){return fabs(x_end - x_start)/(double)(numCols() - 1);} - //! Returns the step of the Y axis - double dy(){return fabs(y_end - y_start)/(double)(numRows() - 1);} - - //! Returns the bounding rect of the matrix coordinates - QwtDoubleRect boundingRect(); - /// Invalidates the bounding rect forcing it to be recalculated - void invalidateBoundingRect(){m_boundingRect = QwtDoubleRect();} - - //! Min and max values in the matrix. - void range(double *min, double *max); - //! Set min and max values in the matrix. - void setRange(double min, double max); - - // Scroll to row and column - void goTo(int row,int col); - //! Scroll to row (row starts with 1) - void goToRow(int row); - //! Scroll to column (column starts with 1) - void goToColumn(int col); - // Set the active tab by name - void goToTab(const QString & name); - - void copySelection(); - - //! Allocate memory for a matrix buffer - static double** allocateMatrixData(int rows, int columns); - //! Free memory used for a matrix buffer - static void freeMatrixData(double **data, int rows); - - int verticalHeaderWidth(){return m_table_viewY->verticalHeader()->width();} - - void dependantClosed(MdiSubWindow* w); - void selfClosed(MdiSubWindow* w); - void repaintAll(); - void closeDependants(); - // for context menu filtering - bool eventFilter(QObject *object, QEvent *e); - //to synchronize the views - void viewChanged(int); - - // Opens modified QtiPlot's MatrixDialog and sets column width and number format - void setMatrixProperties(); + public slots: + + void changeWorkspace(Mantid::API::MatrixWorkspace_sptr ws); + void closeMatrix(); + + //! Return the width of all columns + int columnsWidth(int i=-1); + //! Set the width of all columns for all views (all==true) or the active view (all==false) + void setColumnsWidth(int width, bool all = true); + // Set the width of column in view i (0 - Y, 1 - X, 2 - E) + void setColumnsWidth(int i, int width); + + //! Return the content of the cell as a string + QString text(int row, int col); + //! Return the value of the cell as a double + double cell(int row, int col); + + //! Returns the X value corresponding to column 1 + double xStart(){return x_start;} + //! Returns the X value corresponding to the last column + double xEnd(){return x_end;} + //! Returns the Y value corresponding to row 1 + double yStart(){return y_start;} + //! Returns the Y value corresponding to the last row + double yEnd(){return y_end;} + + //! Returns the step of the X axis + double dx(){return fabs(x_end - x_start)/(double)(numCols() - 1);} + //! Returns the step of the Y axis + double dy(){return fabs(y_end - y_start)/(double)(numRows() - 1);} + + //! Returns the bounding rect of the matrix coordinates + QwtDoubleRect boundingRect(); + /// Invalidates the bounding rect forcing it to be recalculated + void invalidateBoundingRect(){m_boundingRect = QwtDoubleRect();} + + //! Min and max values in the matrix. + void range(double *min, double *max); + //! Set min and max values in the matrix. + void setRange(double min, double max); + + // Scroll to row and column + void goTo(int row,int col); + //! Scroll to row (row starts with 1) + void goToRow(int row); + //! Scroll to column (column starts with 1) + void goToColumn(int col); + // Set the active tab by name + void goToTab(const QString & name); + + void copySelection(); + + //! Allocate memory for a matrix buffer + static double** allocateMatrixData(int rows, int columns); + //! Free memory used for a matrix buffer + static void freeMatrixData(double **data, int rows); + + int verticalHeaderWidth(){return m_table_viewY->verticalHeader()->width();} + + void dependantClosed(MdiSubWindow* w); + void selfClosed(MdiSubWindow* w); + void repaintAll(); + void closeDependants(); + // for context menu filtering + bool eventFilter(QObject *object, QEvent *e); + //to synchronize the views + void viewChanged(int); + + // Opens modified QtiPlot's MatrixDialog and sets column width and number format + void setMatrixProperties(); protected: @@ -246,9 +246,9 @@ protected: QColor m_bk_color; QPixmap m_matrix_icon; double x_start, //!< X value corresponding to column 1 - x_end, //!< X value corresponding to the last column - y_start, //!< Y value corresponding to row 1 - y_end; //!< Y value corresponding to the last row + x_end, //!< X value corresponding to the last column + y_start, //!< Y value corresponding to row 1 + y_end; //!< Y value corresponding to the last row int m_rows,m_cols; int m_startRow; int m_endRow; @@ -294,7 +294,7 @@ class ProjectData { public: ProjectData() : m_grayScale(0),m_intensityChanged(0),m_contourMode(0),m_contourLevels(0), - m_customPen(0),m_contourLabels(0),m_colormapPen(0),m_ContourLinesEditor(0) + m_customPen(0),m_contourLabels(0),m_colormapPen(0),m_ContourLinesEditor(0) {} ~ProjectData(){} bool getGrayScale() const {return m_grayScale;} @@ -332,10 +332,10 @@ private: }; /** - MantidMatrixModel is an implementation of QAbstractTableModel which is an - interface between the data (workspace) and the widget displaying it (QTableView). - It presents spectrum data (Type Y), bin boundaries (Type X), and errors (Type E) - as a table. +MantidMatrixModel is an implementation of QAbstractTableModel which is an +interface between the data (workspace) and the widget displaying it (QTableView). +It presents spectrum data (Type Y), bin boundaries (Type X), and errors (Type E) +as a table. */ class MantidMatrixModel:public QAbstractTableModel { @@ -343,17 +343,17 @@ class MantidMatrixModel:public QAbstractTableModel public: typedef enum {Y,X,E} Type; MantidMatrixModel(QObject *parent, - const Mantid::API::MatrixWorkspace* ws, - int rows, - int cols, - int start, - Type type); + const Mantid::API::MatrixWorkspace* ws, + int rows, + int cols, + int start, + Type type); /// Call this function if the workspace has changed void setup(const Mantid::API::MatrixWorkspace* ws, - int rows, - int cols, - int start); + int rows, + int cols, + int start); /// Implementation of QAbstractTableModel::rowCount() -- number of rows (spectra) that can be shown int rowCount(const QModelIndex &parent = QModelIndex()) const @@ -387,6 +387,8 @@ public slots: /// Signals QTableView that the data have changed. void resetData(){reset();} private: + bool checkMontorCache(int row) const; //check the cache and add to it if neccessary + const Mantid::API::MatrixWorkspace* m_workspace; int m_startRow; ///< starting workspace index to display int m_endRow; ///< ending workspace index to display @@ -396,6 +398,8 @@ private: Type m_type;///< The type: X for bin boundaries, Y for the spectrum data, E for errors char m_format; // Format of numbers returned by data(): 'f' - fixed, 'e' - scientific. int m_prec; // Number precision + QColor m_mon_color; // Monitor Specific background color + mutable QHash<int, bool> m_monCache; //monitor flag cache }; #endif diff --git a/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.cpp b/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.cpp index 470b1d7fe5635e95dc88332d98f66585f60bfed3..8fb459cfd113d654bfee7c5d3b7f55293a714b3f 100644 --- a/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.cpp +++ b/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.cpp @@ -37,7 +37,7 @@ MultiTabScriptInterpreter::MultiTabScriptInterpreter(ScriptingEnv *env, QWidget *parent) : QTabWidget(parent), Scripted(env), m_last_dir(""), m_cursor_pos(), m_reportProgress(false), m_recentScriptList(), m_nullScript(new NullScriptFileInterpreter), - m_current(m_nullScript) + m_current(m_nullScript), m_globalZoomLevel(0) { connect(this, SIGNAL(currentChanged(int)), this, SLOT(tabSelectionChanged(int))); } @@ -85,7 +85,7 @@ bool MultiTabScriptInterpreter::isExecuting() */ void MultiTabScriptInterpreter::newTab(int index, const QString & filename) { - ScriptFileInterpreter *scriptRunner = new ScriptFileInterpreter(this); + ScriptFileInterpreter *scriptRunner = new ScriptFileInterpreter(this,"ScriptWindow"); scriptRunner->setup(*scriptingEnv(), filename); scriptRunner->toggleProgressReporting(m_reportProgress); connect(scriptRunner, SIGNAL(editorModificationChanged(bool)), @@ -94,6 +94,12 @@ void MultiTabScriptInterpreter::newTab(int index, const QString & filename) setCurrentIndex(index); setTabTitle(scriptRunner, filename); // Make sure the tooltip is set scriptRunner->setFocus(); + scriptRunner->editor()->zoomIn(globalZoomLevel()); + connect(scriptRunner->editor(), SIGNAL(textZoomedIn()), this, SLOT(zoomInAllButCurrent())); + connect(scriptRunner->editor(), SIGNAL(textZoomedIn()), this, SLOT(trackZoomIn())); + connect(scriptRunner->editor(), SIGNAL(textZoomedOut()), this, SLOT(zoomOutAllButCurrent())); + connect(scriptRunner->editor(), SIGNAL(textZoomedOut()), this, SLOT(trackZoomOut())); + emit newTabCreated(index); emit tabCountChanged(count()); } @@ -283,17 +289,74 @@ void MultiTabScriptInterpreter::evaluate() QMessageBox::information(this, "MantidPlot", "Evaluate is not implemented."); } -/// Increase font size +/// Tracks the global zoom level +void MultiTabScriptInterpreter::trackZoomIn() +{ + ++m_globalZoomLevel; +} + +/// Tracks the global zoom level +void MultiTabScriptInterpreter::trackZoomOut() +{ + --m_globalZoomLevel; +} + +/// Increase font size on all tabs void MultiTabScriptInterpreter::zoomIn() { - m_current->zoomInOnScript(); + for(int index = 0; index < count(); ++index) + { + interpreterAt(index)->editor()->zoomIn(); + } +} + +/** + * @param skipIndex The tab that should be skipped + */ +void MultiTabScriptInterpreter::zoomInAllButCurrent() +{ + int skipIndex = this->currentIndex(); + for(int i = 0; i < count(); ++i) + { + if(i != skipIndex) interpreterAt(i)->editor()->zoomIn(); + } } -/// Decrease font size + +/// Decrease font size on all tabs void MultiTabScriptInterpreter::zoomOut() { - m_current->zoomOutOnScript(); + for(int i = 0; i < count(); ++i) + { + interpreterAt(i)->editor()->zoomOut(); + } +} + +/** + * @param skipIndex The tab that should be skipped + */ +void MultiTabScriptInterpreter::zoomOutAllButCurrent() +{ + int skipIndex = this->currentIndex(); + for(int i = 0; i < count(); ++i) + { + if(i != skipIndex) interpreterAt(i)->editor()->zoomOut(); + } } +/** + * Resets to zoom on all tabs to default + */ +void MultiTabScriptInterpreter::resetZoom() +{ + m_globalZoomLevel = 0; + for(int i = 0; i < count(); ++i) + { + interpreterAt(i)->editor()->zoomTo(m_globalZoomLevel); + } + +} + + /** * Toggle the progress arrow on/off * @param state :: The state of the option @@ -522,6 +585,7 @@ void MultiTabScriptInterpreter::closeTabAtIndex(int index) { ScriptFileInterpreter *interpreter = interpreterAt(index); interpreter->prepareToClose(); + emit tabClosing(index); removeTab(index); emit tabClosed(index); const int nTabs = count(); diff --git a/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.h b/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.h index 84efa11ace8dd170166811a75a6e5dea0a0f74ba..81331f86799628ff77d7590b558c1145fc5830ff 100644 --- a/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.h +++ b/Code/Mantid/MantidPlot/src/MultiTabScriptInterpreter.h @@ -72,6 +72,9 @@ public: /// Is a script running in the environment bool isExecuting(); + /// Returns the global zoom level + int globalZoomLevel() const { return m_globalZoomLevel; } + /// this method appends the file names of scripts ///in different tabs to a string and returns QString saveToString(); @@ -85,6 +88,8 @@ public: signals: /// Signal that a tab has been created void newTabCreated(int); + /// Signal that a tab is about to close, parametrised by the index + void tabClosing(int); /// Signal that a tab has closed, parametrised by the index void tabClosed(int); /// Signal that the last tab has closed @@ -140,10 +145,21 @@ public slots: /// Evaluate void evaluate(); + /// Tracks the global zoom level + void trackZoomIn(); + /// Tracks the global zoom level + void trackZoomOut(); + /// Increase font size void zoomIn(); + /// Increase font size on all tabs except that given + void zoomInAllButCurrent(); /// Decrease font size void zoomOut(); + /// Decrease font size on all tabs except that given + void zoomOutAllButCurrent(); + /// Resets the zoom level + void resetZoom(); /// Toggle the progress reporting arrow void toggleProgressReporting(bool on); @@ -199,6 +215,8 @@ private: NullScriptFileInterpreter *m_nullScript; /// A pointer to the current interpreter ScriptFileInterpreter *m_current; + /// Store the current global zoom level + int m_globalZoomLevel; }; #endif diff --git a/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.cpp b/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.cpp index 4b3e7fc3d3d515a173a35a22acac04bb0eb34cff..70a3659d0d66a5cac4eb0c8d03efb5ad652a18d1 100644 --- a/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.cpp +++ b/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.cpp @@ -16,9 +16,9 @@ * Construct a widget * @param parent :: The parent widget */ -ScriptFileInterpreter::ScriptFileInterpreter(QWidget *parent) +ScriptFileInterpreter::ScriptFileInterpreter(QWidget *parent, const QString & settingsGroup) : QWidget(parent), m_splitter(new QSplitter(Qt::Vertical,this)), - m_editor(new ScriptEditor(this, NULL)), + m_editor(new ScriptEditor(this, NULL,settingsGroup)), m_messages(new ScriptOutputDisplay), m_status(new QStatusBar), m_runner() { @@ -249,17 +249,6 @@ void ScriptFileInterpreter::executeSelection(const Script::ExecutionMode mode) } } -/// Zoom in on script -void ScriptFileInterpreter::zoomInOnScript() -{ - m_editor->zoomIn(); -} -/// Zoom out on script -void ScriptFileInterpreter::zoomOutOnScript() -{ - m_editor->zoomOut(); -} - /// Toggles the progress reports on/off void ScriptFileInterpreter::toggleProgressReporting(bool state) { @@ -316,6 +305,7 @@ void ScriptFileInterpreter::setupEditor(const ScriptingEnv & environ, const QStr readFileIntoEditor(identifier); } m_editor->setLexer(environ.createCodeLexer()); + m_editor->setSettingsGroup("ScriptWindow"); m_editor->padMargin(); m_editor->setAutoMarginResize(); m_editor->enableAutoCompletion(); diff --git a/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.h b/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.h index 530dfbcd8e19ee6597ec808be176499d4edb3f40..29734a6f694553edaddd7781496de251af7fa946 100644 --- a/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.h +++ b/Code/Mantid/MantidPlot/src/ScriptFileInterpreter.h @@ -28,7 +28,7 @@ class ScriptFileInterpreter : public QWidget public: /// Construct the object - ScriptFileInterpreter(QWidget *parent = NULL); + ScriptFileInterpreter(QWidget *parent = NULL, const QString & settingsGroup = ""); /// Destroy the object ~ScriptFileInterpreter(); /// Make sure we are in a safe state to delete the widget @@ -38,6 +38,8 @@ public: /// Return the filename of the script in the editor virtual QString filename() const; + /// + inline ScriptEditor *editor() const { return m_editor; } /// Has the script text been modified virtual bool isScriptModified() const; /// Is the script running @@ -75,10 +77,6 @@ public slots: /// Execute the current selection virtual void executeSelection(const Script::ExecutionMode mode = Script::Asynchronous); - /// Zoom in on script - virtual void zoomInOnScript(); - /// Zoom out on script - virtual void zoomOutOnScript(); /// Toggles the progress reports on/off virtual void toggleProgressReporting(bool state); /// Toggles the code folding on/off diff --git a/Code/Mantid/MantidPlot/src/ScriptingWindow.cpp b/Code/Mantid/MantidPlot/src/ScriptingWindow.cpp index 62203101b8a3744bef8a167ac1ef2734a2375f10..3b7ee4addd5f17ffbf3714fa4dea5c049f37295e 100755 --- a/Code/Mantid/MantidPlot/src/ScriptingWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ScriptingWindow.cpp @@ -4,11 +4,16 @@ #include "ScriptingWindow.h" #include "MultiTabScriptInterpreter.h" #include "ScriptingEnv.h" +#include "ScriptFileInterpreter.h" #include "pixmaps.h" // Mantid #include "MantidKernel/ConfigService.h" #include "ApplicationWindow.h" + +// MantidQt +#include "MantidQtMantidWidgets/ScriptEditor.h" + //Qt #include <QTextEdit> #include <QMenuBar> @@ -82,6 +87,7 @@ void ScriptingWindow::saveSettings() settings.setValue("/ProgressArrow", m_toggleProgress->isChecked()); settings.setValue("/LastDirectoryVisited", m_manager->m_last_dir); settings.setValue("/RecentScripts",m_manager->recentScripts()); + settings.setValue("/ZoomLevel",m_manager->globalZoomLevel()); settings.endGroup(); } @@ -100,8 +106,9 @@ void ScriptingWindow::readSettings() } m_manager->m_last_dir = lastdir; m_toggleProgress->setChecked(settings.value("ProgressArrow", true).toBool()); - m_manager->setRecentScripts(settings.value("/RecentScripts").toStringList()); + m_manager->m_globalZoomLevel = settings.value("ZoomLevel",0).toInt(); + settings.endGroup(); } @@ -249,6 +256,7 @@ void ScriptingWindow::populateWindowMenu() m_windowMenu->insertSeparator(); m_windowMenu->addAction(m_zoomIn); m_windowMenu->addAction(m_zoomOut); + m_windowMenu->addAction(m_resetZoom); m_windowMenu->insertSeparator(); m_windowMenu->addAction(m_toggleProgress); @@ -525,17 +533,22 @@ void ScriptingWindow::initWindowMenuActions() // Note that we channel the hide through the parent so that we can save the geometry state connect(m_hide, SIGNAL(triggered()), this, SIGNAL(hideMe())); - m_zoomIn = new QAction(("Increase font size"), this); + m_zoomIn = new QAction(("&Increase font size"), this); // Setting two shortcuts makes it work for both the plus on the keypad and one above an = // Despite the Qt docs advertising the use of QKeySequence::ZoomIn as the solution to this, // it doesn't seem to work for me m_zoomIn->setShortcut(Qt::SHIFT+Qt::CTRL+Qt::Key_Equal); m_zoomIn->setShortcut(Qt::CTRL+Qt::Key_Plus); connect(m_zoomIn, SIGNAL(triggered()), m_manager, SLOT(zoomIn())); + connect(m_zoomIn, SIGNAL(triggered()), m_manager, SLOT(trackZoomIn())); - m_zoomOut = new QAction(("Decrease font size"), this); + m_zoomOut = new QAction(("&Decrease font size"), this); m_zoomOut->setShortcut(QKeySequence::ZoomOut); connect(m_zoomOut, SIGNAL(triggered()), m_manager, SLOT(zoomOut())); + connect(m_zoomOut, SIGNAL(triggered()), m_manager, SLOT(trackZoomOut())); + + m_resetZoom = new QAction(("&Reset font size"), this); + connect(m_resetZoom, SIGNAL(triggered()), m_manager, SLOT(resetZoom())); // Toggle the progress arrow m_toggleProgress = new QAction(tr("&Progress Reporting"), this); diff --git a/Code/Mantid/MantidPlot/src/ScriptingWindow.h b/Code/Mantid/MantidPlot/src/ScriptingWindow.h index fb28557804aabe1fe23ad0a7234b173b596b5e41..e666d753ce1a8de78ae567c0a1bf0555cba43379 100755 --- a/Code/Mantid/MantidPlot/src/ScriptingWindow.h +++ b/Code/Mantid/MantidPlot/src/ScriptingWindow.h @@ -108,6 +108,7 @@ private: void initExecMenuActions(); /// Create the window menu actions void initWindowMenuActions(); + /// Returns the current execution mode Script::ExecutionMode getExecutionMode() const; @@ -142,9 +143,8 @@ private: /// Window menu QMenu *m_windowMenu; /// Window actions - QAction *m_alwaysOnTop, *m_hide, *m_zoomIn, *m_zoomOut, + QAction *m_alwaysOnTop, *m_hide, *m_zoomIn, *m_zoomOut, *m_resetZoom, *m_toggleProgress, *m_toggleFolding; - /// Change scripting language QAction *m_scripting_lang; /// Flag to define whether we should accept a close event diff --git a/Code/Mantid/MantidQt/API/src/OptionsPropertyWidget.cpp b/Code/Mantid/MantidQt/API/src/OptionsPropertyWidget.cpp index e113c03674dc03f84e4b4f70d01287449c159bc4..b470fbccebe75c110e16096fe2b705163fc4c2c8 100644 --- a/Code/Mantid/MantidQt/API/src/OptionsPropertyWidget.cpp +++ b/Code/Mantid/MantidQt/API/src/OptionsPropertyWidget.cpp @@ -39,7 +39,6 @@ namespace API //output box and used the saved combo box m_combo = new QComboBox(this); m_combo->setToolTip(m_doc); - connect(m_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(valueChangedSlot())); m_widgets.push_back(m_combo); std::set<std::string> items = prop->allowedValues(); @@ -47,10 +46,14 @@ namespace API { m_combo->addItem(QString::fromStdString(*vitr)); } + // Make current value visible + this->setValue(QString::fromStdString(m_prop->value())); + + // Make sure the connection comes after updating any values + connect(m_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(valueChangedSlot())); // Put the combo in column 1 m_gridLayout->addWidget(m_combo, m_row, 1, 0); - } //---------------------------------------------------------------------------------------------- diff --git a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h index 6eab22afd7770f4a3afab2a3eedb12ed3e00b8d8..26e3cf8df6a373fcb6d751e680356396b24735fd 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h +++ b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h @@ -102,6 +102,8 @@ namespace MantidQt QString m_currentFiles; /// The initial height int m_initialHeight; + /// Flag to indicating if we are populating the dialog + bool m_populating; }; } diff --git a/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp b/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp index 185386d6d818d3710219c30e52b3ae85789d6fde..c0b02f20a66b7be3cb82980c9a690de6726f387b 100644 --- a/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp +++ b/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp @@ -24,6 +24,22 @@ namespace MantidQt { namespace CustomDialogs { + namespace + { + /// Holds a flag at a given value + /// and flips it back to its starting value on destruction + struct HoldFlag + { + HoldFlag(bool& current, const bool holdValue) : initial(current), heldflag(current) + { + heldflag = holdValue; + } + ~HoldFlag() { heldflag = initial; } + bool initial; + bool & heldflag; + }; + } + // Declare the dialog. Name must match the class name DECLARE_DIALOG(LoadDialog); @@ -33,7 +49,8 @@ namespace MantidQt /// Default constructor LoadDialog:: LoadDialog(QWidget *parent) - : API::AlgorithmDialog(parent), m_form(), m_currentFiles(), m_initialHeight(0) + : API::AlgorithmDialog(parent), m_form(), m_currentFiles(), m_initialHeight(0), + m_populating(false) { // We will handle parsing the input ourselves on startup m_autoParseOnInit = false; @@ -48,6 +65,8 @@ namespace MantidQt */ void LoadDialog::createDynamicWidgets() { + HoldFlag hold(m_populating, true); + m_form.fileWidget->blockSignals(true); createDynamicLayout(); m_form.fileWidget->blockSignals(false); @@ -95,10 +114,20 @@ namespace MantidQt } /** - * Protection against removing the file while the dialog is up. + * Called when the run button is clicked */ void LoadDialog::accept() { + // The file widget may have been edited but not lost focus so that the search wasn't + // attempted for the new contents. Force one here. + // The widget does nothing if the contents have not changed so it will be quick for this case + m_form.fileWidget->findFiles(); + while(m_form.fileWidget->isSearching() || m_populating) + { + QApplication::instance()->processEvents(); + } + + // Check that the file still exists just incase it somehow got removed std::string errMess = getAlgorithm()->getPointerToProperty("Filename")->isValid(); if ( !errMess.empty() ) { @@ -311,6 +340,10 @@ namespace MantidQt { optionsBox->addItem(QString::fromStdString(*vitr)); } + // Set current as visible + int index = optionsBox->findText(QString::fromStdString(prop->value())); + if( index >= 0 ) optionsBox->setCurrentIndex(index); + addValidator = false; } // else render a text box diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp index 3e9445270de686a5defc947eec9387faa6e17170..2fde48b55b27556fe3354d792aa04db69c9664b8 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Indirect.cpp @@ -344,6 +344,24 @@ void Indirect::runConvertToEnergy() break; } + // add sample logs to each of the workspaces + QString calibChecked = m_uiForm.ckUseCalib->isChecked() ? "True" : "False"; + QString detailedBalance = m_uiForm.ckDetailedBalance->isChecked() ? "True" : "False"; + QString scaled = m_uiForm.ckScaleMultiplier->isChecked() ? "True" : "False"; + pyInput += "calibCheck = "+calibChecked+"\n" + "detailedBalance = "+detailedBalance+"\n" + "scaled = "+scaled+"\n" + "for ws in ws_list:\n" + " AddSampleLog(Workspace=ws, LogName='calib_file', LogType='String', LogText=str(calibCheck))\n" + " if calibCheck:\n" + " AddSampleLog(Workspace=ws, LogName='calib_file_name', LogType='String', LogText='"+m_uiForm.ind_calibFile->getFirstFilename()+"')\n" + " AddSampleLog(Workspace=ws, LogName='detailed_balance', LogType='String', LogText=str(detailedBalance))\n" + " if detailedBalance:\n" + " AddSampleLog(Workspace=ws, LogName='detailed_balance_temp', LogType='Number', LogText='"+m_uiForm.leDetailedBalance->text()+"')\n" + " AddSampleLog(Workspace=ws, LogName='scale', LogType='String', LogText=str(scaled))\n" + " if scaled:\n" + " AddSampleLog(Workspace=ws, LogName='scale_factor', LogType='Number', LogText='"+m_uiForm.leScaleMultiplier->text()+"')\n"; + QString pyOutput = runPythonCode(pyInput).trimmed(); } @@ -1714,13 +1732,16 @@ void Indirect::sOfQwClicked() "efixed = " + m_uiForm.leEfixed->text() + "\n" "rebin = '" + rebinString + "'\n"; - if(m_uiForm.sqw_cbRebinType->currentText() == "Centre (SofQW)") + QString rebinType = m_uiForm.sqw_cbRebinType->currentText(); + if(rebinType == "Centre (SofQW)") pyInput += "SofQW(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; - else if(m_uiForm.sqw_cbRebinType->currentText() == "Parallelepiped (SofQW2)") + else if(rebinType == "Parallelepiped (SofQW2)") pyInput += "SofQW2(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; - else if(m_uiForm.sqw_cbRebinType->currentText() == "Parallelepiped/Fractional Area (SofQW3)") + else if(rebinType == "Parallelepiped/Fractional Area (SofQW3)") pyInput += "SofQW3(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; + pyInput += "AddSampleLog(Workspace=sqwOutput, LogName='rebin_type', LogType='String', LogText='"+rebinType+"')\n"; + if ( m_uiForm.sqw_ckSave->isChecked() ) { pyInput += "SaveNexus(InputWorkspace=sqwOutput, Filename=sqwOutput+'.nxs')\n"; @@ -1792,8 +1813,8 @@ void Indirect::sOfQwPlotInput() pyInput += "input = '" + m_uiForm.sqw_cbWorkspace->currentText() + "'\n"; } - pyInput += "ConvertSpectrumAxis(InputWorkspace=input, OutputWorkspace=input+'_q', Target='ElasticQ', EMode='Indirect')\n" - "ws = importMatrixWorkspace(input+'_q')\n" + pyInput += "ConvertSpectrumAxis(InputWorkspace=input, OutputWorkspace=input[:-4]+'_rqw', Target='ElasticQ', EMode='Indirect')\n" + "ws = importMatrixWorkspace(input[:-4]+'_rqw')\n" "ws.plotGraph2D()\n"; QString pyOutput = runPythonCode(pyInput).trimmed(); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp index aa70edcf5b23b1fe3556934d70bef886f0d0fd34..cbeef3a91c8734aadbcdf138871dfbe57298d07b 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp @@ -3366,6 +3366,10 @@ void MuonAnalysis::loadAutoSavedValues(const QString& group) int deadTimeTypeIndex = deadTimeOptions.value("deadTimes", 0).toInt(); m_uiForm.deadTimeType->setCurrentIndex(deadTimeTypeIndex); + + QString savedDeadTimeFile = deadTimeOptions.value("deadTimeFile").toString(); + m_uiForm.mwRunDeadTimeFile->setUserInput(savedDeadTimeFile); + if (deadTimeTypeIndex != 2) m_uiForm.mwRunDeadTimeFile->setVisible(false); } @@ -3858,6 +3862,7 @@ void MuonAnalysis::setToolbarsHidden(bool hidden) void MuonAnalysis::changeDeadTimeType(int choice) { m_deadTimesChanged = true; + if (choice == 0 || choice == 1) // if choice == none || choice == from file { m_uiForm.mwRunDeadTimeFile->setVisible(false); @@ -3865,8 +3870,8 @@ void MuonAnalysis::changeDeadTimeType(int choice) } else // choice must be from workspace { - m_uiForm.mwRunDeadTimeFile->setText(""); m_uiForm.mwRunDeadTimeFile->setVisible(true); + m_uiForm.mwRunDeadTimeFile->setUserInput(""); } QSettings group; @@ -3882,6 +3887,14 @@ void MuonAnalysis::changeDeadTimeType(int choice) */ void MuonAnalysis::deadTimeFileSelected() { + if(!m_uiForm.mwRunDeadTimeFile->isValid()) + return; + + // Remember the filename for the next time interface is opened + QSettings group; + group.beginGroup(m_settingsGroup + "DeadTimeOptions"); + group.setValue("deadTimeFile", m_uiForm.mwRunDeadTimeFile->getText()); + m_deadTimesChanged = true; homeTabUpdatePlot(); } diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h index 83e8415631627bdfbeda52bac6a700a77cf30f7b..b0d879d3c54960cd9ca70e61883b68b8daad3488 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h @@ -166,6 +166,7 @@ namespace MantidQt QString getText() const; bool isValid() const; + bool isSearching() const; QStringList getFilenames() const; QString getFirstFilename() const; int getEntryNum() const; diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/ScriptEditor.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/ScriptEditor.h index 23ea3e14705283415959ce8a71b07036a0f3a63c..4f9e87e560309e631f87055d367b4eb12465659c 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/ScriptEditor.h +++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/ScriptEditor.h @@ -97,11 +97,21 @@ public: public: /// Constructor - ScriptEditor(QWidget* parent = 0, QsciLexer* lexer = NULL); + ScriptEditor(QWidget* parent = 0, QsciLexer* lexer = NULL, + const QString & settingsGroup = ""); ///Destructor ~ScriptEditor(); - // Set a new code lexer for this object + /// Set the name of the group to save the settings for + void setSettingsGroup(const QString & name); + /// Settings group + QString settingsGroup() const; + /// Read settings from persistent store + void readSettings(); + /// Write settings from persistent store + void writeSettings(); + + /// Set a new code lexer for this object void setLexer(QsciLexer *); // Make the object resize to margin to fit the contents void setAutoMarginResize(); @@ -165,20 +175,18 @@ public slots: /// Raise find replace dialog virtual void showFindReplaceDialog(); - /// Override the zoomIn slot - virtual void zoomIn(); - /// Override the zoomIn slot - virtual void zoomIn(int level); - /// Override the zoomOut slot - virtual void zoomOut(); - /// Override the zoomOut slot - virtual void zoomOut(int level); + /// Override zoomTo slot + virtual void zoomTo(int level); signals: /// Inform observers that undo information is available void undoAvailable(bool); /// Inform observers that redo information is available void redoAvailable(bool); + /// Emitted when a zoom in is requested + void textZoomedIn(); + /// Emitted when a zoom in is requested + void textZoomedOut(); protected: /// Write to the given device @@ -187,12 +195,6 @@ protected: private slots: private: - /// Settings group - QString settingsGroup() const; - /// Read settings from persistent store - void readSettings(); - /// Write settings from persistent store - void writeSettings(); /// Forward a KeyPress event to QsciScintilla base class. Necessary due to bug in QsciScintilla void forwardKeyPressToBase(QKeyEvent *event); @@ -211,10 +213,10 @@ private: static QColor g_error_colour; /// previous key int m_previousKey; - /// How many times the zoom level is changed - int m_zoomLevel; /// A pointer to the find replace dialog FindReplaceDialog *m_findDialog; + /// Name of group that the settings are stored under + QString m_settingsGroup; }; diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp index 185919ae15e55cbda9fdba0929ce366ed85b42e4..87157889de71df10c2410ed464e4a4397ceda8a9 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp @@ -73,6 +73,8 @@ void FindFilesThread::run() // Reset result member vars. m_error.clear(); m_filenames.clear(); + m_valueForProperty.clear(); + if( m_text.empty() ) { if( m_isOptional ) @@ -87,7 +89,6 @@ void FindFilesThread::run() try { - m_valueForProperty = ""; // Use the property of the algorithm to find files, if one has been specified. if( m_algorithm.length() != 0 && m_property.length() != 0 ) { @@ -494,6 +495,16 @@ bool MWRunFiles::isValid() const } } +/** + * Is the widget currently searching + * @return True if a search is inprogress + */ +bool MWRunFiles::isSearching() const +{ + return (m_thread ? m_thread->isRunning() : false); +} + + /** * Returns the names of the files found * @return an array of filenames entered in the box diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/ScriptEditor.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/ScriptEditor.cpp index f28838e039a57ccda54edc06d354913087a868aa..5ca25a683813589308d419a5c364392027105e0d 100644 --- a/Code/Mantid/MantidQt/MantidWidgets/src/ScriptEditor.cpp +++ b/Code/Mantid/MantidQt/MantidWidgets/src/ScriptEditor.cpp @@ -138,22 +138,17 @@ QColor ScriptEditor::g_error_colour = QColor("red"); * Constructor * @param parent :: The parent widget (can be NULL) * @param codelexer :: define the syntax highlighting and code completion. + * @param settingsGroup :: Used when saving settings to persistent store */ -ScriptEditor::ScriptEditor(QWidget *parent, QsciLexer *codelexer) : +ScriptEditor::ScriptEditor(QWidget *parent, QsciLexer *codelexer, const QString & settingsGroup) : QsciScintilla(parent), m_filename(""), m_progressArrowKey(markerDefine(QsciScintilla::RightArrow)), - m_currentExecLine(0), m_completer(NULL),m_previousKey(0), m_zoomLevel(0), - m_findDialog(new FindReplaceDialog(this)) + m_currentExecLine(0), m_completer(NULL),m_previousKey(0), + m_findDialog(new FindReplaceDialog(this)), m_settingsGroup(settingsGroup) { //Syntax highlighting and code completion setLexer(codelexer); readSettings(); -#ifdef __APPLE__ - // Make all fonts 4 points bigger on the Mac because otherwise they're tiny! - if( m_zoomLevel == 0 ) m_zoomLevel = 4; -#endif - - zoomIn(m_zoomLevel); setMarginLineNumbers(1,true); //Editor properties @@ -169,7 +164,6 @@ ScriptEditor::ScriptEditor(QWidget *parent, QsciLexer *codelexer) : */ ScriptEditor::~ScriptEditor() { - writeSettings(); if( m_completer ) { delete m_completer; @@ -180,6 +174,39 @@ ScriptEditor::~ScriptEditor() } } +/** + * @param name The name of the group + */ +void ScriptEditor::setSettingsGroup(const QString & name) +{ + m_settingsGroup = name; +} + +/// Settings group +/** + * Returns a string containing the settings group to use + * @return A QString containing the group to use within the QSettings class + */ +QString ScriptEditor::settingsGroup() const +{ + return m_settingsGroup; +} + +/** + * Read settings saved to persistent store + */ +void ScriptEditor::readSettings() +{ +} + +/** + * Read settings saved to persistent store + */ +void ScriptEditor::writeSettings() +{ +} + + /** * Set a new code lexer for this object. Note that this clears all auto complete information */ @@ -345,10 +372,12 @@ void ScriptEditor::wheelEvent( QWheelEvent * e ) if ( e->delta() > 0 ) { zoomIn(); + emit textZoomedIn(); // allows tracking } else { zoomOut(); + emit textZoomedOut(); //allows tracking } } else @@ -481,41 +510,16 @@ void ScriptEditor::showFindReplaceDialog() } /** - * Override the zoomIn slot to keep a count of the level - */ -void ScriptEditor::zoomIn() -{ - ++m_zoomLevel; - QsciScintilla::zoomIn(); -} - -/** - * Override the zoomIn slot to keep a count of the level - * @param level Increase font size by this many points - */ -void ScriptEditor::zoomIn(int level) -{ - m_zoomLevel = level; - QsciScintilla::zoomIn(level); -} - -/** - * Override the zoomIn slot to keep a count of the level + * Override the zoomTo slot to make the font size larger on Mac as the defaults are tiny + * @param level Set the font size to this level of zoom */ - -void ScriptEditor::zoomOut() +void ScriptEditor::zoomTo(int level) { - --m_zoomLevel; - QsciScintilla::zoomOut(); -} -/** - * Override the zoomIn slot to keep a count of the level - * @param level Decrease font size by this many points - */ -void ScriptEditor::zoomOut(int level) -{ - m_zoomLevel = -level; - QsciScintilla::zoomOut(level); +#ifdef __APPLE__ + // Make all fonts 4 points bigger on the Mac because otherwise they're tiny! + level += 4; +#endif + QsciScintilla::zoomTo(level); } /** @@ -530,38 +534,6 @@ void ScriptEditor::writeToDevice(QIODevice & device) const // Private member functions //------------------------------------------------ -/// Settings group -/** - * Returns a string containing the settings group to use - * @return A QString containing the group to use within the QSettings class - */ -QString ScriptEditor::settingsGroup() const -{ - return "/ScriptWindow"; -} - -/** - * Read settings saved to persistent store - */ -void ScriptEditor::readSettings() -{ - QSettings settings; - settings.beginGroup(settingsGroup()); - m_zoomLevel = settings.readNumEntry("ZoomLevel", 0); - settings.endGroup(); -} - -/** - * Read settings saved to persistent store - */ -void ScriptEditor::writeSettings() -{ - QSettings settings; - settings.beginGroup(settingsGroup()); - settings.setValue("ZoomLevel", m_zoomLevel); - settings.endGroup(); -} - /** * Forward the QKeyEvent to the QsciScintilla base class. * Under Gnome on Linux with Qscintilla versions < 2.4.2 there is a bug with the autocomplete diff --git a/Code/Mantid/MantidQt/SliceViewer/inc/MantidQtSliceViewer/PeakOverlayMultiSphereFactory.h b/Code/Mantid/MantidQt/SliceViewer/inc/MantidQtSliceViewer/PeakOverlayMultiSphereFactory.h index e975c3ad9101f1480870f19f8e58eab5e4651b06..d488cc8d43f882583c4410e3c8cce485bcd35933 100644 --- a/Code/Mantid/MantidQt/SliceViewer/inc/MantidQtSliceViewer/PeakOverlayMultiSphereFactory.h +++ b/Code/Mantid/MantidQt/SliceViewer/inc/MantidQtSliceViewer/PeakOverlayMultiSphereFactory.h @@ -36,9 +36,9 @@ namespace MantidQt class DLLExport PeakOverlayMultiSphereFactory : public PeakOverlayViewFactoryBase { private: - double m_peakRadius; - double m_backgroundInnerRadius; - double m_backgroundOuterRadius; + std::vector<double> m_peakRadius; + std::vector<double> m_backgroundInnerRadius; + std::vector<double> m_backgroundOuterRadius; Mantid::API::IPeaksWorkspace_sptr m_peaksWS; int m_FOM; public: diff --git a/Code/Mantid/MantidQt/SliceViewer/src/PeakOverlayMultiSphereFactory.cpp b/Code/Mantid/MantidQt/SliceViewer/src/PeakOverlayMultiSphereFactory.cpp index 78951920f826d775cfc44a6ab345c00c764d969b..22e8c5eb9d14a2a0e09268dfaeffc69acb651319 100644 --- a/Code/Mantid/MantidQt/SliceViewer/src/PeakOverlayMultiSphereFactory.cpp +++ b/Code/Mantid/MantidQt/SliceViewer/src/PeakOverlayMultiSphereFactory.cpp @@ -19,12 +19,29 @@ namespace MantidQt { if (m_peaksWS->hasIntegratedPeaks()) { - m_peakRadius = boost::lexical_cast<double>( - m_peaksWS->run().getProperty("PeakRadius")->value()); - m_backgroundInnerRadius = boost::lexical_cast<double>( - m_peaksWS->run().getProperty("BackgroundInnerRadius")->value()); - m_backgroundOuterRadius = boost::lexical_cast<double>( - m_peaksWS->run().getProperty("BackgroundOuterRadius")->value()); + try + { + m_peakRadius = + m_peaksWS->run().getPropertyValueAsType<std::vector<double> >("PeakRadius"); + m_backgroundInnerRadius = + m_peaksWS->run().getPropertyValueAsType<std::vector<double> >("BackgroundInnerRadius"); + m_backgroundOuterRadius = + m_peaksWS->run().getPropertyValueAsType<std::vector<double> >("BackgroundOuterRadius"); + } + catch (...) + { + double m_peakRadius0 = m_peaksWS->run().getPropertyValueAsType<double>("PeakRadius"); + double m_backgroundInnerRadius0 = + m_peaksWS->run().getPropertyValueAsType<double>("BackgroundInnerRadius"); + double m_backgroundOuterRadius0 = + m_peaksWS->run().getPropertyValueAsType<double>("BackgroundOuterRadius"); + for(size_t i = 0; i < m_peaksWS->rowCount(); ++i) + { + m_peakRadius.push_back(m_peakRadius0); + m_backgroundInnerRadius.push_back(m_backgroundInnerRadius0); + m_backgroundOuterRadius.push_back(m_backgroundOuterRadius0); + } + } m_FOM = 2; // Possible to display workspaces with this factory. } } @@ -37,7 +54,7 @@ namespace MantidQt { const IPeak& peak = m_peaksWS->getPeak(static_cast<int>(i)); auto position = transform->transformPeak(peak); - physicalPeaks[i] = boost::make_shared<PhysicalSphericalPeak>(position, m_peakRadius, m_backgroundInnerRadius, m_backgroundOuterRadius); + physicalPeaks[i] = boost::make_shared<PhysicalSphericalPeak>(position, m_peakRadius[i], m_backgroundInnerRadius[i], m_backgroundOuterRadius[i]); } // Make the overlay widget. diff --git a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.cxx b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.cxx index 66903d7bd10234b641b91d4ade3296d524b7f5be..a01d2f64f77843f152bb99fcc4163806f317113d 100644 --- a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.cxx +++ b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.cxx @@ -2,6 +2,7 @@ #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" #include "vtkUnstructuredGridAlgorithm.h" #include "vtkUnstructuredGrid.h" @@ -75,6 +76,14 @@ void vtkSplatterPlot::SetTopPercentile(double topPercentile) } } +/** + * Getter for the time + * @return the time. + */ +double vtkSplatterPlot::getTime() const +{ + return m_time; +} int vtkSplatterPlot::RequestData(vtkInformation *, vtkInformationVector **inputVector, @@ -87,6 +96,13 @@ int vtkSplatterPlot::RequestData(vtkInformation *, vtkDataSet *output = vtkDataSet::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP())) + { + // usually only one actual step requested + m_time = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); + } + m_presenter->setTime(m_time); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkDataSet *input = vtkDataSet::SafeDownCast( inInfo->Get(vtkDataObject::DATA_OBJECT())); @@ -145,12 +161,10 @@ void vtkSplatterPlot::PrintSelf(ostream& os, vtkIndent indent) /** * Output the progress information and progress text. * @param : progress - *@param : message + * @param : message */ void vtkSplatterPlot::updateAlgorithmProgress(double progress, const std::string& message) { this->SetProgress(progress); this->SetProgressText(message.c_str()); } - - diff --git a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.h b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.h index c320aba4109a2f28c3772d1ec0c602b51ecee7a3..48a03de3de4a02ac34711d0688fc29650c640ecc 100644 --- a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.h +++ b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/SplatterPlot/vtkSplatterPlot.h @@ -18,6 +18,7 @@ class VTK_EXPORT vtkSplatterPlot : public vtkUnstructuredGridAlgorithm public: static vtkSplatterPlot *New(); vtkTypeMacro(vtkSplatterPlot, vtkUnstructuredGridAlgorithm); + double getTime() const; void PrintSelf(ostream& os, vtkIndent indent); void SetNumberOfPoints(int nPoints); void SetTopPercentile(double topPercentile); @@ -38,9 +39,10 @@ private: Mantid::VATES::vtkSplatterPlotFactory *m_presenter; /// Holder for the workspace name std::string m_wsName; + /// Time. + double m_time; vtkSplatterPlot(const vtkSplatterPlot&); void operator = (const vtkSplatterPlot&); - }; #endif diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h index 6c5028a2919f1a8c3db48cbe8fa2c619e3c1733a..5e4867e5e21fbc6d16964b641701c33c4804cd1c 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h @@ -73,6 +73,9 @@ public: /// Set percentage of boxes from which points will be plotted virtual void SetPercentToUse(double percentToUse); + /// Set the time value. + void setTime(double timeStep); + private: template<typename MDE, size_t nd> @@ -117,7 +120,8 @@ private: /// Variable to hold sorted list, so sort doesn't have to be repeated mutable std::vector< Mantid::API::IMDNode * > m_sortedBoxes; - + /// Time value. + double m_time; }; } diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp index b813dd53b10dd9991a17df36cd88ae6c7824dda0..d7545bf6c8e15c099eb7429d76d8913426bb65be 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp @@ -78,6 +78,7 @@ namespace VATES // boxes to use. size_t totalPoints = ws->getNPoints(); size_t numPoints = m_numPoints; + if (numPoints > totalPoints) { numPoints = totalPoints; @@ -144,7 +145,6 @@ namespace VATES std::cout << "DONE SORTING" << std::endl; } } - size_t num_boxes_to_use = static_cast<size_t>(percent_to_use * static_cast<double>(m_sortedBoxes.size()) / 100.0); if (num_boxes_to_use >= m_sortedBoxes.size()) { @@ -329,6 +329,7 @@ namespace VATES // Define where the slice is in 4D // TODO: Where to slice? Right now is just 0 std::vector<coord_t> point(nd, 0); + point[3] = coord_t(m_time); //Specifically for 4th/time dimension. // Define two opposing planes that point in all higher dimensions std::vector<coord_t> normal1(nd, 0); @@ -354,7 +355,7 @@ namespace VATES // Clean up if (this->slice) { - delete this->sliceMask; + delete[] this->sliceMask; delete this->sliceImplicitFunction; } @@ -388,11 +389,6 @@ namespace VATES { throw std::runtime_error("Invalid vtkSplatterPlotFactory. Workspace must have at least 3 dimensions."); } - size_t nd = m_workspace->getNonIntegratedDimensions().size(); - if (nd > 3) - { - throw std::runtime_error("SplatterPlot cannot handle 4D data, please integrate to 3D!"); - } } /** @@ -429,5 +425,18 @@ namespace VATES } } + /** + * Set the time value. + * @param double : the time + */ + void vtkSplatterPlotFactory::setTime(double time) + { + if (m_time != time) + { + m_buildSortedList = true; + } + m_time = time; + } + } } diff --git a/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h b/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h index 881edcdf55b46c69577513fde9b31f25798052dd..ba20b8e01db527b402554075ed7ae2c0b27ae745 100644 --- a/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h @@ -91,37 +91,24 @@ public: Mantid::MDEvents::MDEventWorkspace4Lean::sptr ws = MDEventsTestHelper::makeMDEW<4>(5, -10.0, 10.0, 1); vtkSplatterPlotFactory factory(ThresholdRange_scptr(new UserDefinedThresholdRange(0, 1)), "signal"); - TS_ASSERT_THROWS(factory.initialize(ws), std::runtime_error&); - //vtkDataSet* product = NULL; + factory.initialize(ws); + vtkDataSet* product = NULL; - //TS_ASSERT_THROWS(factory.create(progressUpdate), std::runtime_error&); - //TS_ASSERT_THROWS_NOTHING(product = factory.create(progressUpdate)); + TS_ASSERT_THROWS_NOTHING(product = factory.create(progressUpdate)); - /* - const size_t expected_n_points = 8*125; - const size_t expected_n_cells = 125; + // 6 is 5% of 125 + const size_t expected_n_points = 6; + const size_t expected_n_cells = 6; const size_t expected_n_signals = expected_n_cells; TSM_ASSERT_EQUALS("Wrong number of points", expected_n_points, product->GetNumberOfPoints()); TSM_ASSERT_EQUALS("Wrong number of cells", expected_n_cells, product->GetNumberOfCells()); - TSM_ASSERT_EQUALS("Wrong number of points to cells. Hexahedron has 8 vertexes.", expected_n_cells * 8, product->GetNumberOfPoints()); TSM_ASSERT_EQUALS("No signal Array", "signal", std::string(product->GetCellData()->GetArray(0)->GetName())); TSM_ASSERT_EQUALS("Wrong sized signal Array", expected_n_signals, product->GetCellData()->GetArray(0)->GetSize()); - //Check dataset bounds - double* bounds = product->GetBounds(); - TS_ASSERT_EQUALS(-9.5, bounds[0]); - TS_ASSERT_EQUALS(9.5, bounds[1]); - TS_ASSERT_EQUALS(-9.5, bounds[2]); - TS_ASSERT_EQUALS(9.5, bounds[3]); - TS_ASSERT_EQUALS(-9.5, bounds[4]); - TS_ASSERT_EQUALS(9.5, bounds[5]); - product->Delete(); - */ } - }; #endif diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp index e6051028a46120a2964ec1b8bce6c2f396fc0e44..527fef5654d1087ea51155e4eda646f5d4c63085 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp @@ -134,11 +134,6 @@ void SplatterPlotView::render() QString renderType = "Points"; pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); - if (this->checkForBadDimensions(src)) - { - return; - } - // Do not allow overplotting of MDWorkspaces if (!this->isPeaksWorkspace(src) && NULL != this->splatSource) { @@ -208,41 +203,6 @@ void SplatterPlotView::resetDisplay() this->view->resetDisplay(); } -/** - * This function checks any incoming MDEventWorkspace to ensure that it has - * only 3 non-integrated dimensions. Have to do this since the - * vtkSplatterPlotFactory isn't setup properly. - * - * @param src : The pipeline source to perform the dimension check - * @return True if there are more than 3 non-integrated dimensions - */ -bool SplatterPlotView::checkForBadDimensions(pqPipelineSource *src) -{ - if (!this->isPeaksWorkspace(src)) - { - QString wsName(vtkSMPropertyHelper(src->getProxy(), - "Mantid Workspace Name", true).GetAsString()); - if(!wsName.isEmpty()) - { - ADSWorkspaceProvider<Mantid::API::IMDEventWorkspace> wsProvider; - API::Workspace_sptr ws = wsProvider.fetchWorkspace(wsName.toStdString()); - API::IMDEventWorkspace_const_sptr infoWs = boost::dynamic_pointer_cast<const API::IMDEventWorkspace>(ws); - std::size_t numDims = infoWs->getNonIntegratedDimensions().size(); - if (numDims > 3) - { - QMessageBox::warning(this, QApplication::tr("Dimension Warning"), - QApplication::tr("SplatterPlot mode does not allow "\ - "4D data. Please integrate to 3D "\ - "via SliceMD!. Returning to Standard View.")); - pqActiveObjects::instance().setActiveSource(src); - emit this->resetToStandardView(); - return true; - } - } - } - return false; -} - /** * This function checks to see if the Override PC button has been * toggled. If the state is unchecked (false), we want to make sure diff --git a/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/UnitTestFacilities.xml b/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/UnitTestFacilities.xml index 59fdd5b1711b65a69883ff355f33f29a54fd9cce..2a554ec995aec5cd3e8443a7afd8400813d2e210 100644 --- a/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/UnitTestFacilities.xml +++ b/Code/Mantid/instrument/IDFs_for_UNIT_TESTING/UnitTestFacilities.xml @@ -17,6 +17,16 @@ <livedata listener="ISISHistoDataListener" address="127.0.0.1:6789" /> </instrument> + <instrument name="TestDataListener"> + <technique>Test Listener</technique> + <livedata listener="TestDataListener" address="127.0.0.1:0" /> + </instrument> + + <instrument name="FakeEventDataListener"> + <technique>Test Listener</technique> + <livedata listener="FakeEventDataListener" address="127.0.0.1:0" /> + </instrument> + </facility> -</facilities> \ No newline at end of file +</facilities> diff --git a/Code/Mantid/instrument/OSIRIS_Parameters.xml b/Code/Mantid/instrument/OSIRIS_Parameters.xml index 54323c2d4d7013a4688e0443535a65228bbd4be6..8caaf1f739f3d91589480649097c4abd00465cdd 100644 --- a/Code/Mantid/instrument/OSIRIS_Parameters.xml +++ b/Code/Mantid/instrument/OSIRIS_Parameters.xml @@ -16,7 +16,7 @@ </parameter> <parameter name="refl-diffraction" type="string"> - <value val="diffraction" /> + <value val="diffonly,diffspec" /> </parameter> <!-- Reduction workflow parameters under this line --> diff --git a/Code/Mantid/instrument/WISH_Definition_6Panel.xml b/Code/Mantid/instrument/WISH_Definition_6Panel.xml index 2fc01d71655e0cab99e06e635898ded416bfb864..c907298af9fa3a35001ca7a30b7eb20023a25751 100644 --- a/Code/Mantid/instrument/WISH_Definition_6Panel.xml +++ b/Code/Mantid/instrument/WISH_Definition_6Panel.xml @@ -2,8 +2,8 @@ <!-- For help on the notation used to specify an Instrument Definition File see http://www.mantidproject.org/IDF --> <instrument name="WISH" valid-from ="2012-09-26 17:24:36" - valid-to ="2100-01-31 23:59:59" - last-modified="2012-11-13 16:00:00"> + valid-to ="2013-07-01 17:24:36" + last-modified="2013-10-10 09:00:00"> <defaults> <length unit="meter"/> diff --git a/Code/Mantid/instrument/WISH_Definition_9Panels.xml b/Code/Mantid/instrument/WISH_Definition_9Panels.xml new file mode 100644 index 0000000000000000000000000000000000000000..88a764c0931e200ee46bc457e9945e5b35b1de22 --- /dev/null +++ b/Code/Mantid/instrument/WISH_Definition_9Panels.xml @@ -0,0 +1,2755 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- For help on the notation used to specify an Instrument Definition File + see http://www.mantidproject.org/IDF --> +<instrument name="WISH" valid-from ="2013-07-01 17:24:36" + valid-to ="2100-01-31 23:59:59" + last-modified="2012-11-13 16:00:00"> + + <defaults> + <length unit="meter"/> + <angle unit="degree"/> + <location r="0.0" t="0.0" p="0.0" ang="0.0" axis-x="0.0" axis-y="0.0" axis-z="1.0"/> + <reference-frame> + <!-- The z-axis is set parallel to and in the direction of the beam. the + y-axis points up and the coordinate system is right handed. --> + <along-beam axis="z"/> + <pointing-up axis="y"/> + <handedness val="right"/> + <origin val="beam" /> + </reference-frame> + <offsets spherical="vectors" /> + <!-- Comment "components-are-facing" out if you dont want the + components defined in this file to face a position by default --> + <components-are-facing x="0.0" y="0.0" z="0.0" /> + <default-view view="cylindrical_y"/> + </defaults> + <!-- LIST OF PHYSICAL COMPONENTS (which the instrument consists of) --> + <!-- detector components --> + <properties> + </properties> + <component type="monitors" idlist="monitors"> + <location/> + </component> + <component type="panel01" idlist="panel01"> + <location /> + </component> + <component type="panel02" idlist="panel02"> + <location /> + </component> + <component type="panel03" idlist="panel03"> + <location /> + </component> + <component type="panel04" idlist="panel04"> + <location /> + </component> + <component type="panel05" idlist="panel05"> + <location /> + </component> + <component type="panel10" idlist="panel10"> + <location /> + </component> + <component type="panel09" idlist="panel09"> + <location /> + </component> + <component type="panel08" idlist="panel08"> + <location /> + </component> + <component type="panel07" idlist="panel07"> + <location /> + </component> + <!-- source and sample-position components --> + <component type="undulator"> + <location z="-40.0"> <facing val="none"/> </location> + </component> + + <component type="nickel-holder"> + <location> <facing val="none"/> </location> + </component> + + <!-- DEFINITION OF TYPES --> + <!-- Source types --> + <type name="undulator" is="Source"> + <properties /> + <cylinder id="some-shape"> + <centre-of-bottom-base r="0.0" t="0.0" p="0.0" /> + <axis x="0.0" y="0.0" z="1.0" /> + <radius val="0.01" /> + <height val="0.03" /> + </cylinder> + <algebra val="some-shape" /> + </type> + + <!-- Sample-position types --> + <type name="nickel-holder" is="SamplePos"> + <properties /> + <sphere id="some-shape"> + <centre x="0.0" y="0.0" z="0.0" /> + <radius val="0.03" /> + </sphere> + <algebra val="some-shape" /> + </type> + + <!-- Detectors types --> + <type name="monitors"> + <component type="monitor"> + <location r="32.70" t="180.0" p="0.0" name="monitor1" /> + <location r="30.964" t="180.0" p="0.0" name="monitor2" /> + <location r="9.95" t="180.0" p="0.0" name="monitor3" /> + <location r="1.5" t="180.0" p="0.0" name="monitor4" /> + <location r="1.50" t="0.0" p="0.0" name="monitor5" /> + </component> + </type> + +<type name="panel01"> + <component type="WISHpanel"> +<location x="-0.96521 " z=" 1.9790 " name="WISHpanel01" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel02"> + <component type="WISHpanel"> +<location x=" -1.8672 " z=" 1.1668 " name="WISHpanel02" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel03"> + <component type="WISHpanel"> +<location x=" -2.2018 " z="-0.96244E-07" name="WISHpanel03" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel04"> + <component type="WISHpanel"> +<location x=" -1.8672 " z=" -1.1668 " name="WISHpanel04" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel05"> + <component type="WISHpanel"> +<location x="-0.96521 " z=" -1.9790 " name="WISHpanel05" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel10"> + <component type="WISHpanel"> +<location x="0.96521 " z=" -1.9790 " name="WISHpanel10" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel09"> + <component type="WISHpanel"> +<location x=" 1.8672 " z=" -1.1668 " name="WISHpanel09" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel08"> + <component type="WISHpanel"> +<location x=" 2.2018 " z="-0.96244E-07" name="WISHpanel08" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> +<type name="panel07"> + <component type="WISHpanel"> +<location x=" 1.8672 " z=" 1.1668 " name="WISHpanel07" > <facing x="0" y="0" z="0"/> </location> + </component> + </type> + <type name="WISHpanel"> + <properties /> + <component type="tubeup"> +<location x=" 0.603717 " z=" -0.825844E-01" name="tube001" /> +<location x=" 0.588122 " z=" -0.781998E-01" name="tube003" /> +<location x=" 0.572495 " z=" -0.739301E-01" name="tube005" /> +<location x=" 0.556837 " z=" -0.697755E-01" name="tube007" /> +<location x=" 0.541148 " z=" -0.657362E-01" name="tube009" /> +<location x=" 0.525431 " z=" -0.618124E-01" name="tube011" /> +<location x=" 0.509685 " z=" -0.580044E-01" name="tube013" /> +<location x=" 0.493911 " z=" -0.543124E-01" name="tube015" /> +<location x=" 0.478111 " z=" -0.507365E-01" name="tube017" /> +<location x=" 0.462284 " z=" -0.472769E-01" name="tube019" /> +<location x=" 0.446433 " z=" -0.439339E-01" name="tube021" /> +<location x=" 0.430558 " z=" -0.407076E-01" name="tube023" /> +<location x=" 0.414659 " z=" -0.375982E-01" name="tube025" /> +<location x=" 0.398738 " z=" -0.346059E-01" name="tube027" /> +<location x=" 0.382795 " z=" -0.317307E-01" name="tube029" /> +<location x=" 0.366831 " z=" -0.289730E-01" name="tube031" /> +<location x=" 0.350848 " z=" -0.263328E-01" name="tube033" /> +<location x=" 0.334846 " z=" -0.238102E-01" name="tube035" /> +<location x=" 0.318825 " z=" -0.214055E-01" name="tube037" /> +<location x=" 0.302787 " z=" -0.191187E-01" name="tube039" /> +<location x=" 0.286733 " z=" -0.169500E-01" name="tube041" /> +<location x=" 0.270664 " z=" -0.148994E-01" name="tube043" /> +<location x=" 0.254579 " z=" -0.129671E-01" name="tube045" /> +<location x=" 0.238481 " z=" -0.111532E-01" name="tube047" /> +<location x=" 0.222370 " z=" -0.945783E-02" name="tube049" /> +<location x=" 0.206247 " z=" -0.788102E-02" name="tube051" /> +<location x=" 0.190113 " z=" -0.642288E-02" name="tube053" /> +<location x=" 0.173968 " z=" -0.508349E-02" name="tube055" /> +<location x=" 0.157815 " z=" -0.386292E-02" name="tube057" /> +<location x=" 0.141652 " z=" -0.276124E-02" name="tube059" /> +<location x=" 0.125482 " z=" -0.177850E-02" name="tube061" /> +<location x=" 0.109305 " z=" -0.914756E-03" name="tube063" /> +<location x=" 0.931222E-01" z=" -0.170062E-03" name="tube065" /> +<location x=" 0.769343E-01" z=" 0.455547E-03" name="tube067" /> +<location x=" 0.607423E-01" z=" 0.962035E-03" name="tube069" /> +<location x=" 0.445470E-01" z=" 0.134938E-02" name="tube071" /> +<location x=" 0.283492E-01" z=" 0.161755E-02" name="tube073" /> +<location x=" 0.121499E-01" z=" 0.176654E-02" name="tube075" /> +<location x=" -0.405000E-02" z=" 0.179634E-02" name="tube077" /> +<location x=" -0.202497E-01" z=" 0.170694E-02" name="tube079" /> +<location x=" -0.364483E-01" z=" 0.149836E-02" name="tube081" /> +<location x=" -0.526450E-01" z=" 0.117060E-02" name="tube083" /> +<location x=" -0.688388E-01" z=" 0.723683E-03" name="tube085" /> +<location x=" -0.850289E-01" z=" 0.157631E-03" name="tube087" /> +<location x=" -0.101214 " z=" -0.527525E-03" name="tube089" /> +<location x=" -0.117394 " z=" -0.133175E-02" name="tube091" /> +<location x=" -0.133568 " z=" -0.225499E-02" name="tube093" /> +<location x=" -0.149734 " z=" -0.329721E-02" name="tube095" /> +<location x=" -0.165893 " z=" -0.445835E-02" name="tube097" /> +<location x=" -0.182042 " z=" -0.573834E-02" name="tube099" /> +<location x=" -0.198181 " z=" -0.713712E-02" name="tube101" /> +<location x=" -0.214310 " z=" -0.865460E-02" name="tube103" /> +<location x=" -0.230427 " z=" -0.102907E-01" name="tube105" /> +<location x=" -0.246532 " z=" -0.120454E-01" name="tube107" /> +<location x=" -0.262623 " z=" -0.139185E-01" name="tube109" /> +<location x=" -0.278700 " z=" -0.159099E-01" name="tube111" /> +<location x=" -0.294762 " z=" -0.180196E-01" name="tube113" /> +<location x=" -0.310808 " z=" -0.202473E-01" name="tube115" /> +<location x=" -0.326838 " z=" -0.225931E-01" name="tube117" /> +<location x=" -0.342849 " z=" -0.250568E-01" name="tube119" /> +<location x=" -0.358842 " z=" -0.276382E-01" name="tube121" /> +<location x=" -0.374816 " z=" -0.303372E-01" name="tube123" /> +<location x=" -0.390769 " z=" -0.331536E-01" name="tube125" /> +<location x=" -0.406701 " z=" -0.360874E-01" name="tube127" /> +<location x=" -0.422611 " z=" -0.391383E-01" name="tube129" /> +<location x=" -0.438498 " z=" -0.423062E-01" name="tube131" /> +<location x=" -0.454362 " z=" -0.455908E-01" name="tube133" /> +<location x=" -0.470201 " z=" -0.489921E-01" name="tube135" /> +<location x=" -0.486014 " z=" -0.525099E-01" name="tube137" /> +<location x=" -0.501801 " z=" -0.561439E-01" name="tube139" /> +<location x=" -0.517561 " z=" -0.598939E-01" name="tube141" /> +<location x=" -0.533293 " z=" -0.637599E-01" name="tube143" /> +<location x=" -0.548996 " z=" -0.677414E-01" name="tube145" /> +<location x=" -0.564670 " z=" -0.718384E-01" name="tube147" /> +<location x=" -0.580312 " z=" -0.760506E-01" name="tube149" /> +<location x=" -0.595924 " z=" -0.803777E-01" name="tube151" /> + </component> + <component type="tubedown"> +<location x=" 0.595924 " z=" -0.803777E-01" name="tube002" /> +<location x=" 0.580312 " z=" -0.760506E-01" name="tube004" /> +<location x=" 0.564670 " z=" -0.718384E-01" name="tube006" /> +<location x=" 0.548996 " z=" -0.677414E-01" name="tube008" /> +<location x=" 0.533293 " z=" -0.637599E-01" name="tube010" /> +<location x=" 0.517561 " z=" -0.598939E-01" name="tube012" /> +<location x=" 0.501801 " z=" -0.561439E-01" name="tube014" /> +<location x=" 0.486014 " z=" -0.525099E-01" name="tube016" /> +<location x=" 0.470201 " z=" -0.489921E-01" name="tube018" /> +<location x=" 0.454362 " z=" -0.455908E-01" name="tube020" /> +<location x=" 0.438498 " z=" -0.423062E-01" name="tube022" /> +<location x=" 0.422611 " z=" -0.391383E-01" name="tube024" /> +<location x=" 0.406701 " z=" -0.360874E-01" name="tube026" /> +<location x=" 0.390769 " z=" -0.331536E-01" name="tube028" /> +<location x=" 0.374816 " z=" -0.303372E-01" name="tube030" /> +<location x=" 0.358842 " z=" -0.276382E-01" name="tube032" /> +<location x=" 0.342849 " z=" -0.250568E-01" name="tube034" /> +<location x=" 0.326838 " z=" -0.225931E-01" name="tube036" /> +<location x=" 0.310808 " z=" -0.202473E-01" name="tube038" /> +<location x=" 0.294762 " z=" -0.180196E-01" name="tube040" /> +<location x=" 0.278700 " z=" -0.159099E-01" name="tube042" /> +<location x=" 0.262623 " z=" -0.139185E-01" name="tube044" /> +<location x=" 0.246532 " z=" -0.120454E-01" name="tube046" /> +<location x=" 0.230427 " z=" -0.102907E-01" name="tube048" /> +<location x=" 0.214310 " z=" -0.865460E-02" name="tube050" /> +<location x=" 0.198181 " z=" -0.713712E-02" name="tube052" /> +<location x=" 0.182042 " z=" -0.573834E-02" name="tube054" /> +<location x=" 0.165893 " z=" -0.445835E-02" name="tube056" /> +<location x=" 0.149734 " z=" -0.329721E-02" name="tube058" /> +<location x=" 0.133568 " z=" -0.225499E-02" name="tube060" /> +<location x=" 0.117394 " z=" -0.133175E-02" name="tube062" /> +<location x=" 0.101214 " z=" -0.527525E-03" name="tube064" /> +<location x=" 0.850289E-01" z=" 0.157631E-03" name="tube066" /> +<location x=" 0.688388E-01" z=" 0.723683E-03" name="tube068" /> +<location x=" 0.526450E-01" z=" 0.117060E-02" name="tube070" /> +<location x=" 0.364483E-01" z=" 0.149836E-02" name="tube072" /> +<location x=" 0.202497E-01" z=" 0.170694E-02" name="tube074" /> +<location x=" 0.405000E-02" z=" 0.179634E-02" name="tube076" /> +<location x=" -0.121499E-01" z=" 0.176654E-02" name="tube078" /> +<location x=" -0.283492E-01" z=" 0.161755E-02" name="tube080" /> +<location x=" -0.445470E-01" z=" 0.134938E-02" name="tube082" /> +<location x=" -0.607423E-01" z=" 0.962035E-03" name="tube084" /> +<location x=" -0.769343E-01" z=" 0.455547E-03" name="tube086" /> +<location x=" -0.931222E-01" z=" -0.170062E-03" name="tube088" /> +<location x=" -0.109305 " z=" -0.914756E-03" name="tube090" /> +<location x=" -0.125482 " z=" -0.177850E-02" name="tube092" /> +<location x=" -0.141652 " z=" -0.276124E-02" name="tube094" /> +<location x=" -0.157815 " z=" -0.386292E-02" name="tube096" /> +<location x=" -0.173968 " z=" -0.508349E-02" name="tube098" /> +<location x=" -0.190113 " z=" -0.642288E-02" name="tube100" /> +<location x=" -0.206247 " z=" -0.788102E-02" name="tube102" /> +<location x=" -0.222370 " z=" -0.945783E-02" name="tube104" /> +<location x=" -0.238481 " z=" -0.111532E-01" name="tube106" /> +<location x=" -0.254579 " z=" -0.129671E-01" name="tube108" /> +<location x=" -0.270664 " z=" -0.148994E-01" name="tube110" /> +<location x=" -0.286733 " z=" -0.169500E-01" name="tube112" /> +<location x=" -0.302787 " z=" -0.191187E-01" name="tube114" /> +<location x=" -0.318825 " z=" -0.214055E-01" name="tube116" /> +<location x=" -0.334846 " z=" -0.238102E-01" name="tube118" /> +<location x=" -0.350848 " z=" -0.263328E-01" name="tube120" /> +<location x=" -0.366831 " z=" -0.289730E-01" name="tube122" /> +<location x=" -0.382795 " z=" -0.317307E-01" name="tube124" /> +<location x=" -0.398738 " z=" -0.346059E-01" name="tube126" /> +<location x=" -0.414659 " z=" -0.375982E-01" name="tube128" /> +<location x=" -0.430558 " z=" -0.407076E-01" name="tube130" /> +<location x=" -0.446433 " z=" -0.439339E-01" name="tube132" /> +<location x=" -0.462284 " z=" -0.472769E-01" name="tube134" /> +<location x=" -0.478111 " z=" -0.507365E-01" name="tube136" /> +<location x=" -0.493911 " z=" -0.543124E-01" name="tube138" /> +<location x=" -0.509685 " z=" -0.580044E-01" name="tube140" /> +<location x=" -0.525431 " z=" -0.618124E-01" name="tube142" /> +<location x=" -0.541148 " z=" -0.657362E-01" name="tube144" /> +<location x=" -0.556837 " z=" -0.697755E-01" name="tube146" /> +<location x=" -0.572495 " z=" -0.739301E-01" name="tube148" /> +<location x=" -0.588122 " z=" -0.781998E-01" name="tube150" /> +<location x=" -0.603717 " z=" -0.825844E-01" name="tube152" /> + </component> + </type> + + <type name="tubeup" outline="yes"> + <component type="pixel"> + <location y=" -0.517983 " name="pixel0001"/> + <location y=" -0.515950 " name="pixel0002"/> + <location y=" -0.513917 " name="pixel0003"/> + <location y=" -0.511884 " name="pixel0004"/> + <location y=" -0.509851 " name="pixel0005"/> + <location y=" -0.507817 " name="pixel0006"/> + <location y=" -0.505784 " name="pixel0007"/> + <location y=" -0.503751 " name="pixel0008"/> + <location y=" -0.501718 " name="pixel0009"/> + <location y=" -0.499685 " name="pixel0010"/> + <location y=" -0.497651 " name="pixel0011"/> + <location y=" -0.495618 " name="pixel0012"/> + <location y=" -0.493585 " name="pixel0013"/> + <location y=" -0.491552 " name="pixel0014"/> + <location y=" -0.489519 " name="pixel0015"/> + <location y=" -0.487485 " name="pixel0016"/> + <location y=" -0.485452 " name="pixel0017"/> + <location y=" -0.483419 " name="pixel0018"/> + <location y=" -0.481386 " name="pixel0019"/> + <location y=" -0.479353 " name="pixel0020"/> + <location y=" -0.477319 " name="pixel0021"/> + <location y=" -0.475286 " name="pixel0022"/> + <location y=" -0.473253 " name="pixel0023"/> + <location y=" -0.471220 " name="pixel0024"/> + <location y=" -0.469187 " name="pixel0025"/> + <location y=" -0.467153 " name="pixel0026"/> + <location y=" -0.465120 " name="pixel0027"/> + <location y=" -0.463087 " name="pixel0028"/> + <location y=" -0.461054 " name="pixel0029"/> + <location y=" -0.459021 " name="pixel0030"/> + <location y=" -0.456987 " name="pixel0031"/> + <location y=" -0.454954 " name="pixel0032"/> + <location y=" -0.452921 " name="pixel0033"/> + <location y=" -0.450888 " name="pixel0034"/> + <location y=" -0.448854 " name="pixel0035"/> + <location y=" -0.446821 " name="pixel0036"/> + <location y=" -0.444788 " name="pixel0037"/> + <location y=" -0.442755 " name="pixel0038"/> + <location y=" -0.440722 " name="pixel0039"/> + <location y=" -0.438688 " name="pixel0040"/> + <location y=" -0.436655 " name="pixel0041"/> + <location y=" -0.434622 " name="pixel0042"/> + <location y=" -0.432589 " name="pixel0043"/> + <location y=" -0.430556 " name="pixel0044"/> + <location y=" -0.428522 " name="pixel0045"/> + <location y=" -0.426489 " name="pixel0046"/> + <location y=" -0.424456 " name="pixel0047"/> + <location y=" -0.422423 " name="pixel0048"/> + <location y=" -0.420390 " name="pixel0049"/> + <location y=" -0.418356 " name="pixel0050"/> + <location y=" -0.416323 " name="pixel0051"/> + <location y=" -0.414290 " name="pixel0052"/> + <location y=" -0.412257 " name="pixel0053"/> + <location y=" -0.410224 " name="pixel0054"/> + <location y=" -0.408190 " name="pixel0055"/> + <location y=" -0.406157 " name="pixel0056"/> + <location y=" -0.404124 " name="pixel0057"/> + <location y=" -0.402091 " name="pixel0058"/> + <location y=" -0.400058 " name="pixel0059"/> + <location y=" -0.398024 " name="pixel0060"/> + <location y=" -0.395991 " name="pixel0061"/> + <location y=" -0.393958 " name="pixel0062"/> + <location y=" -0.391925 " name="pixel0063"/> + <location y=" -0.389892 " name="pixel0064"/> + <location y=" -0.387858 " name="pixel0065"/> + <location y=" -0.385825 " name="pixel0066"/> + <location y=" -0.383792 " name="pixel0067"/> + <location y=" -0.381759 " name="pixel0068"/> + <location y=" -0.379726 " name="pixel0069"/> + <location y=" -0.377692 " name="pixel0070"/> + <location y=" -0.375659 " name="pixel0071"/> + <location y=" -0.373626 " name="pixel0072"/> + <location y=" -0.371593 " name="pixel0073"/> + <location y=" -0.369560 " name="pixel0074"/> + <location y=" -0.367526 " name="pixel0075"/> + <location y=" -0.365493 " name="pixel0076"/> + <location y=" -0.363460 " name="pixel0077"/> + <location y=" -0.361427 " name="pixel0078"/> + <location y=" -0.359394 " name="pixel0079"/> + <location y=" -0.357360 " name="pixel0080"/> + <location y=" -0.355327 " name="pixel0081"/> + <location y=" -0.353294 " name="pixel0082"/> + <location y=" -0.351261 " name="pixel0083"/> + <location y=" -0.349228 " name="pixel0084"/> + <location y=" -0.347194 " name="pixel0085"/> + <location y=" -0.345161 " name="pixel0086"/> + <location y=" -0.343128 " name="pixel0087"/> + <location y=" -0.341095 " name="pixel0088"/> + <location y=" -0.339062 " name="pixel0089"/> + <location y=" -0.337028 " name="pixel0090"/> + <location y=" -0.334995 " name="pixel0091"/> + <location y=" -0.332962 " name="pixel0092"/> + <location y=" -0.330929 " name="pixel0093"/> + <location y=" -0.328896 " name="pixel0094"/> + <location y=" -0.326862 " name="pixel0095"/> + <location y=" -0.324829 " name="pixel0096"/> + <location y=" -0.322796 " name="pixel0097"/> + <location y=" -0.320763 " name="pixel0098"/> + <location y=" -0.318729 " name="pixel0099"/> + <location y=" -0.316696 " name="pixel0100"/> + <location y=" -0.314663 " name="pixel0101"/> + <location y=" -0.312630 " name="pixel0102"/> + <location y=" -0.310597 " name="pixel0103"/> + <location y=" -0.308563 " name="pixel0104"/> + <location y=" -0.306530 " name="pixel0105"/> + <location y=" -0.304497 " name="pixel0106"/> + <location y=" -0.302464 " name="pixel0107"/> + <location y=" -0.300431 " name="pixel0108"/> + <location y=" -0.298397 " name="pixel0109"/> + <location y=" -0.296364 " name="pixel0110"/> + <location y=" -0.294331 " name="pixel0111"/> + <location y=" -0.292298 " name="pixel0112"/> + <location y=" -0.290265 " name="pixel0113"/> + <location y=" -0.288231 " name="pixel0114"/> + <location y=" -0.286198 " name="pixel0115"/> + <location y=" -0.284165 " name="pixel0116"/> + <location y=" -0.282132 " name="pixel0117"/> + <location y=" -0.280099 " name="pixel0118"/> + <location y=" -0.278065 " name="pixel0119"/> + <location y=" -0.276032 " name="pixel0120"/> + <location y=" -0.273999 " name="pixel0121"/> + <location y=" -0.271966 " name="pixel0122"/> + <location y=" -0.269933 " name="pixel0123"/> + <location y=" -0.267899 " name="pixel0124"/> + <location y=" -0.265866 " name="pixel0125"/> + <location y=" -0.263833 " name="pixel0126"/> + <location y=" -0.261800 " name="pixel0127"/> + <location y=" -0.259767 " name="pixel0128"/> + <location y=" -0.257733 " name="pixel0129"/> + <location y=" -0.255700 " name="pixel0130"/> + <location y=" -0.253667 " name="pixel0131"/> + <location y=" -0.251634 " name="pixel0132"/> + <location y=" -0.249601 " name="pixel0133"/> + <location y=" -0.247567 " name="pixel0134"/> + <location y=" -0.245534 " name="pixel0135"/> + <location y=" -0.243501 " name="pixel0136"/> + <location y=" -0.241468 " name="pixel0137"/> + <location y=" -0.239435 " name="pixel0138"/> + <location y=" -0.237401 " name="pixel0139"/> + <location y=" -0.235368 " name="pixel0140"/> + <location y=" -0.233335 " name="pixel0141"/> + <location y=" -0.231302 " name="pixel0142"/> + <location y=" -0.229269 " name="pixel0143"/> + <location y=" -0.227235 " name="pixel0144"/> + <location y=" -0.225202 " name="pixel0145"/> + <location y=" -0.223169 " name="pixel0146"/> + <location y=" -0.221136 " name="pixel0147"/> + <location y=" -0.219103 " name="pixel0148"/> + <location y=" -0.217069 " name="pixel0149"/> + <location y=" -0.215036 " name="pixel0150"/> + <location y=" -0.213003 " name="pixel0151"/> + <location y=" -0.210970 " name="pixel0152"/> + <location y=" -0.208937 " name="pixel0153"/> + <location y=" -0.206903 " name="pixel0154"/> + <location y=" -0.204870 " name="pixel0155"/> + <location y=" -0.202837 " name="pixel0156"/> + <location y=" -0.200804 " name="pixel0157"/> + <location y=" -0.198771 " name="pixel0158"/> + <location y=" -0.196737 " name="pixel0159"/> + <location y=" -0.194704 " name="pixel0160"/> + <location y=" -0.192671 " name="pixel0161"/> + <location y=" -0.190638 " name="pixel0162"/> + <location y=" -0.188604 " name="pixel0163"/> + <location y=" -0.186571 " name="pixel0164"/> + <location y=" -0.184538 " name="pixel0165"/> + <location y=" -0.182505 " name="pixel0166"/> + <location y=" -0.180472 " name="pixel0167"/> + <location y=" -0.178438 " name="pixel0168"/> + <location y=" -0.176405 " name="pixel0169"/> + <location y=" -0.174372 " name="pixel0170"/> + <location y=" -0.172339 " name="pixel0171"/> + <location y=" -0.170306 " name="pixel0172"/> + <location y=" -0.168272 " name="pixel0173"/> + <location y=" -0.166239 " name="pixel0174"/> + <location y=" -0.164206 " name="pixel0175"/> + <location y=" -0.162173 " name="pixel0176"/> + <location y=" -0.160140 " name="pixel0177"/> + <location y=" -0.158106 " name="pixel0178"/> + <location y=" -0.156073 " name="pixel0179"/> + <location y=" -0.154040 " name="pixel0180"/> + <location y=" -0.152007 " name="pixel0181"/> + <location y=" -0.149974 " name="pixel0182"/> + <location y=" -0.147940 " name="pixel0183"/> + <location y=" -0.145907 " name="pixel0184"/> + <location y=" -0.143874 " name="pixel0185"/> + <location y=" -0.141841 " name="pixel0186"/> + <location y=" -0.139808 " name="pixel0187"/> + <location y=" -0.137774 " name="pixel0188"/> + <location y=" -0.135741 " name="pixel0189"/> + <location y=" -0.133708 " name="pixel0190"/> + <location y=" -0.131675 " name="pixel0191"/> + <location y=" -0.129642 " name="pixel0192"/> + <location y=" -0.127608 " name="pixel0193"/> + <location y=" -0.125575 " name="pixel0194"/> + <location y=" -0.123542 " name="pixel0195"/> + <location y=" -0.121509 " name="pixel0196"/> + <location y=" -0.119476 " name="pixel0197"/> + <location y=" -0.117442 " name="pixel0198"/> + <location y=" -0.115409 " name="pixel0199"/> + <location y=" -0.113376 " name="pixel0200"/> + <location y=" -0.111343 " name="pixel0201"/> + <location y=" -0.109310 " name="pixel0202"/> + <location y=" -0.107276 " name="pixel0203"/> + <location y=" -0.105243 " name="pixel0204"/> + <location y=" -0.103210 " name="pixel0205"/> + <location y=" -0.101177 " name="pixel0206"/> + <location y=" -0.991436E-01" name="pixel0207"/> + <location y=" -0.971104E-01" name="pixel0208"/> + <location y=" -0.950771E-01" name="pixel0209"/> + <location y=" -0.930439E-01" name="pixel0210"/> + <location y=" -0.910107E-01" name="pixel0211"/> + <location y=" -0.889775E-01" name="pixel0212"/> + <location y=" -0.869443E-01" name="pixel0213"/> + <location y=" -0.849111E-01" name="pixel0214"/> + <location y=" -0.828779E-01" name="pixel0215"/> + <location y=" -0.808447E-01" name="pixel0216"/> + <location y=" -0.788115E-01" name="pixel0217"/> + <location y=" -0.767783E-01" name="pixel0218"/> + <location y=" -0.747451E-01" name="pixel0219"/> + <location y=" -0.727119E-01" name="pixel0220"/> + <location y=" -0.706787E-01" name="pixel0221"/> + <location y=" -0.686455E-01" name="pixel0222"/> + <location y=" -0.666123E-01" name="pixel0223"/> + <location y=" -0.645791E-01" name="pixel0224"/> + <location y=" -0.625459E-01" name="pixel0225"/> + <location y=" -0.605127E-01" name="pixel0226"/> + <location y=" -0.584795E-01" name="pixel0227"/> + <location y=" -0.564463E-01" name="pixel0228"/> + <location y=" -0.544131E-01" name="pixel0229"/> + <location y=" -0.523799E-01" name="pixel0230"/> + <location y=" -0.503467E-01" name="pixel0231"/> + <location y=" -0.483135E-01" name="pixel0232"/> + <location y=" -0.462803E-01" name="pixel0233"/> + <location y=" -0.442471E-01" name="pixel0234"/> + <location y=" -0.422139E-01" name="pixel0235"/> + <location y=" -0.401807E-01" name="pixel0236"/> + <location y=" -0.381475E-01" name="pixel0237"/> + <location y=" -0.361143E-01" name="pixel0238"/> + <location y=" -0.340811E-01" name="pixel0239"/> + <location y=" -0.320479E-01" name="pixel0240"/> + <location y=" -0.300146E-01" name="pixel0241"/> + <location y=" -0.279814E-01" name="pixel0242"/> + <location y=" -0.259482E-01" name="pixel0243"/> + <location y=" -0.239150E-01" name="pixel0244"/> + <location y=" -0.218818E-01" name="pixel0245"/> + <location y=" -0.198486E-01" name="pixel0246"/> + <location y=" -0.178154E-01" name="pixel0247"/> + <location y=" -0.157822E-01" name="pixel0248"/> + <location y=" -0.137490E-01" name="pixel0249"/> + <location y=" -0.117158E-01" name="pixel0250"/> + <location y=" -0.968262E-02" name="pixel0251"/> + <location y=" -0.764941E-02" name="pixel0252"/> + <location y=" -0.561621E-02" name="pixel0253"/> + <location y=" -0.358301E-02" name="pixel0254"/> + <location y=" -0.154980E-02" name="pixel0255"/> + <location y=" 0.483398E-03" name="pixel0256"/> + <location y=" 0.251660E-02" name="pixel0257"/> + <location y=" 0.454980E-02" name="pixel0258"/> + <location y=" 0.658301E-02" name="pixel0259"/> + <location y=" 0.861621E-02" name="pixel0260"/> + <location y=" 0.106494E-01" name="pixel0261"/> + <location y=" 0.126826E-01" name="pixel0262"/> + <location y=" 0.147158E-01" name="pixel0263"/> + <location y=" 0.167490E-01" name="pixel0264"/> + <location y=" 0.187822E-01" name="pixel0265"/> + <location y=" 0.208154E-01" name="pixel0266"/> + <location y=" 0.228486E-01" name="pixel0267"/> + <location y=" 0.248818E-01" name="pixel0268"/> + <location y=" 0.269150E-01" name="pixel0269"/> + <location y=" 0.289482E-01" name="pixel0270"/> + <location y=" 0.309814E-01" name="pixel0271"/> + <location y=" 0.330146E-01" name="pixel0272"/> + <location y=" 0.350479E-01" name="pixel0273"/> + <location y=" 0.370811E-01" name="pixel0274"/> + <location y=" 0.391143E-01" name="pixel0275"/> + <location y=" 0.411475E-01" name="pixel0276"/> + <location y=" 0.431807E-01" name="pixel0277"/> + <location y=" 0.452139E-01" name="pixel0278"/> + <location y=" 0.472471E-01" name="pixel0279"/> + <location y=" 0.492803E-01" name="pixel0280"/> + <location y=" 0.513135E-01" name="pixel0281"/> + <location y=" 0.533467E-01" name="pixel0282"/> + <location y=" 0.553799E-01" name="pixel0283"/> + <location y=" 0.574131E-01" name="pixel0284"/> + <location y=" 0.594463E-01" name="pixel0285"/> + <location y=" 0.614795E-01" name="pixel0286"/> + <location y=" 0.635127E-01" name="pixel0287"/> + <location y=" 0.655459E-01" name="pixel0288"/> + <location y=" 0.675791E-01" name="pixel0289"/> + <location y=" 0.696123E-01" name="pixel0290"/> + <location y=" 0.716455E-01" name="pixel0291"/> + <location y=" 0.736787E-01" name="pixel0292"/> + <location y=" 0.757119E-01" name="pixel0293"/> + <location y=" 0.777451E-01" name="pixel0294"/> + <location y=" 0.797783E-01" name="pixel0295"/> + <location y=" 0.818115E-01" name="pixel0296"/> + <location y=" 0.838447E-01" name="pixel0297"/> + <location y=" 0.858779E-01" name="pixel0298"/> + <location y=" 0.879111E-01" name="pixel0299"/> + <location y=" 0.899443E-01" name="pixel0300"/> + <location y=" 0.919775E-01" name="pixel0301"/> + <location y=" 0.940107E-01" name="pixel0302"/> + <location y=" 0.960439E-01" name="pixel0303"/> + <location y=" 0.980771E-01" name="pixel0304"/> + <location y=" 0.100110 " name="pixel0305"/> + <location y=" 0.102144 " name="pixel0306"/> + <location y=" 0.104177 " name="pixel0307"/> + <location y=" 0.106210 " name="pixel0308"/> + <location y=" 0.108243 " name="pixel0309"/> + <location y=" 0.110276 " name="pixel0310"/> + <location y=" 0.112310 " name="pixel0311"/> + <location y=" 0.114343 " name="pixel0312"/> + <location y=" 0.116376 " name="pixel0313"/> + <location y=" 0.118409 " name="pixel0314"/> + <location y=" 0.120442 " name="pixel0315"/> + <location y=" 0.122476 " name="pixel0316"/> + <location y=" 0.124509 " name="pixel0317"/> + <location y=" 0.126542 " name="pixel0318"/> + <location y=" 0.128575 " name="pixel0319"/> + <location y=" 0.130608 " name="pixel0320"/> + <location y=" 0.132642 " name="pixel0321"/> + <location y=" 0.134675 " name="pixel0322"/> + <location y=" 0.136708 " name="pixel0323"/> + <location y=" 0.138741 " name="pixel0324"/> + <location y=" 0.140774 " name="pixel0325"/> + <location y=" 0.142808 " name="pixel0326"/> + <location y=" 0.144841 " name="pixel0327"/> + <location y=" 0.146874 " name="pixel0328"/> + <location y=" 0.148907 " name="pixel0329"/> + <location y=" 0.150940 " name="pixel0330"/> + <location y=" 0.152974 " name="pixel0331"/> + <location y=" 0.155007 " name="pixel0332"/> + <location y=" 0.157040 " name="pixel0333"/> + <location y=" 0.159073 " name="pixel0334"/> + <location y=" 0.161106 " name="pixel0335"/> + <location y=" 0.163140 " name="pixel0336"/> + <location y=" 0.165173 " name="pixel0337"/> + <location y=" 0.167206 " name="pixel0338"/> + <location y=" 0.169239 " name="pixel0339"/> + <location y=" 0.171272 " name="pixel0340"/> + <location y=" 0.173306 " name="pixel0341"/> + <location y=" 0.175339 " name="pixel0342"/> + <location y=" 0.177372 " name="pixel0343"/> + <location y=" 0.179405 " name="pixel0344"/> + <location y=" 0.181438 " name="pixel0345"/> + <location y=" 0.183472 " name="pixel0346"/> + <location y=" 0.185505 " name="pixel0347"/> + <location y=" 0.187538 " name="pixel0348"/> + <location y=" 0.189571 " name="pixel0349"/> + <location y=" 0.191604 " name="pixel0350"/> + <location y=" 0.193638 " name="pixel0351"/> + <location y=" 0.195671 " name="pixel0352"/> + <location y=" 0.197704 " name="pixel0353"/> + <location y=" 0.199737 " name="pixel0354"/> + <location y=" 0.201771 " name="pixel0355"/> + <location y=" 0.203804 " name="pixel0356"/> + <location y=" 0.205837 " name="pixel0357"/> + <location y=" 0.207870 " name="pixel0358"/> + <location y=" 0.209903 " name="pixel0359"/> + <location y=" 0.211937 " name="pixel0360"/> + <location y=" 0.213970 " name="pixel0361"/> + <location y=" 0.216003 " name="pixel0362"/> + <location y=" 0.218036 " name="pixel0363"/> + <location y=" 0.220069 " name="pixel0364"/> + <location y=" 0.222103 " name="pixel0365"/> + <location y=" 0.224136 " name="pixel0366"/> + <location y=" 0.226169 " name="pixel0367"/> + <location y=" 0.228202 " name="pixel0368"/> + <location y=" 0.230235 " name="pixel0369"/> + <location y=" 0.232269 " name="pixel0370"/> + <location y=" 0.234302 " name="pixel0371"/> + <location y=" 0.236335 " name="pixel0372"/> + <location y=" 0.238368 " name="pixel0373"/> + <location y=" 0.240401 " name="pixel0374"/> + <location y=" 0.242435 " name="pixel0375"/> + <location y=" 0.244468 " name="pixel0376"/> + <location y=" 0.246501 " name="pixel0377"/> + <location y=" 0.248534 " name="pixel0378"/> + <location y=" 0.250567 " name="pixel0379"/> + <location y=" 0.252601 " name="pixel0380"/> + <location y=" 0.254634 " name="pixel0381"/> + <location y=" 0.256667 " name="pixel0382"/> + <location y=" 0.258700 " name="pixel0383"/> + <location y=" 0.260733 " name="pixel0384"/> + <location y=" 0.262767 " name="pixel0385"/> + <location y=" 0.264800 " name="pixel0386"/> + <location y=" 0.266833 " name="pixel0387"/> + <location y=" 0.268866 " name="pixel0388"/> + <location y=" 0.270899 " name="pixel0389"/> + <location y=" 0.272933 " name="pixel0390"/> + <location y=" 0.274966 " name="pixel0391"/> + <location y=" 0.276999 " name="pixel0392"/> + <location y=" 0.279032 " name="pixel0393"/> + <location y=" 0.281065 " name="pixel0394"/> + <location y=" 0.283099 " name="pixel0395"/> + <location y=" 0.285132 " name="pixel0396"/> + <location y=" 0.287165 " name="pixel0397"/> + <location y=" 0.289198 " name="pixel0398"/> + <location y=" 0.291231 " name="pixel0399"/> + <location y=" 0.293265 " name="pixel0400"/> + <location y=" 0.295298 " name="pixel0401"/> + <location y=" 0.297331 " name="pixel0402"/> + <location y=" 0.299364 " name="pixel0403"/> + <location y=" 0.301397 " name="pixel0404"/> + <location y=" 0.303431 " name="pixel0405"/> + <location y=" 0.305464 " name="pixel0406"/> + <location y=" 0.307497 " name="pixel0407"/> + <location y=" 0.309530 " name="pixel0408"/> + <location y=" 0.311563 " name="pixel0409"/> + <location y=" 0.313597 " name="pixel0410"/> + <location y=" 0.315630 " name="pixel0411"/> + <location y=" 0.317663 " name="pixel0412"/> + <location y=" 0.319696 " name="pixel0413"/> + <location y=" 0.321729 " name="pixel0414"/> + <location y=" 0.323763 " name="pixel0415"/> + <location y=" 0.325796 " name="pixel0416"/> + <location y=" 0.327829 " name="pixel0417"/> + <location y=" 0.329862 " name="pixel0418"/> + <location y=" 0.331896 " name="pixel0419"/> + <location y=" 0.333929 " name="pixel0420"/> + <location y=" 0.335962 " name="pixel0421"/> + <location y=" 0.337995 " name="pixel0422"/> + <location y=" 0.340028 " name="pixel0423"/> + <location y=" 0.342062 " name="pixel0424"/> + <location y=" 0.344095 " name="pixel0425"/> + <location y=" 0.346128 " name="pixel0426"/> + <location y=" 0.348161 " name="pixel0427"/> + <location y=" 0.350194 " name="pixel0428"/> + <location y=" 0.352228 " name="pixel0429"/> + <location y=" 0.354261 " name="pixel0430"/> + <location y=" 0.356294 " name="pixel0431"/> + <location y=" 0.358327 " name="pixel0432"/> + <location y=" 0.360360 " name="pixel0433"/> + <location y=" 0.362394 " name="pixel0434"/> + <location y=" 0.364427 " name="pixel0435"/> + <location y=" 0.366460 " name="pixel0436"/> + <location y=" 0.368493 " name="pixel0437"/> + <location y=" 0.370526 " name="pixel0438"/> + <location y=" 0.372560 " name="pixel0439"/> + <location y=" 0.374593 " name="pixel0440"/> + <location y=" 0.376626 " name="pixel0441"/> + <location y=" 0.378659 " name="pixel0442"/> + <location y=" 0.380692 " name="pixel0443"/> + <location y=" 0.382726 " name="pixel0444"/> + <location y=" 0.384759 " name="pixel0445"/> + <location y=" 0.386792 " name="pixel0446"/> + <location y=" 0.388825 " name="pixel0447"/> + <location y=" 0.390858 " name="pixel0448"/> + <location y=" 0.392892 " name="pixel0449"/> + <location y=" 0.394925 " name="pixel0450"/> + <location y=" 0.396958 " name="pixel0451"/> + <location y=" 0.398991 " name="pixel0452"/> + <location y=" 0.401024 " name="pixel0453"/> + <location y=" 0.403058 " name="pixel0454"/> + <location y=" 0.405091 " name="pixel0455"/> + <location y=" 0.407124 " name="pixel0456"/> + <location y=" 0.409157 " name="pixel0457"/> + <location y=" 0.411190 " name="pixel0458"/> + <location y=" 0.413224 " name="pixel0459"/> + <location y=" 0.415257 " name="pixel0460"/> + <location y=" 0.417290 " name="pixel0461"/> + <location y=" 0.419323 " name="pixel0462"/> + <location y=" 0.421356 " name="pixel0463"/> + <location y=" 0.423390 " name="pixel0464"/> + <location y=" 0.425423 " name="pixel0465"/> + <location y=" 0.427456 " name="pixel0466"/> + <location y=" 0.429489 " name="pixel0467"/> + <location y=" 0.431522 " name="pixel0468"/> + <location y=" 0.433556 " name="pixel0469"/> + <location y=" 0.435589 " name="pixel0470"/> + <location y=" 0.437622 " name="pixel0471"/> + <location y=" 0.439655 " name="pixel0472"/> + <location y=" 0.441688 " name="pixel0473"/> + <location y=" 0.443722 " name="pixel0474"/> + <location y=" 0.445755 " name="pixel0475"/> + <location y=" 0.447788 " name="pixel0476"/> + <location y=" 0.449821 " name="pixel0477"/> + <location y=" 0.451854 " name="pixel0478"/> + <location y=" 0.453888 " name="pixel0479"/> + <location y=" 0.455921 " name="pixel0480"/> + <location y=" 0.457954 " name="pixel0481"/> + <location y=" 0.459987 " name="pixel0482"/> + <location y=" 0.462021 " name="pixel0483"/> + <location y=" 0.464054 " name="pixel0484"/> + <location y=" 0.466087 " name="pixel0485"/> + <location y=" 0.468120 " name="pixel0486"/> + <location y=" 0.470153 " name="pixel0487"/> + <location y=" 0.472187 " name="pixel0488"/> + <location y=" 0.474220 " name="pixel0489"/> + <location y=" 0.476253 " name="pixel0490"/> + <location y=" 0.478286 " name="pixel0491"/> + <location y=" 0.480319 " name="pixel0492"/> + <location y=" 0.482353 " name="pixel0493"/> + <location y=" 0.484386 " name="pixel0494"/> + <location y=" 0.486419 " name="pixel0495"/> + <location y=" 0.488452 " name="pixel0496"/> + <location y=" 0.490485 " name="pixel0497"/> + <location y=" 0.492519 " name="pixel0498"/> + <location y=" 0.494552 " name="pixel0499"/> + <location y=" 0.496585 " name="pixel0500"/> + <location y=" 0.498618 " name="pixel0501"/> + <location y=" 0.500651 " name="pixel0502"/> + <location y=" 0.502685 " name="pixel0503"/> + <location y=" 0.504718 " name="pixel0504"/> + <location y=" 0.506751 " name="pixel0505"/> + <location y=" 0.508784 " name="pixel0506"/> + <location y=" 0.510817 " name="pixel0507"/> + <location y=" 0.512851 " name="pixel0508"/> + <location y=" 0.514884 " name="pixel0509"/> + <location y=" 0.516917 " name="pixel0510"/> + <location y=" 0.518950 " name="pixel0511"/> + <location y=" 0.520983 " name="pixel0512"/> + </component> + </type> + <type name="tubedown" outline="yes"> + <component type="pixel"> + <location y=" -0.520983 " name="pixel0001"/> + <location y=" -0.518950 " name="pixel0002"/> + <location y=" -0.516917 " name="pixel0003"/> + <location y=" -0.514884 " name="pixel0004"/> + <location y=" -0.512851 " name="pixel0005"/> + <location y=" -0.510817 " name="pixel0006"/> + <location y=" -0.508784 " name="pixel0007"/> + <location y=" -0.506751 " name="pixel0008"/> + <location y=" -0.504718 " name="pixel0009"/> + <location y=" -0.502685 " name="pixel0010"/> + <location y=" -0.500651 " name="pixel0011"/> + <location y=" -0.498618 " name="pixel0012"/> + <location y=" -0.496585 " name="pixel0013"/> + <location y=" -0.494552 " name="pixel0014"/> + <location y=" -0.492519 " name="pixel0015"/> + <location y=" -0.490485 " name="pixel0016"/> + <location y=" -0.488452 " name="pixel0017"/> + <location y=" -0.486419 " name="pixel0018"/> + <location y=" -0.484386 " name="pixel0019"/> + <location y=" -0.482353 " name="pixel0020"/> + <location y=" -0.480319 " name="pixel0021"/> + <location y=" -0.478286 " name="pixel0022"/> + <location y=" -0.476253 " name="pixel0023"/> + <location y=" -0.474220 " name="pixel0024"/> + <location y=" -0.472187 " name="pixel0025"/> + <location y=" -0.470153 " name="pixel0026"/> + <location y=" -0.468120 " name="pixel0027"/> + <location y=" -0.466087 " name="pixel0028"/> + <location y=" -0.464054 " name="pixel0029"/> + <location y=" -0.462021 " name="pixel0030"/> + <location y=" -0.459987 " name="pixel0031"/> + <location y=" -0.457954 " name="pixel0032"/> + <location y=" -0.455921 " name="pixel0033"/> + <location y=" -0.453888 " name="pixel0034"/> + <location y=" -0.451854 " name="pixel0035"/> + <location y=" -0.449821 " name="pixel0036"/> + <location y=" -0.447788 " name="pixel0037"/> + <location y=" -0.445755 " name="pixel0038"/> + <location y=" -0.443722 " name="pixel0039"/> + <location y=" -0.441688 " name="pixel0040"/> + <location y=" -0.439655 " name="pixel0041"/> + <location y=" -0.437622 " name="pixel0042"/> + <location y=" -0.435589 " name="pixel0043"/> + <location y=" -0.433556 " name="pixel0044"/> + <location y=" -0.431522 " name="pixel0045"/> + <location y=" -0.429489 " name="pixel0046"/> + <location y=" -0.427456 " name="pixel0047"/> + <location y=" -0.425423 " name="pixel0048"/> + <location y=" -0.423390 " name="pixel0049"/> + <location y=" -0.421356 " name="pixel0050"/> + <location y=" -0.419323 " name="pixel0051"/> + <location y=" -0.417290 " name="pixel0052"/> + <location y=" -0.415257 " name="pixel0053"/> + <location y=" -0.413224 " name="pixel0054"/> + <location y=" -0.411190 " name="pixel0055"/> + <location y=" -0.409157 " name="pixel0056"/> + <location y=" -0.407124 " name="pixel0057"/> + <location y=" -0.405091 " name="pixel0058"/> + <location y=" -0.403058 " name="pixel0059"/> + <location y=" -0.401024 " name="pixel0060"/> + <location y=" -0.398991 " name="pixel0061"/> + <location y=" -0.396958 " name="pixel0062"/> + <location y=" -0.394925 " name="pixel0063"/> + <location y=" -0.392892 " name="pixel0064"/> + <location y=" -0.390858 " name="pixel0065"/> + <location y=" -0.388825 " name="pixel0066"/> + <location y=" -0.386792 " name="pixel0067"/> + <location y=" -0.384759 " name="pixel0068"/> + <location y=" -0.382726 " name="pixel0069"/> + <location y=" -0.380692 " name="pixel0070"/> + <location y=" -0.378659 " name="pixel0071"/> + <location y=" -0.376626 " name="pixel0072"/> + <location y=" -0.374593 " name="pixel0073"/> + <location y=" -0.372560 " name="pixel0074"/> + <location y=" -0.370526 " name="pixel0075"/> + <location y=" -0.368493 " name="pixel0076"/> + <location y=" -0.366460 " name="pixel0077"/> + <location y=" -0.364427 " name="pixel0078"/> + <location y=" -0.362394 " name="pixel0079"/> + <location y=" -0.360360 " name="pixel0080"/> + <location y=" -0.358327 " name="pixel0081"/> + <location y=" -0.356294 " name="pixel0082"/> + <location y=" -0.354261 " name="pixel0083"/> + <location y=" -0.352228 " name="pixel0084"/> + <location y=" -0.350194 " name="pixel0085"/> + <location y=" -0.348161 " name="pixel0086"/> + <location y=" -0.346128 " name="pixel0087"/> + <location y=" -0.344095 " name="pixel0088"/> + <location y=" -0.342062 " name="pixel0089"/> + <location y=" -0.340028 " name="pixel0090"/> + <location y=" -0.337995 " name="pixel0091"/> + <location y=" -0.335962 " name="pixel0092"/> + <location y=" -0.333929 " name="pixel0093"/> + <location y=" -0.331896 " name="pixel0094"/> + <location y=" -0.329862 " name="pixel0095"/> + <location y=" -0.327829 " name="pixel0096"/> + <location y=" -0.325796 " name="pixel0097"/> + <location y=" -0.323763 " name="pixel0098"/> + <location y=" -0.321729 " name="pixel0099"/> + <location y=" -0.319696 " name="pixel0100"/> + <location y=" -0.317663 " name="pixel0101"/> + <location y=" -0.315630 " name="pixel0102"/> + <location y=" -0.313597 " name="pixel0103"/> + <location y=" -0.311563 " name="pixel0104"/> + <location y=" -0.309530 " name="pixel0105"/> + <location y=" -0.307497 " name="pixel0106"/> + <location y=" -0.305464 " name="pixel0107"/> + <location y=" -0.303431 " name="pixel0108"/> + <location y=" -0.301397 " name="pixel0109"/> + <location y=" -0.299364 " name="pixel0110"/> + <location y=" -0.297331 " name="pixel0111"/> + <location y=" -0.295298 " name="pixel0112"/> + <location y=" -0.293265 " name="pixel0113"/> + <location y=" -0.291231 " name="pixel0114"/> + <location y=" -0.289198 " name="pixel0115"/> + <location y=" -0.287165 " name="pixel0116"/> + <location y=" -0.285132 " name="pixel0117"/> + <location y=" -0.283099 " name="pixel0118"/> + <location y=" -0.281065 " name="pixel0119"/> + <location y=" -0.279032 " name="pixel0120"/> + <location y=" -0.276999 " name="pixel0121"/> + <location y=" -0.274966 " name="pixel0122"/> + <location y=" -0.272933 " name="pixel0123"/> + <location y=" -0.270899 " name="pixel0124"/> + <location y=" -0.268866 " name="pixel0125"/> + <location y=" -0.266833 " name="pixel0126"/> + <location y=" -0.264800 " name="pixel0127"/> + <location y=" -0.262767 " name="pixel0128"/> + <location y=" -0.260733 " name="pixel0129"/> + <location y=" -0.258700 " name="pixel0130"/> + <location y=" -0.256667 " name="pixel0131"/> + <location y=" -0.254634 " name="pixel0132"/> + <location y=" -0.252601 " name="pixel0133"/> + <location y=" -0.250567 " name="pixel0134"/> + <location y=" -0.248534 " name="pixel0135"/> + <location y=" -0.246501 " name="pixel0136"/> + <location y=" -0.244468 " name="pixel0137"/> + <location y=" -0.242435 " name="pixel0138"/> + <location y=" -0.240401 " name="pixel0139"/> + <location y=" -0.238368 " name="pixel0140"/> + <location y=" -0.236335 " name="pixel0141"/> + <location y=" -0.234302 " name="pixel0142"/> + <location y=" -0.232269 " name="pixel0143"/> + <location y=" -0.230235 " name="pixel0144"/> + <location y=" -0.228202 " name="pixel0145"/> + <location y=" -0.226169 " name="pixel0146"/> + <location y=" -0.224136 " name="pixel0147"/> + <location y=" -0.222103 " name="pixel0148"/> + <location y=" -0.220069 " name="pixel0149"/> + <location y=" -0.218036 " name="pixel0150"/> + <location y=" -0.216003 " name="pixel0151"/> + <location y=" -0.213970 " name="pixel0152"/> + <location y=" -0.211937 " name="pixel0153"/> + <location y=" -0.209903 " name="pixel0154"/> + <location y=" -0.207870 " name="pixel0155"/> + <location y=" -0.205837 " name="pixel0156"/> + <location y=" -0.203804 " name="pixel0157"/> + <location y=" -0.201771 " name="pixel0158"/> + <location y=" -0.199737 " name="pixel0159"/> + <location y=" -0.197704 " name="pixel0160"/> + <location y=" -0.195671 " name="pixel0161"/> + <location y=" -0.193638 " name="pixel0162"/> + <location y=" -0.191604 " name="pixel0163"/> + <location y=" -0.189571 " name="pixel0164"/> + <location y=" -0.187538 " name="pixel0165"/> + <location y=" -0.185505 " name="pixel0166"/> + <location y=" -0.183472 " name="pixel0167"/> + <location y=" -0.181438 " name="pixel0168"/> + <location y=" -0.179405 " name="pixel0169"/> + <location y=" -0.177372 " name="pixel0170"/> + <location y=" -0.175339 " name="pixel0171"/> + <location y=" -0.173306 " name="pixel0172"/> + <location y=" -0.171272 " name="pixel0173"/> + <location y=" -0.169239 " name="pixel0174"/> + <location y=" -0.167206 " name="pixel0175"/> + <location y=" -0.165173 " name="pixel0176"/> + <location y=" -0.163140 " name="pixel0177"/> + <location y=" -0.161106 " name="pixel0178"/> + <location y=" -0.159073 " name="pixel0179"/> + <location y=" -0.157040 " name="pixel0180"/> + <location y=" -0.155007 " name="pixel0181"/> + <location y=" -0.152974 " name="pixel0182"/> + <location y=" -0.150940 " name="pixel0183"/> + <location y=" -0.148907 " name="pixel0184"/> + <location y=" -0.146874 " name="pixel0185"/> + <location y=" -0.144841 " name="pixel0186"/> + <location y=" -0.142808 " name="pixel0187"/> + <location y=" -0.140774 " name="pixel0188"/> + <location y=" -0.138741 " name="pixel0189"/> + <location y=" -0.136708 " name="pixel0190"/> + <location y=" -0.134675 " name="pixel0191"/> + <location y=" -0.132642 " name="pixel0192"/> + <location y=" -0.130608 " name="pixel0193"/> + <location y=" -0.128575 " name="pixel0194"/> + <location y=" -0.126542 " name="pixel0195"/> + <location y=" -0.124509 " name="pixel0196"/> + <location y=" -0.122476 " name="pixel0197"/> + <location y=" -0.120442 " name="pixel0198"/> + <location y=" -0.118409 " name="pixel0199"/> + <location y=" -0.116376 " name="pixel0200"/> + <location y=" -0.114343 " name="pixel0201"/> + <location y=" -0.112310 " name="pixel0202"/> + <location y=" -0.110276 " name="pixel0203"/> + <location y=" -0.108243 " name="pixel0204"/> + <location y=" -0.106210 " name="pixel0205"/> + <location y=" -0.104177 " name="pixel0206"/> + <location y=" -0.102144 " name="pixel0207"/> + <location y=" -0.100110 " name="pixel0208"/> + <location y=" -0.980771E-01" name="pixel0209"/> + <location y=" -0.960439E-01" name="pixel0210"/> + <location y=" -0.940107E-01" name="pixel0211"/> + <location y=" -0.919775E-01" name="pixel0212"/> + <location y=" -0.899443E-01" name="pixel0213"/> + <location y=" -0.879111E-01" name="pixel0214"/> + <location y=" -0.858779E-01" name="pixel0215"/> + <location y=" -0.838447E-01" name="pixel0216"/> + <location y=" -0.818115E-01" name="pixel0217"/> + <location y=" -0.797783E-01" name="pixel0218"/> + <location y=" -0.777451E-01" name="pixel0219"/> + <location y=" -0.757119E-01" name="pixel0220"/> + <location y=" -0.736787E-01" name="pixel0221"/> + <location y=" -0.716455E-01" name="pixel0222"/> + <location y=" -0.696123E-01" name="pixel0223"/> + <location y=" -0.675791E-01" name="pixel0224"/> + <location y=" -0.655459E-01" name="pixel0225"/> + <location y=" -0.635127E-01" name="pixel0226"/> + <location y=" -0.614795E-01" name="pixel0227"/> + <location y=" -0.594463E-01" name="pixel0228"/> + <location y=" -0.574131E-01" name="pixel0229"/> + <location y=" -0.553799E-01" name="pixel0230"/> + <location y=" -0.533467E-01" name="pixel0231"/> + <location y=" -0.513135E-01" name="pixel0232"/> + <location y=" -0.492803E-01" name="pixel0233"/> + <location y=" -0.472471E-01" name="pixel0234"/> + <location y=" -0.452139E-01" name="pixel0235"/> + <location y=" -0.431807E-01" name="pixel0236"/> + <location y=" -0.411475E-01" name="pixel0237"/> + <location y=" -0.391143E-01" name="pixel0238"/> + <location y=" -0.370811E-01" name="pixel0239"/> + <location y=" -0.350479E-01" name="pixel0240"/> + <location y=" -0.330146E-01" name="pixel0241"/> + <location y=" -0.309814E-01" name="pixel0242"/> + <location y=" -0.289482E-01" name="pixel0243"/> + <location y=" -0.269150E-01" name="pixel0244"/> + <location y=" -0.248818E-01" name="pixel0245"/> + <location y=" -0.228486E-01" name="pixel0246"/> + <location y=" -0.208154E-01" name="pixel0247"/> + <location y=" -0.187822E-01" name="pixel0248"/> + <location y=" -0.167490E-01" name="pixel0249"/> + <location y=" -0.147158E-01" name="pixel0250"/> + <location y=" -0.126826E-01" name="pixel0251"/> + <location y=" -0.106494E-01" name="pixel0252"/> + <location y=" -0.861621E-02" name="pixel0253"/> + <location y=" -0.658301E-02" name="pixel0254"/> + <location y=" -0.454980E-02" name="pixel0255"/> + <location y=" -0.251660E-02" name="pixel0256"/> + <location y=" -0.483398E-03" name="pixel0257"/> + <location y=" 0.154980E-02" name="pixel0258"/> + <location y=" 0.358301E-02" name="pixel0259"/> + <location y=" 0.561621E-02" name="pixel0260"/> + <location y=" 0.764941E-02" name="pixel0261"/> + <location y=" 0.968262E-02" name="pixel0262"/> + <location y=" 0.117158E-01" name="pixel0263"/> + <location y=" 0.137490E-01" name="pixel0264"/> + <location y=" 0.157822E-01" name="pixel0265"/> + <location y=" 0.178154E-01" name="pixel0266"/> + <location y=" 0.198486E-01" name="pixel0267"/> + <location y=" 0.218818E-01" name="pixel0268"/> + <location y=" 0.239150E-01" name="pixel0269"/> + <location y=" 0.259482E-01" name="pixel0270"/> + <location y=" 0.279814E-01" name="pixel0271"/> + <location y=" 0.300146E-01" name="pixel0272"/> + <location y=" 0.320479E-01" name="pixel0273"/> + <location y=" 0.340811E-01" name="pixel0274"/> + <location y=" 0.361143E-01" name="pixel0275"/> + <location y=" 0.381475E-01" name="pixel0276"/> + <location y=" 0.401807E-01" name="pixel0277"/> + <location y=" 0.422139E-01" name="pixel0278"/> + <location y=" 0.442471E-01" name="pixel0279"/> + <location y=" 0.462803E-01" name="pixel0280"/> + <location y=" 0.483135E-01" name="pixel0281"/> + <location y=" 0.503467E-01" name="pixel0282"/> + <location y=" 0.523799E-01" name="pixel0283"/> + <location y=" 0.544131E-01" name="pixel0284"/> + <location y=" 0.564463E-01" name="pixel0285"/> + <location y=" 0.584795E-01" name="pixel0286"/> + <location y=" 0.605127E-01" name="pixel0287"/> + <location y=" 0.625459E-01" name="pixel0288"/> + <location y=" 0.645791E-01" name="pixel0289"/> + <location y=" 0.666123E-01" name="pixel0290"/> + <location y=" 0.686455E-01" name="pixel0291"/> + <location y=" 0.706787E-01" name="pixel0292"/> + <location y=" 0.727119E-01" name="pixel0293"/> + <location y=" 0.747451E-01" name="pixel0294"/> + <location y=" 0.767783E-01" name="pixel0295"/> + <location y=" 0.788115E-01" name="pixel0296"/> + <location y=" 0.808447E-01" name="pixel0297"/> + <location y=" 0.828779E-01" name="pixel0298"/> + <location y=" 0.849111E-01" name="pixel0299"/> + <location y=" 0.869443E-01" name="pixel0300"/> + <location y=" 0.889775E-01" name="pixel0301"/> + <location y=" 0.910107E-01" name="pixel0302"/> + <location y=" 0.930439E-01" name="pixel0303"/> + <location y=" 0.950771E-01" name="pixel0304"/> + <location y=" 0.971104E-01" name="pixel0305"/> + <location y=" 0.991436E-01" name="pixel0306"/> + <location y=" 0.101177 " name="pixel0307"/> + <location y=" 0.103210 " name="pixel0308"/> + <location y=" 0.105243 " name="pixel0309"/> + <location y=" 0.107276 " name="pixel0310"/> + <location y=" 0.109310 " name="pixel0311"/> + <location y=" 0.111343 " name="pixel0312"/> + <location y=" 0.113376 " name="pixel0313"/> + <location y=" 0.115409 " name="pixel0314"/> + <location y=" 0.117442 " name="pixel0315"/> + <location y=" 0.119476 " name="pixel0316"/> + <location y=" 0.121509 " name="pixel0317"/> + <location y=" 0.123542 " name="pixel0318"/> + <location y=" 0.125575 " name="pixel0319"/> + <location y=" 0.127608 " name="pixel0320"/> + <location y=" 0.129642 " name="pixel0321"/> + <location y=" 0.131675 " name="pixel0322"/> + <location y=" 0.133708 " name="pixel0323"/> + <location y=" 0.135741 " name="pixel0324"/> + <location y=" 0.137774 " name="pixel0325"/> + <location y=" 0.139808 " name="pixel0326"/> + <location y=" 0.141841 " name="pixel0327"/> + <location y=" 0.143874 " name="pixel0328"/> + <location y=" 0.145907 " name="pixel0329"/> + <location y=" 0.147940 " name="pixel0330"/> + <location y=" 0.149974 " name="pixel0331"/> + <location y=" 0.152007 " name="pixel0332"/> + <location y=" 0.154040 " name="pixel0333"/> + <location y=" 0.156073 " name="pixel0334"/> + <location y=" 0.158106 " name="pixel0335"/> + <location y=" 0.160140 " name="pixel0336"/> + <location y=" 0.162173 " name="pixel0337"/> + <location y=" 0.164206 " name="pixel0338"/> + <location y=" 0.166239 " name="pixel0339"/> + <location y=" 0.168272 " name="pixel0340"/> + <location y=" 0.170306 " name="pixel0341"/> + <location y=" 0.172339 " name="pixel0342"/> + <location y=" 0.174372 " name="pixel0343"/> + <location y=" 0.176405 " name="pixel0344"/> + <location y=" 0.178438 " name="pixel0345"/> + <location y=" 0.180472 " name="pixel0346"/> + <location y=" 0.182505 " name="pixel0347"/> + <location y=" 0.184538 " name="pixel0348"/> + <location y=" 0.186571 " name="pixel0349"/> + <location y=" 0.188604 " name="pixel0350"/> + <location y=" 0.190638 " name="pixel0351"/> + <location y=" 0.192671 " name="pixel0352"/> + <location y=" 0.194704 " name="pixel0353"/> + <location y=" 0.196737 " name="pixel0354"/> + <location y=" 0.198771 " name="pixel0355"/> + <location y=" 0.200804 " name="pixel0356"/> + <location y=" 0.202837 " name="pixel0357"/> + <location y=" 0.204870 " name="pixel0358"/> + <location y=" 0.206903 " name="pixel0359"/> + <location y=" 0.208937 " name="pixel0360"/> + <location y=" 0.210970 " name="pixel0361"/> + <location y=" 0.213003 " name="pixel0362"/> + <location y=" 0.215036 " name="pixel0363"/> + <location y=" 0.217069 " name="pixel0364"/> + <location y=" 0.219103 " name="pixel0365"/> + <location y=" 0.221136 " name="pixel0366"/> + <location y=" 0.223169 " name="pixel0367"/> + <location y=" 0.225202 " name="pixel0368"/> + <location y=" 0.227235 " name="pixel0369"/> + <location y=" 0.229269 " name="pixel0370"/> + <location y=" 0.231302 " name="pixel0371"/> + <location y=" 0.233335 " name="pixel0372"/> + <location y=" 0.235368 " name="pixel0373"/> + <location y=" 0.237401 " name="pixel0374"/> + <location y=" 0.239435 " name="pixel0375"/> + <location y=" 0.241468 " name="pixel0376"/> + <location y=" 0.243501 " name="pixel0377"/> + <location y=" 0.245534 " name="pixel0378"/> + <location y=" 0.247567 " name="pixel0379"/> + <location y=" 0.249601 " name="pixel0380"/> + <location y=" 0.251634 " name="pixel0381"/> + <location y=" 0.253667 " name="pixel0382"/> + <location y=" 0.255700 " name="pixel0383"/> + <location y=" 0.257733 " name="pixel0384"/> + <location y=" 0.259767 " name="pixel0385"/> + <location y=" 0.261800 " name="pixel0386"/> + <location y=" 0.263833 " name="pixel0387"/> + <location y=" 0.265866 " name="pixel0388"/> + <location y=" 0.267899 " name="pixel0389"/> + <location y=" 0.269933 " name="pixel0390"/> + <location y=" 0.271966 " name="pixel0391"/> + <location y=" 0.273999 " name="pixel0392"/> + <location y=" 0.276032 " name="pixel0393"/> + <location y=" 0.278065 " name="pixel0394"/> + <location y=" 0.280099 " name="pixel0395"/> + <location y=" 0.282132 " name="pixel0396"/> + <location y=" 0.284165 " name="pixel0397"/> + <location y=" 0.286198 " name="pixel0398"/> + <location y=" 0.288231 " name="pixel0399"/> + <location y=" 0.290265 " name="pixel0400"/> + <location y=" 0.292298 " name="pixel0401"/> + <location y=" 0.294331 " name="pixel0402"/> + <location y=" 0.296364 " name="pixel0403"/> + <location y=" 0.298397 " name="pixel0404"/> + <location y=" 0.300431 " name="pixel0405"/> + <location y=" 0.302464 " name="pixel0406"/> + <location y=" 0.304497 " name="pixel0407"/> + <location y=" 0.306530 " name="pixel0408"/> + <location y=" 0.308563 " name="pixel0409"/> + <location y=" 0.310597 " name="pixel0410"/> + <location y=" 0.312630 " name="pixel0411"/> + <location y=" 0.314663 " name="pixel0412"/> + <location y=" 0.316696 " name="pixel0413"/> + <location y=" 0.318729 " name="pixel0414"/> + <location y=" 0.320763 " name="pixel0415"/> + <location y=" 0.322796 " name="pixel0416"/> + <location y=" 0.324829 " name="pixel0417"/> + <location y=" 0.326862 " name="pixel0418"/> + <location y=" 0.328896 " name="pixel0419"/> + <location y=" 0.330929 " name="pixel0420"/> + <location y=" 0.332962 " name="pixel0421"/> + <location y=" 0.334995 " name="pixel0422"/> + <location y=" 0.337028 " name="pixel0423"/> + <location y=" 0.339062 " name="pixel0424"/> + <location y=" 0.341095 " name="pixel0425"/> + <location y=" 0.343128 " name="pixel0426"/> + <location y=" 0.345161 " name="pixel0427"/> + <location y=" 0.347194 " name="pixel0428"/> + <location y=" 0.349228 " name="pixel0429"/> + <location y=" 0.351261 " name="pixel0430"/> + <location y=" 0.353294 " name="pixel0431"/> + <location y=" 0.355327 " name="pixel0432"/> + <location y=" 0.357360 " name="pixel0433"/> + <location y=" 0.359394 " name="pixel0434"/> + <location y=" 0.361427 " name="pixel0435"/> + <location y=" 0.363460 " name="pixel0436"/> + <location y=" 0.365493 " name="pixel0437"/> + <location y=" 0.367526 " name="pixel0438"/> + <location y=" 0.369560 " name="pixel0439"/> + <location y=" 0.371593 " name="pixel0440"/> + <location y=" 0.373626 " name="pixel0441"/> + <location y=" 0.375659 " name="pixel0442"/> + <location y=" 0.377692 " name="pixel0443"/> + <location y=" 0.379726 " name="pixel0444"/> + <location y=" 0.381759 " name="pixel0445"/> + <location y=" 0.383792 " name="pixel0446"/> + <location y=" 0.385825 " name="pixel0447"/> + <location y=" 0.387858 " name="pixel0448"/> + <location y=" 0.389892 " name="pixel0449"/> + <location y=" 0.391925 " name="pixel0450"/> + <location y=" 0.393958 " name="pixel0451"/> + <location y=" 0.395991 " name="pixel0452"/> + <location y=" 0.398024 " name="pixel0453"/> + <location y=" 0.400058 " name="pixel0454"/> + <location y=" 0.402091 " name="pixel0455"/> + <location y=" 0.404124 " name="pixel0456"/> + <location y=" 0.406157 " name="pixel0457"/> + <location y=" 0.408190 " name="pixel0458"/> + <location y=" 0.410224 " name="pixel0459"/> + <location y=" 0.412257 " name="pixel0460"/> + <location y=" 0.414290 " name="pixel0461"/> + <location y=" 0.416323 " name="pixel0462"/> + <location y=" 0.418356 " name="pixel0463"/> + <location y=" 0.420390 " name="pixel0464"/> + <location y=" 0.422423 " name="pixel0465"/> + <location y=" 0.424456 " name="pixel0466"/> + <location y=" 0.426489 " name="pixel0467"/> + <location y=" 0.428522 " name="pixel0468"/> + <location y=" 0.430556 " name="pixel0469"/> + <location y=" 0.432589 " name="pixel0470"/> + <location y=" 0.434622 " name="pixel0471"/> + <location y=" 0.436655 " name="pixel0472"/> + <location y=" 0.438688 " name="pixel0473"/> + <location y=" 0.440722 " name="pixel0474"/> + <location y=" 0.442755 " name="pixel0475"/> + <location y=" 0.444788 " name="pixel0476"/> + <location y=" 0.446821 " name="pixel0477"/> + <location y=" 0.448854 " name="pixel0478"/> + <location y=" 0.450888 " name="pixel0479"/> + <location y=" 0.452921 " name="pixel0480"/> + <location y=" 0.454954 " name="pixel0481"/> + <location y=" 0.456987 " name="pixel0482"/> + <location y=" 0.459021 " name="pixel0483"/> + <location y=" 0.461054 " name="pixel0484"/> + <location y=" 0.463087 " name="pixel0485"/> + <location y=" 0.465120 " name="pixel0486"/> + <location y=" 0.467153 " name="pixel0487"/> + <location y=" 0.469187 " name="pixel0488"/> + <location y=" 0.471220 " name="pixel0489"/> + <location y=" 0.473253 " name="pixel0490"/> + <location y=" 0.475286 " name="pixel0491"/> + <location y=" 0.477319 " name="pixel0492"/> + <location y=" 0.479353 " name="pixel0493"/> + <location y=" 0.481386 " name="pixel0494"/> + <location y=" 0.483419 " name="pixel0495"/> + <location y=" 0.485452 " name="pixel0496"/> + <location y=" 0.487485 " name="pixel0497"/> + <location y=" 0.489519 " name="pixel0498"/> + <location y=" 0.491552 " name="pixel0499"/> + <location y=" 0.493585 " name="pixel0500"/> + <location y=" 0.495618 " name="pixel0501"/> + <location y=" 0.497651 " name="pixel0502"/> + <location y=" 0.499685 " name="pixel0503"/> + <location y=" 0.501718 " name="pixel0504"/> + <location y=" 0.503751 " name="pixel0505"/> + <location y=" 0.505784 " name="pixel0506"/> + <location y=" 0.507817 " name="pixel0507"/> + <location y=" 0.509851 " name="pixel0508"/> + <location y=" 0.511884 " name="pixel0509"/> + <location y=" 0.513917 " name="pixel0510"/> + <location y=" 0.515950 " name="pixel0511"/> + <location y=" 0.517983 " name="pixel0512"/> + </component> + </type> + + <type name="monitor" is="monitor"> + <properties/> + <cylinder id="some-shape"> + <centre-of-bottom-base r="0.0" t="0.0" p="0.0" /> + <axis x="0.0" y="0.0" z="1.0" /> + <radius val="0.01" /> + <height val="0.03" /> + </cylinder> + <algebra val="some-shape" /> + </type> + + <type name="pixel" is="detector"> + <cylinder id="cyl-approx"> + <centre-of-bottom-base r="0.0" t="0.0" p="0.0" /> + <axis x="0.0" y="0.2" z="0.0" /> + <radius val="0.004" /> + <height val=" 0.203320E-02" /> + </cylinder> + <algebra val="cyl-approx" /> + </type> + + <!-- MONITOR ID LISTS --> + <idlist idname="monitors"> + <id start="1" end="5" /> + </idlist> + + <!-- DETECTOR ID LISTS --> + <idlist idname="panel01"> + <id start="01707000" end="01707511" /> + <id start="01705000" end="01705511" /> + <id start="01703000" end="01703511" /> + <id start="01701000" end="01701511" /> + <id start="01623000" end="01623511" /> + <id start="01621000" end="01621511" /> + <id start="01619000" end="01619511" /> + <id start="01617000" end="01617511" /> + <id start="01615000" end="01615511" /> + <id start="01613000" end="01613511" /> + <id start="01611000" end="01611511" /> + <id start="01609000" end="01609511" /> + <id start="01607000" end="01607511" /> + <id start="01605000" end="01605511" /> + <id start="01603000" end="01603511" /> + <id start="01601000" end="01601511" /> + <id start="01523000" end="01523511" /> + <id start="01521000" end="01521511" /> + <id start="01519000" end="01519511" /> + <id start="01517000" end="01517511" /> + <id start="01515000" end="01515511" /> + <id start="01513000" end="01513511" /> + <id start="01511000" end="01511511" /> + <id start="01509000" end="01509511" /> + <id start="01507000" end="01507511" /> + <id start="01505000" end="01505511" /> + <id start="01503000" end="01503511" /> + <id start="01501000" end="01501511" /> + <id start="01423000" end="01423511" /> + <id start="01421000" end="01421511" /> + <id start="01419000" end="01419511" /> + <id start="01417000" end="01417511" /> + <id start="01415000" end="01415511" /> + <id start="01413000" end="01413511" /> + <id start="01411000" end="01411511" /> + <id start="01409000" end="01409511" /> + <id start="01407000" end="01407511" /> + <id start="01405000" end="01405511" /> + <id start="01403000" end="01403511" /> + <id start="01401000" end="01401511" /> + <id start="01323000" end="01323511" /> + <id start="01321000" end="01321511" /> + <id start="01319000" end="01319511" /> + <id start="01317000" end="01317511" /> + <id start="01315000" end="01315511" /> + <id start="01313000" end="01313511" /> + <id start="01311000" end="01311511" /> + <id start="01309000" end="01309511" /> + <id start="01307000" end="01307511" /> + <id start="01305000" end="01305511" /> + <id start="01303000" end="01303511" /> + <id start="01301000" end="01301511" /> + <id start="01223000" end="01223511" /> + <id start="01221000" end="01221511" /> + <id start="01219000" end="01219511" /> + <id start="01217000" end="01217511" /> + <id start="01215000" end="01215511" /> + <id start="01213000" end="01213511" /> + <id start="01211000" end="01211511" /> + <id start="01209000" end="01209511" /> + <id start="01207000" end="01207511" /> + <id start="01205000" end="01205511" /> + <id start="01203000" end="01203511" /> + <id start="01201000" end="01201511" /> + <id start="01123000" end="01123511" /> + <id start="01121000" end="01121511" /> + <id start="01119000" end="01119511" /> + <id start="01117000" end="01117511" /> + <id start="01115000" end="01115511" /> + <id start="01113000" end="01113511" /> + <id start="01111000" end="01111511" /> + <id start="01109000" end="01109511" /> + <id start="01107000" end="01107511" /> + <id start="01105000" end="01105511" /> + <id start="01103000" end="01103511" /> + <id start="01101000" end="01101511" /> + <id start="01706000" end="01706511" /> + <id start="01704000" end="01704511" /> + <id start="01702000" end="01702511" /> + <id start="01700000" end="01700511" /> + <id start="01622000" end="01622511" /> + <id start="01620000" end="01620511" /> + <id start="01618000" end="01618511" /> + <id start="01616000" end="01616511" /> + <id start="01614000" end="01614511" /> + <id start="01612000" end="01612511" /> + <id start="01610000" end="01610511" /> + <id start="01608000" end="01608511" /> + <id start="01606000" end="01606511" /> + <id start="01604000" end="01604511" /> + <id start="01602000" end="01602511" /> + <id start="01600000" end="01600511" /> + <id start="01522000" end="01522511" /> + <id start="01520000" end="01520511" /> + <id start="01518000" end="01518511" /> + <id start="01516000" end="01516511" /> + <id start="01514000" end="01514511" /> + <id start="01512000" end="01512511" /> + <id start="01510000" end="01510511" /> + <id start="01508000" end="01508511" /> + <id start="01506000" end="01506511" /> + <id start="01504000" end="01504511" /> + <id start="01502000" end="01502511" /> + <id start="01500000" end="01500511" /> + <id start="01422000" end="01422511" /> + <id start="01420000" end="01420511" /> + <id start="01418000" end="01418511" /> + <id start="01416000" end="01416511" /> + <id start="01414000" end="01414511" /> + <id start="01412000" end="01412511" /> + <id start="01410000" end="01410511" /> + <id start="01408000" end="01408511" /> + <id start="01406000" end="01406511" /> + <id start="01404000" end="01404511" /> + <id start="01402000" end="01402511" /> + <id start="01400000" end="01400511" /> + <id start="01322000" end="01322511" /> + <id start="01320000" end="01320511" /> + <id start="01318000" end="01318511" /> + <id start="01316000" end="01316511" /> + <id start="01314000" end="01314511" /> + <id start="01312000" end="01312511" /> + <id start="01310000" end="01310511" /> + <id start="01308000" end="01308511" /> + <id start="01306000" end="01306511" /> + <id start="01304000" end="01304511" /> + <id start="01302000" end="01302511" /> + <id start="01300000" end="01300511" /> + <id start="01222000" end="01222511" /> + <id start="01220000" end="01220511" /> + <id start="01218000" end="01218511" /> + <id start="01216000" end="01216511" /> + <id start="01214000" end="01214511" /> + <id start="01212000" end="01212511" /> + <id start="01210000" end="01210511" /> + <id start="01208000" end="01208511" /> + <id start="01206000" end="01206511" /> + <id start="01204000" end="01204511" /> + <id start="01202000" end="01202511" /> + <id start="01200000" end="01200511" /> + <id start="01122000" end="01122511" /> + <id start="01120000" end="01120511" /> + <id start="01118000" end="01118511" /> + <id start="01116000" end="01116511" /> + <id start="01114000" end="01114511" /> + <id start="01112000" end="01112511" /> + <id start="01110000" end="01110511" /> + <id start="01108000" end="01108511" /> + <id start="01106000" end="01106511" /> + <id start="01104000" end="01104511" /> + <id start="01102000" end="01102511" /> + <id start="01100000" end="01100511" /> + </idlist> + <idlist idname="panel02"> + <id start="02707000" end="02707511" /> + <id start="02705000" end="02705511" /> + <id start="02703000" end="02703511" /> + <id start="02701000" end="02701511" /> + <id start="02623000" end="02623511" /> + <id start="02621000" end="02621511" /> + <id start="02619000" end="02619511" /> + <id start="02617000" end="02617511" /> + <id start="02615000" end="02615511" /> + <id start="02613000" end="02613511" /> + <id start="02611000" end="02611511" /> + <id start="02609000" end="02609511" /> + <id start="02607000" end="02607511" /> + <id start="02605000" end="02605511" /> + <id start="02603000" end="02603511" /> + <id start="02601000" end="02601511" /> + <id start="02523000" end="02523511" /> + <id start="02521000" end="02521511" /> + <id start="02519000" end="02519511" /> + <id start="02517000" end="02517511" /> + <id start="02515000" end="02515511" /> + <id start="02513000" end="02513511" /> + <id start="02511000" end="02511511" /> + <id start="02509000" end="02509511" /> + <id start="02507000" end="02507511" /> + <id start="02505000" end="02505511" /> + <id start="02503000" end="02503511" /> + <id start="02501000" end="02501511" /> + <id start="02423000" end="02423511" /> + <id start="02421000" end="02421511" /> + <id start="02419000" end="02419511" /> + <id start="02417000" end="02417511" /> + <id start="02415000" end="02415511" /> + <id start="02413000" end="02413511" /> + <id start="02411000" end="02411511" /> + <id start="02409000" end="02409511" /> + <id start="02407000" end="02407511" /> + <id start="02405000" end="02405511" /> + <id start="02403000" end="02403511" /> + <id start="02401000" end="02401511" /> + <id start="02323000" end="02323511" /> + <id start="02321000" end="02321511" /> + <id start="02319000" end="02319511" /> + <id start="02317000" end="02317511" /> + <id start="02315000" end="02315511" /> + <id start="02313000" end="02313511" /> + <id start="02311000" end="02311511" /> + <id start="02309000" end="02309511" /> + <id start="02307000" end="02307511" /> + <id start="02305000" end="02305511" /> + <id start="02303000" end="02303511" /> + <id start="02301000" end="02301511" /> + <id start="02223000" end="02223511" /> + <id start="02221000" end="02221511" /> + <id start="02219000" end="02219511" /> + <id start="02217000" end="02217511" /> + <id start="02215000" end="02215511" /> + <id start="02213000" end="02213511" /> + <id start="02211000" end="02211511" /> + <id start="02209000" end="02209511" /> + <id start="02207000" end="02207511" /> + <id start="02205000" end="02205511" /> + <id start="02203000" end="02203511" /> + <id start="02201000" end="02201511" /> + <id start="02123000" end="02123511" /> + <id start="02121000" end="02121511" /> + <id start="02119000" end="02119511" /> + <id start="02117000" end="02117511" /> + <id start="02115000" end="02115511" /> + <id start="02113000" end="02113511" /> + <id start="02111000" end="02111511" /> + <id start="02109000" end="02109511" /> + <id start="02107000" end="02107511" /> + <id start="02105000" end="02105511" /> + <id start="02103000" end="02103511" /> + <id start="02101000" end="02101511" /> + <id start="02706000" end="02706511" /> + <id start="02704000" end="02704511" /> + <id start="02702000" end="02702511" /> + <id start="02700000" end="02700511" /> + <id start="02622000" end="02622511" /> + <id start="02620000" end="02620511" /> + <id start="02618000" end="02618511" /> + <id start="02616000" end="02616511" /> + <id start="02614000" end="02614511" /> + <id start="02612000" end="02612511" /> + <id start="02610000" end="02610511" /> + <id start="02608000" end="02608511" /> + <id start="02606000" end="02606511" /> + <id start="02604000" end="02604511" /> + <id start="02602000" end="02602511" /> + <id start="02600000" end="02600511" /> + <id start="02522000" end="02522511" /> + <id start="02520000" end="02520511" /> + <id start="02518000" end="02518511" /> + <id start="02516000" end="02516511" /> + <id start="02514000" end="02514511" /> + <id start="02512000" end="02512511" /> + <id start="02510000" end="02510511" /> + <id start="02508000" end="02508511" /> + <id start="02506000" end="02506511" /> + <id start="02504000" end="02504511" /> + <id start="02502000" end="02502511" /> + <id start="02500000" end="02500511" /> + <id start="02422000" end="02422511" /> + <id start="02420000" end="02420511" /> + <id start="02418000" end="02418511" /> + <id start="02416000" end="02416511" /> + <id start="02414000" end="02414511" /> + <id start="02412000" end="02412511" /> + <id start="02410000" end="02410511" /> + <id start="02408000" end="02408511" /> + <id start="02406000" end="02406511" /> + <id start="02404000" end="02404511" /> + <id start="02402000" end="02402511" /> + <id start="02400000" end="02400511" /> + <id start="02322000" end="02322511" /> + <id start="02320000" end="02320511" /> + <id start="02318000" end="02318511" /> + <id start="02316000" end="02316511" /> + <id start="02314000" end="02314511" /> + <id start="02312000" end="02312511" /> + <id start="02310000" end="02310511" /> + <id start="02308000" end="02308511" /> + <id start="02306000" end="02306511" /> + <id start="02304000" end="02304511" /> + <id start="02302000" end="02302511" /> + <id start="02300000" end="02300511" /> + <id start="02222000" end="02222511" /> + <id start="02220000" end="02220511" /> + <id start="02218000" end="02218511" /> + <id start="02216000" end="02216511" /> + <id start="02214000" end="02214511" /> + <id start="02212000" end="02212511" /> + <id start="02210000" end="02210511" /> + <id start="02208000" end="02208511" /> + <id start="02206000" end="02206511" /> + <id start="02204000" end="02204511" /> + <id start="02202000" end="02202511" /> + <id start="02200000" end="02200511" /> + <id start="02122000" end="02122511" /> + <id start="02120000" end="02120511" /> + <id start="02118000" end="02118511" /> + <id start="02116000" end="02116511" /> + <id start="02114000" end="02114511" /> + <id start="02112000" end="02112511" /> + <id start="02110000" end="02110511" /> + <id start="02108000" end="02108511" /> + <id start="02106000" end="02106511" /> + <id start="02104000" end="02104511" /> + <id start="02102000" end="02102511" /> + <id start="02100000" end="02100511" /> + </idlist> + <idlist idname="panel03"> + <id start="03707000" end="03707511" /> + <id start="03705000" end="03705511" /> + <id start="03703000" end="03703511" /> + <id start="03701000" end="03701511" /> + <id start="03623000" end="03623511" /> + <id start="03621000" end="03621511" /> + <id start="03619000" end="03619511" /> + <id start="03617000" end="03617511" /> + <id start="03615000" end="03615511" /> + <id start="03613000" end="03613511" /> + <id start="03611000" end="03611511" /> + <id start="03609000" end="03609511" /> + <id start="03607000" end="03607511" /> + <id start="03605000" end="03605511" /> + <id start="03603000" end="03603511" /> + <id start="03601000" end="03601511" /> + <id start="03523000" end="03523511" /> + <id start="03521000" end="03521511" /> + <id start="03519000" end="03519511" /> + <id start="03517000" end="03517511" /> + <id start="03515000" end="03515511" /> + <id start="03513000" end="03513511" /> + <id start="03511000" end="03511511" /> + <id start="03509000" end="03509511" /> + <id start="03507000" end="03507511" /> + <id start="03505000" end="03505511" /> + <id start="03503000" end="03503511" /> + <id start="03501000" end="03501511" /> + <id start="03423000" end="03423511" /> + <id start="03421000" end="03421511" /> + <id start="03419000" end="03419511" /> + <id start="03417000" end="03417511" /> + <id start="03415000" end="03415511" /> + <id start="03413000" end="03413511" /> + <id start="03411000" end="03411511" /> + <id start="03409000" end="03409511" /> + <id start="03407000" end="03407511" /> + <id start="03405000" end="03405511" /> + <id start="03403000" end="03403511" /> + <id start="03401000" end="03401511" /> + <id start="03323000" end="03323511" /> + <id start="03321000" end="03321511" /> + <id start="03319000" end="03319511" /> + <id start="03317000" end="03317511" /> + <id start="03315000" end="03315511" /> + <id start="03313000" end="03313511" /> + <id start="03311000" end="03311511" /> + <id start="03309000" end="03309511" /> + <id start="03307000" end="03307511" /> + <id start="03305000" end="03305511" /> + <id start="03303000" end="03303511" /> + <id start="03301000" end="03301511" /> + <id start="03223000" end="03223511" /> + <id start="03221000" end="03221511" /> + <id start="03219000" end="03219511" /> + <id start="03217000" end="03217511" /> + <id start="03215000" end="03215511" /> + <id start="03213000" end="03213511" /> + <id start="03211000" end="03211511" /> + <id start="03209000" end="03209511" /> + <id start="03207000" end="03207511" /> + <id start="03205000" end="03205511" /> + <id start="03203000" end="03203511" /> + <id start="03201000" end="03201511" /> + <id start="03123000" end="03123511" /> + <id start="03121000" end="03121511" /> + <id start="03119000" end="03119511" /> + <id start="03117000" end="03117511" /> + <id start="03115000" end="03115511" /> + <id start="03113000" end="03113511" /> + <id start="03111000" end="03111511" /> + <id start="03109000" end="03109511" /> + <id start="03107000" end="03107511" /> + <id start="03105000" end="03105511" /> + <id start="03103000" end="03103511" /> + <id start="03101000" end="03101511" /> + <id start="03706000" end="03706511" /> + <id start="03704000" end="03704511" /> + <id start="03702000" end="03702511" /> + <id start="03700000" end="03700511" /> + <id start="03622000" end="03622511" /> + <id start="03620000" end="03620511" /> + <id start="03618000" end="03618511" /> + <id start="03616000" end="03616511" /> + <id start="03614000" end="03614511" /> + <id start="03612000" end="03612511" /> + <id start="03610000" end="03610511" /> + <id start="03608000" end="03608511" /> + <id start="03606000" end="03606511" /> + <id start="03604000" end="03604511" /> + <id start="03602000" end="03602511" /> + <id start="03600000" end="03600511" /> + <id start="03522000" end="03522511" /> + <id start="03520000" end="03520511" /> + <id start="03518000" end="03518511" /> + <id start="03516000" end="03516511" /> + <id start="03514000" end="03514511" /> + <id start="03512000" end="03512511" /> + <id start="03510000" end="03510511" /> + <id start="03508000" end="03508511" /> + <id start="03506000" end="03506511" /> + <id start="03504000" end="03504511" /> + <id start="03502000" end="03502511" /> + <id start="03500000" end="03500511" /> + <id start="03422000" end="03422511" /> + <id start="03420000" end="03420511" /> + <id start="03418000" end="03418511" /> + <id start="03416000" end="03416511" /> + <id start="03414000" end="03414511" /> + <id start="03412000" end="03412511" /> + <id start="03410000" end="03410511" /> + <id start="03408000" end="03408511" /> + <id start="03406000" end="03406511" /> + <id start="03404000" end="03404511" /> + <id start="03402000" end="03402511" /> + <id start="03400000" end="03400511" /> + <id start="03322000" end="03322511" /> + <id start="03320000" end="03320511" /> + <id start="03318000" end="03318511" /> + <id start="03316000" end="03316511" /> + <id start="03314000" end="03314511" /> + <id start="03312000" end="03312511" /> + <id start="03310000" end="03310511" /> + <id start="03308000" end="03308511" /> + <id start="03306000" end="03306511" /> + <id start="03304000" end="03304511" /> + <id start="03302000" end="03302511" /> + <id start="03300000" end="03300511" /> + <id start="03222000" end="03222511" /> + <id start="03220000" end="03220511" /> + <id start="03218000" end="03218511" /> + <id start="03216000" end="03216511" /> + <id start="03214000" end="03214511" /> + <id start="03212000" end="03212511" /> + <id start="03210000" end="03210511" /> + <id start="03208000" end="03208511" /> + <id start="03206000" end="03206511" /> + <id start="03204000" end="03204511" /> + <id start="03202000" end="03202511" /> + <id start="03200000" end="03200511" /> + <id start="03122000" end="03122511" /> + <id start="03120000" end="03120511" /> + <id start="03118000" end="03118511" /> + <id start="03116000" end="03116511" /> + <id start="03114000" end="03114511" /> + <id start="03112000" end="03112511" /> + <id start="03110000" end="03110511" /> + <id start="03108000" end="03108511" /> + <id start="03106000" end="03106511" /> + <id start="03104000" end="03104511" /> + <id start="03102000" end="03102511" /> + <id start="03100000" end="03100511" /> + </idlist> + <idlist idname="panel04"> + <id start="04707000" end="04707511" /> + <id start="04705000" end="04705511" /> + <id start="04703000" end="04703511" /> + <id start="04701000" end="04701511" /> + <id start="04623000" end="04623511" /> + <id start="04621000" end="04621511" /> + <id start="04619000" end="04619511" /> + <id start="04617000" end="04617511" /> + <id start="04615000" end="04615511" /> + <id start="04613000" end="04613511" /> + <id start="04611000" end="04611511" /> + <id start="04609000" end="04609511" /> + <id start="04607000" end="04607511" /> + <id start="04605000" end="04605511" /> + <id start="04603000" end="04603511" /> + <id start="04601000" end="04601511" /> + <id start="04523000" end="04523511" /> + <id start="04521000" end="04521511" /> + <id start="04519000" end="04519511" /> + <id start="04517000" end="04517511" /> + <id start="04515000" end="04515511" /> + <id start="04513000" end="04513511" /> + <id start="04511000" end="04511511" /> + <id start="04509000" end="04509511" /> + <id start="04507000" end="04507511" /> + <id start="04505000" end="04505511" /> + <id start="04503000" end="04503511" /> + <id start="04501000" end="04501511" /> + <id start="04423000" end="04423511" /> + <id start="04421000" end="04421511" /> + <id start="04419000" end="04419511" /> + <id start="04417000" end="04417511" /> + <id start="04415000" end="04415511" /> + <id start="04413000" end="04413511" /> + <id start="04411000" end="04411511" /> + <id start="04409000" end="04409511" /> + <id start="04407000" end="04407511" /> + <id start="04405000" end="04405511" /> + <id start="04403000" end="04403511" /> + <id start="04401000" end="04401511" /> + <id start="04323000" end="04323511" /> + <id start="04321000" end="04321511" /> + <id start="04319000" end="04319511" /> + <id start="04317000" end="04317511" /> + <id start="04315000" end="04315511" /> + <id start="04313000" end="04313511" /> + <id start="04311000" end="04311511" /> + <id start="04309000" end="04309511" /> + <id start="04307000" end="04307511" /> + <id start="04305000" end="04305511" /> + <id start="04303000" end="04303511" /> + <id start="04301000" end="04301511" /> + <id start="04223000" end="04223511" /> + <id start="04221000" end="04221511" /> + <id start="04219000" end="04219511" /> + <id start="04217000" end="04217511" /> + <id start="04215000" end="04215511" /> + <id start="04213000" end="04213511" /> + <id start="04211000" end="04211511" /> + <id start="04209000" end="04209511" /> + <id start="04207000" end="04207511" /> + <id start="04205000" end="04205511" /> + <id start="04203000" end="04203511" /> + <id start="04201000" end="04201511" /> + <id start="04123000" end="04123511" /> + <id start="04121000" end="04121511" /> + <id start="04119000" end="04119511" /> + <id start="04117000" end="04117511" /> + <id start="04115000" end="04115511" /> + <id start="04113000" end="04113511" /> + <id start="04111000" end="04111511" /> + <id start="04109000" end="04109511" /> + <id start="04107000" end="04107511" /> + <id start="04105000" end="04105511" /> + <id start="04103000" end="04103511" /> + <id start="04101000" end="04101511" /> + <id start="04706000" end="04706511" /> + <id start="04704000" end="04704511" /> + <id start="04702000" end="04702511" /> + <id start="04700000" end="04700511" /> + <id start="04622000" end="04622511" /> + <id start="04620000" end="04620511" /> + <id start="04618000" end="04618511" /> + <id start="04616000" end="04616511" /> + <id start="04614000" end="04614511" /> + <id start="04612000" end="04612511" /> + <id start="04610000" end="04610511" /> + <id start="04608000" end="04608511" /> + <id start="04606000" end="04606511" /> + <id start="04604000" end="04604511" /> + <id start="04602000" end="04602511" /> + <id start="04600000" end="04600511" /> + <id start="04522000" end="04522511" /> + <id start="04520000" end="04520511" /> + <id start="04518000" end="04518511" /> + <id start="04516000" end="04516511" /> + <id start="04514000" end="04514511" /> + <id start="04512000" end="04512511" /> + <id start="04510000" end="04510511" /> + <id start="04508000" end="04508511" /> + <id start="04506000" end="04506511" /> + <id start="04504000" end="04504511" /> + <id start="04502000" end="04502511" /> + <id start="04500000" end="04500511" /> + <id start="04422000" end="04422511" /> + <id start="04420000" end="04420511" /> + <id start="04418000" end="04418511" /> + <id start="04416000" end="04416511" /> + <id start="04414000" end="04414511" /> + <id start="04412000" end="04412511" /> + <id start="04410000" end="04410511" /> + <id start="04408000" end="04408511" /> + <id start="04406000" end="04406511" /> + <id start="04404000" end="04404511" /> + <id start="04402000" end="04402511" /> + <id start="04400000" end="04400511" /> + <id start="04322000" end="04322511" /> + <id start="04320000" end="04320511" /> + <id start="04318000" end="04318511" /> + <id start="04316000" end="04316511" /> + <id start="04314000" end="04314511" /> + <id start="04312000" end="04312511" /> + <id start="04310000" end="04310511" /> + <id start="04308000" end="04308511" /> + <id start="04306000" end="04306511" /> + <id start="04304000" end="04304511" /> + <id start="04302000" end="04302511" /> + <id start="04300000" end="04300511" /> + <id start="04222000" end="04222511" /> + <id start="04220000" end="04220511" /> + <id start="04218000" end="04218511" /> + <id start="04216000" end="04216511" /> + <id start="04214000" end="04214511" /> + <id start="04212000" end="04212511" /> + <id start="04210000" end="04210511" /> + <id start="04208000" end="04208511" /> + <id start="04206000" end="04206511" /> + <id start="04204000" end="04204511" /> + <id start="04202000" end="04202511" /> + <id start="04200000" end="04200511" /> + <id start="04122000" end="04122511" /> + <id start="04120000" end="04120511" /> + <id start="04118000" end="04118511" /> + <id start="04116000" end="04116511" /> + <id start="04114000" end="04114511" /> + <id start="04112000" end="04112511" /> + <id start="04110000" end="04110511" /> + <id start="04108000" end="04108511" /> + <id start="04106000" end="04106511" /> + <id start="04104000" end="04104511" /> + <id start="04102000" end="04102511" /> + <id start="04100000" end="04100511" /> + </idlist> + <idlist idname="panel05"> + <id start="05707000" end="05707511" /> + <id start="05705000" end="05705511" /> + <id start="05703000" end="05703511" /> + <id start="05701000" end="05701511" /> + <id start="05623000" end="05623511" /> + <id start="05621000" end="05621511" /> + <id start="05619000" end="05619511" /> + <id start="05617000" end="05617511" /> + <id start="05615000" end="05615511" /> + <id start="05613000" end="05613511" /> + <id start="05611000" end="05611511" /> + <id start="05609000" end="05609511" /> + <id start="05607000" end="05607511" /> + <id start="05605000" end="05605511" /> + <id start="05603000" end="05603511" /> + <id start="05601000" end="05601511" /> + <id start="05523000" end="05523511" /> + <id start="05521000" end="05521511" /> + <id start="05519000" end="05519511" /> + <id start="05517000" end="05517511" /> + <id start="05515000" end="05515511" /> + <id start="05513000" end="05513511" /> + <id start="05511000" end="05511511" /> + <id start="05509000" end="05509511" /> + <id start="05507000" end="05507511" /> + <id start="05505000" end="05505511" /> + <id start="05503000" end="05503511" /> + <id start="05501000" end="05501511" /> + <id start="05423000" end="05423511" /> + <id start="05421000" end="05421511" /> + <id start="05419000" end="05419511" /> + <id start="05417000" end="05417511" /> + <id start="05415000" end="05415511" /> + <id start="05413000" end="05413511" /> + <id start="05411000" end="05411511" /> + <id start="05409000" end="05409511" /> + <id start="05407000" end="05407511" /> + <id start="05405000" end="05405511" /> + <id start="05403000" end="05403511" /> + <id start="05401000" end="05401511" /> + <id start="05323000" end="05323511" /> + <id start="05321000" end="05321511" /> + <id start="05319000" end="05319511" /> + <id start="05317000" end="05317511" /> + <id start="05315000" end="05315511" /> + <id start="05313000" end="05313511" /> + <id start="05311000" end="05311511" /> + <id start="05309000" end="05309511" /> + <id start="05307000" end="05307511" /> + <id start="05305000" end="05305511" /> + <id start="05303000" end="05303511" /> + <id start="05301000" end="05301511" /> + <id start="05223000" end="05223511" /> + <id start="05221000" end="05221511" /> + <id start="05219000" end="05219511" /> + <id start="05217000" end="05217511" /> + <id start="05215000" end="05215511" /> + <id start="05213000" end="05213511" /> + <id start="05211000" end="05211511" /> + <id start="05209000" end="05209511" /> + <id start="05207000" end="05207511" /> + <id start="05205000" end="05205511" /> + <id start="05203000" end="05203511" /> + <id start="05201000" end="05201511" /> + <id start="05123000" end="05123511" /> + <id start="05121000" end="05121511" /> + <id start="05119000" end="05119511" /> + <id start="05117000" end="05117511" /> + <id start="05115000" end="05115511" /> + <id start="05113000" end="05113511" /> + <id start="05111000" end="05111511" /> + <id start="05109000" end="05109511" /> + <id start="05107000" end="05107511" /> + <id start="05105000" end="05105511" /> + <id start="05103000" end="05103511" /> + <id start="05101000" end="05101511" /> + <id start="05706000" end="05706511" /> + <id start="05704000" end="05704511" /> + <id start="05702000" end="05702511" /> + <id start="05700000" end="05700511" /> + <id start="05622000" end="05622511" /> + <id start="05620000" end="05620511" /> + <id start="05618000" end="05618511" /> + <id start="05616000" end="05616511" /> + <id start="05614000" end="05614511" /> + <id start="05612000" end="05612511" /> + <id start="05610000" end="05610511" /> + <id start="05608000" end="05608511" /> + <id start="05606000" end="05606511" /> + <id start="05604000" end="05604511" /> + <id start="05602000" end="05602511" /> + <id start="05600000" end="05600511" /> + <id start="05522000" end="05522511" /> + <id start="05520000" end="05520511" /> + <id start="05518000" end="05518511" /> + <id start="05516000" end="05516511" /> + <id start="05514000" end="05514511" /> + <id start="05512000" end="05512511" /> + <id start="05510000" end="05510511" /> + <id start="05508000" end="05508511" /> + <id start="05506000" end="05506511" /> + <id start="05504000" end="05504511" /> + <id start="05502000" end="05502511" /> + <id start="05500000" end="05500511" /> + <id start="05422000" end="05422511" /> + <id start="05420000" end="05420511" /> + <id start="05418000" end="05418511" /> + <id start="05416000" end="05416511" /> + <id start="05414000" end="05414511" /> + <id start="05412000" end="05412511" /> + <id start="05410000" end="05410511" /> + <id start="05408000" end="05408511" /> + <id start="05406000" end="05406511" /> + <id start="05404000" end="05404511" /> + <id start="05402000" end="05402511" /> + <id start="05400000" end="05400511" /> + <id start="05322000" end="05322511" /> + <id start="05320000" end="05320511" /> + <id start="05318000" end="05318511" /> + <id start="05316000" end="05316511" /> + <id start="05314000" end="05314511" /> + <id start="05312000" end="05312511" /> + <id start="05310000" end="05310511" /> + <id start="05308000" end="05308511" /> + <id start="05306000" end="05306511" /> + <id start="05304000" end="05304511" /> + <id start="05302000" end="05302511" /> + <id start="05300000" end="05300511" /> + <id start="05222000" end="05222511" /> + <id start="05220000" end="05220511" /> + <id start="05218000" end="05218511" /> + <id start="05216000" end="05216511" /> + <id start="05214000" end="05214511" /> + <id start="05212000" end="05212511" /> + <id start="05210000" end="05210511" /> + <id start="05208000" end="05208511" /> + <id start="05206000" end="05206511" /> + <id start="05204000" end="05204511" /> + <id start="05202000" end="05202511" /> + <id start="05200000" end="05200511" /> + <id start="05122000" end="05122511" /> + <id start="05120000" end="05120511" /> + <id start="05118000" end="05118511" /> + <id start="05116000" end="05116511" /> + <id start="05114000" end="05114511" /> + <id start="05112000" end="05112511" /> + <id start="05110000" end="05110511" /> + <id start="05108000" end="05108511" /> + <id start="05106000" end="05106511" /> + <id start="05104000" end="05104511" /> + <id start="05102000" end="05102511" /> + <id start="05100000" end="05100511" /> + </idlist> + <idlist idname="panel10"> + <id start="10707000" end="10707511" /> + <id start="10705000" end="10705511" /> + <id start="10703000" end="10703511" /> + <id start="10701000" end="10701511" /> + <id start="10623000" end="10623511" /> + <id start="10621000" end="10621511" /> + <id start="10619000" end="10619511" /> + <id start="10617000" end="10617511" /> + <id start="10615000" end="10615511" /> + <id start="10613000" end="10613511" /> + <id start="10611000" end="10611511" /> + <id start="10609000" end="10609511" /> + <id start="10607000" end="10607511" /> + <id start="10605000" end="10605511" /> + <id start="10603000" end="10603511" /> + <id start="10601000" end="10601511" /> + <id start="10523000" end="10523511" /> + <id start="10521000" end="10521511" /> + <id start="10519000" end="10519511" /> + <id start="10517000" end="10517511" /> + <id start="10515000" end="10515511" /> + <id start="10513000" end="10513511" /> + <id start="10511000" end="10511511" /> + <id start="10509000" end="10509511" /> + <id start="10507000" end="10507511" /> + <id start="10505000" end="10505511" /> + <id start="10503000" end="10503511" /> + <id start="10501000" end="10501511" /> + <id start="10423000" end="10423511" /> + <id start="10421000" end="10421511" /> + <id start="10419000" end="10419511" /> + <id start="10417000" end="10417511" /> + <id start="10415000" end="10415511" /> + <id start="10413000" end="10413511" /> + <id start="10411000" end="10411511" /> + <id start="10409000" end="10409511" /> + <id start="10407000" end="10407511" /> + <id start="10405000" end="10405511" /> + <id start="10403000" end="10403511" /> + <id start="10401000" end="10401511" /> + <id start="10323000" end="10323511" /> + <id start="10321000" end="10321511" /> + <id start="10319000" end="10319511" /> + <id start="10317000" end="10317511" /> + <id start="10315000" end="10315511" /> + <id start="10313000" end="10313511" /> + <id start="10311000" end="10311511" /> + <id start="10309000" end="10309511" /> + <id start="10307000" end="10307511" /> + <id start="10305000" end="10305511" /> + <id start="10303000" end="10303511" /> + <id start="10301000" end="10301511" /> + <id start="10223000" end="10223511" /> + <id start="10221000" end="10221511" /> + <id start="10219000" end="10219511" /> + <id start="10217000" end="10217511" /> + <id start="10215000" end="10215511" /> + <id start="10213000" end="10213511" /> + <id start="10211000" end="10211511" /> + <id start="10209000" end="10209511" /> + <id start="10207000" end="10207511" /> + <id start="10205000" end="10205511" /> + <id start="10203000" end="10203511" /> + <id start="10201000" end="10201511" /> + <id start="10123000" end="10123511" /> + <id start="10121000" end="10121511" /> + <id start="10119000" end="10119511" /> + <id start="10117000" end="10117511" /> + <id start="10115000" end="10115511" /> + <id start="10113000" end="10113511" /> + <id start="10111000" end="10111511" /> + <id start="10109000" end="10109511" /> + <id start="10107000" end="10107511" /> + <id start="10105000" end="10105511" /> + <id start="10103000" end="10103511" /> + <id start="10101000" end="10101511" /> + <id start="10706000" end="10706511" /> + <id start="10704000" end="10704511" /> + <id start="10702000" end="10702511" /> + <id start="10700000" end="10700511" /> + <id start="10622000" end="10622511" /> + <id start="10620000" end="10620511" /> + <id start="10618000" end="10618511" /> + <id start="10616000" end="10616511" /> + <id start="10614000" end="10614511" /> + <id start="10612000" end="10612511" /> + <id start="10610000" end="10610511" /> + <id start="10608000" end="10608511" /> + <id start="10606000" end="10606511" /> + <id start="10604000" end="10604511" /> + <id start="10602000" end="10602511" /> + <id start="10600000" end="10600511" /> + <id start="10522000" end="10522511" /> + <id start="10520000" end="10520511" /> + <id start="10518000" end="10518511" /> + <id start="10516000" end="10516511" /> + <id start="10514000" end="10514511" /> + <id start="10512000" end="10512511" /> + <id start="10510000" end="10510511" /> + <id start="10508000" end="10508511" /> + <id start="10506000" end="10506511" /> + <id start="10504000" end="10504511" /> + <id start="10502000" end="10502511" /> + <id start="10500000" end="10500511" /> + <id start="10422000" end="10422511" /> + <id start="10420000" end="10420511" /> + <id start="10418000" end="10418511" /> + <id start="10416000" end="10416511" /> + <id start="10414000" end="10414511" /> + <id start="10412000" end="10412511" /> + <id start="10410000" end="10410511" /> + <id start="10408000" end="10408511" /> + <id start="10406000" end="10406511" /> + <id start="10404000" end="10404511" /> + <id start="10402000" end="10402511" /> + <id start="10400000" end="10400511" /> + <id start="10322000" end="10322511" /> + <id start="10320000" end="10320511" /> + <id start="10318000" end="10318511" /> + <id start="10316000" end="10316511" /> + <id start="10314000" end="10314511" /> + <id start="10312000" end="10312511" /> + <id start="10310000" end="10310511" /> + <id start="10308000" end="10308511" /> + <id start="10306000" end="10306511" /> + <id start="10304000" end="10304511" /> + <id start="10302000" end="10302511" /> + <id start="10300000" end="10300511" /> + <id start="10222000" end="10222511" /> + <id start="10220000" end="10220511" /> + <id start="10218000" end="10218511" /> + <id start="10216000" end="10216511" /> + <id start="10214000" end="10214511" /> + <id start="10212000" end="10212511" /> + <id start="10210000" end="10210511" /> + <id start="10208000" end="10208511" /> + <id start="10206000" end="10206511" /> + <id start="10204000" end="10204511" /> + <id start="10202000" end="10202511" /> + <id start="10200000" end="10200511" /> + <id start="10122000" end="10122511" /> + <id start="10120000" end="10120511" /> + <id start="10118000" end="10118511" /> + <id start="10116000" end="10116511" /> + <id start="10114000" end="10114511" /> + <id start="10112000" end="10112511" /> + <id start="10110000" end="10110511" /> + <id start="10108000" end="10108511" /> + <id start="10106000" end="10106511" /> + <id start="10104000" end="10104511" /> + <id start="10102000" end="10102511" /> + <id start="10100000" end="10100511" /> + </idlist> + <idlist idname="panel09"> + <id start="09707000" end="09707511" /> + <id start="09705000" end="09705511" /> + <id start="09703000" end="09703511" /> + <id start="09701000" end="09701511" /> + <id start="09623000" end="09623511" /> + <id start="09621000" end="09621511" /> + <id start="09619000" end="09619511" /> + <id start="09617000" end="09617511" /> + <id start="09615000" end="09615511" /> + <id start="09613000" end="09613511" /> + <id start="09611000" end="09611511" /> + <id start="09609000" end="09609511" /> + <id start="09607000" end="09607511" /> + <id start="09605000" end="09605511" /> + <id start="09603000" end="09603511" /> + <id start="09601000" end="09601511" /> + <id start="09523000" end="09523511" /> + <id start="09521000" end="09521511" /> + <id start="09519000" end="09519511" /> + <id start="09517000" end="09517511" /> + <id start="09515000" end="09515511" /> + <id start="09513000" end="09513511" /> + <id start="09511000" end="09511511" /> + <id start="09509000" end="09509511" /> + <id start="09507000" end="09507511" /> + <id start="09505000" end="09505511" /> + <id start="09503000" end="09503511" /> + <id start="09501000" end="09501511" /> + <id start="09423000" end="09423511" /> + <id start="09421000" end="09421511" /> + <id start="09419000" end="09419511" /> + <id start="09417000" end="09417511" /> + <id start="09415000" end="09415511" /> + <id start="09413000" end="09413511" /> + <id start="09411000" end="09411511" /> + <id start="09409000" end="09409511" /> + <id start="09407000" end="09407511" /> + <id start="09405000" end="09405511" /> + <id start="09403000" end="09403511" /> + <id start="09401000" end="09401511" /> + <id start="09323000" end="09323511" /> + <id start="09321000" end="09321511" /> + <id start="09319000" end="09319511" /> + <id start="09317000" end="09317511" /> + <id start="09315000" end="09315511" /> + <id start="09313000" end="09313511" /> + <id start="09311000" end="09311511" /> + <id start="09309000" end="09309511" /> + <id start="09307000" end="09307511" /> + <id start="09305000" end="09305511" /> + <id start="09303000" end="09303511" /> + <id start="09301000" end="09301511" /> + <id start="09223000" end="09223511" /> + <id start="09221000" end="09221511" /> + <id start="09219000" end="09219511" /> + <id start="09217000" end="09217511" /> + <id start="09215000" end="09215511" /> + <id start="09213000" end="09213511" /> + <id start="09211000" end="09211511" /> + <id start="09209000" end="09209511" /> + <id start="09207000" end="09207511" /> + <id start="09205000" end="09205511" /> + <id start="09203000" end="09203511" /> + <id start="09201000" end="09201511" /> + <id start="09123000" end="09123511" /> + <id start="09121000" end="09121511" /> + <id start="09119000" end="09119511" /> + <id start="09117000" end="09117511" /> + <id start="09115000" end="09115511" /> + <id start="09113000" end="09113511" /> + <id start="09111000" end="09111511" /> + <id start="09109000" end="09109511" /> + <id start="09107000" end="09107511" /> + <id start="09105000" end="09105511" /> + <id start="09103000" end="09103511" /> + <id start="09101000" end="09101511" /> + <id start="09706000" end="09706511" /> + <id start="09704000" end="09704511" /> + <id start="09702000" end="09702511" /> + <id start="09700000" end="09700511" /> + <id start="09622000" end="09622511" /> + <id start="09620000" end="09620511" /> + <id start="09618000" end="09618511" /> + <id start="09616000" end="09616511" /> + <id start="09614000" end="09614511" /> + <id start="09612000" end="09612511" /> + <id start="09610000" end="09610511" /> + <id start="09608000" end="09608511" /> + <id start="09606000" end="09606511" /> + <id start="09604000" end="09604511" /> + <id start="09602000" end="09602511" /> + <id start="09600000" end="09600511" /> + <id start="09522000" end="09522511" /> + <id start="09520000" end="09520511" /> + <id start="09518000" end="09518511" /> + <id start="09516000" end="09516511" /> + <id start="09514000" end="09514511" /> + <id start="09512000" end="09512511" /> + <id start="09510000" end="09510511" /> + <id start="09508000" end="09508511" /> + <id start="09506000" end="09506511" /> + <id start="09504000" end="09504511" /> + <id start="09502000" end="09502511" /> + <id start="09500000" end="09500511" /> + <id start="09422000" end="09422511" /> + <id start="09420000" end="09420511" /> + <id start="09418000" end="09418511" /> + <id start="09416000" end="09416511" /> + <id start="09414000" end="09414511" /> + <id start="09412000" end="09412511" /> + <id start="09410000" end="09410511" /> + <id start="09408000" end="09408511" /> + <id start="09406000" end="09406511" /> + <id start="09404000" end="09404511" /> + <id start="09402000" end="09402511" /> + <id start="09400000" end="09400511" /> + <id start="09322000" end="09322511" /> + <id start="09320000" end="09320511" /> + <id start="09318000" end="09318511" /> + <id start="09316000" end="09316511" /> + <id start="09314000" end="09314511" /> + <id start="09312000" end="09312511" /> + <id start="09310000" end="09310511" /> + <id start="09308000" end="09308511" /> + <id start="09306000" end="09306511" /> + <id start="09304000" end="09304511" /> + <id start="09302000" end="09302511" /> + <id start="09300000" end="09300511" /> + <id start="09222000" end="09222511" /> + <id start="09220000" end="09220511" /> + <id start="09218000" end="09218511" /> + <id start="09216000" end="09216511" /> + <id start="09214000" end="09214511" /> + <id start="09212000" end="09212511" /> + <id start="09210000" end="09210511" /> + <id start="09208000" end="09208511" /> + <id start="09206000" end="09206511" /> + <id start="09204000" end="09204511" /> + <id start="09202000" end="09202511" /> + <id start="09200000" end="09200511" /> + <id start="09122000" end="09122511" /> + <id start="09120000" end="09120511" /> + <id start="09118000" end="09118511" /> + <id start="09116000" end="09116511" /> + <id start="09114000" end="09114511" /> + <id start="09112000" end="09112511" /> + <id start="09110000" end="09110511" /> + <id start="09108000" end="09108511" /> + <id start="09106000" end="09106511" /> + <id start="09104000" end="09104511" /> + <id start="09102000" end="09102511" /> + <id start="09100000" end="09100511" /> + </idlist> + <idlist idname="panel08"> + <id start="08707000" end="08707511" /> + <id start="08705000" end="08705511" /> + <id start="08703000" end="08703511" /> + <id start="08701000" end="08701511" /> + <id start="08623000" end="08623511" /> + <id start="08621000" end="08621511" /> + <id start="08619000" end="08619511" /> + <id start="08617000" end="08617511" /> + <id start="08615000" end="08615511" /> + <id start="08613000" end="08613511" /> + <id start="08611000" end="08611511" /> + <id start="08609000" end="08609511" /> + <id start="08607000" end="08607511" /> + <id start="08605000" end="08605511" /> + <id start="08603000" end="08603511" /> + <id start="08601000" end="08601511" /> + <id start="08523000" end="08523511" /> + <id start="08521000" end="08521511" /> + <id start="08519000" end="08519511" /> + <id start="08517000" end="08517511" /> + <id start="08515000" end="08515511" /> + <id start="08513000" end="08513511" /> + <id start="08511000" end="08511511" /> + <id start="08509000" end="08509511" /> + <id start="08507000" end="08507511" /> + <id start="08505000" end="08505511" /> + <id start="08503000" end="08503511" /> + <id start="08501000" end="08501511" /> + <id start="08423000" end="08423511" /> + <id start="08421000" end="08421511" /> + <id start="08419000" end="08419511" /> + <id start="08417000" end="08417511" /> + <id start="08415000" end="08415511" /> + <id start="08413000" end="08413511" /> + <id start="08411000" end="08411511" /> + <id start="08409000" end="08409511" /> + <id start="08407000" end="08407511" /> + <id start="08405000" end="08405511" /> + <id start="08403000" end="08403511" /> + <id start="08401000" end="08401511" /> + <id start="08323000" end="08323511" /> + <id start="08321000" end="08321511" /> + <id start="08319000" end="08319511" /> + <id start="08317000" end="08317511" /> + <id start="08315000" end="08315511" /> + <id start="08313000" end="08313511" /> + <id start="08311000" end="08311511" /> + <id start="08309000" end="08309511" /> + <id start="08307000" end="08307511" /> + <id start="08305000" end="08305511" /> + <id start="08303000" end="08303511" /> + <id start="08301000" end="08301511" /> + <id start="08223000" end="08223511" /> + <id start="08221000" end="08221511" /> + <id start="08219000" end="08219511" /> + <id start="08217000" end="08217511" /> + <id start="08215000" end="08215511" /> + <id start="08213000" end="08213511" /> + <id start="08211000" end="08211511" /> + <id start="08209000" end="08209511" /> + <id start="08207000" end="08207511" /> + <id start="08205000" end="08205511" /> + <id start="08203000" end="08203511" /> + <id start="08201000" end="08201511" /> + <id start="08123000" end="08123511" /> + <id start="08121000" end="08121511" /> + <id start="08119000" end="08119511" /> + <id start="08117000" end="08117511" /> + <id start="08115000" end="08115511" /> + <id start="08113000" end="08113511" /> + <id start="08111000" end="08111511" /> + <id start="08109000" end="08109511" /> + <id start="08107000" end="08107511" /> + <id start="08105000" end="08105511" /> + <id start="08103000" end="08103511" /> + <id start="08101000" end="08101511" /> + <id start="08706000" end="08706511" /> + <id start="08704000" end="08704511" /> + <id start="08702000" end="08702511" /> + <id start="08700000" end="08700511" /> + <id start="08622000" end="08622511" /> + <id start="08620000" end="08620511" /> + <id start="08618000" end="08618511" /> + <id start="08616000" end="08616511" /> + <id start="08614000" end="08614511" /> + <id start="08612000" end="08612511" /> + <id start="08610000" end="08610511" /> + <id start="08608000" end="08608511" /> + <id start="08606000" end="08606511" /> + <id start="08604000" end="08604511" /> + <id start="08602000" end="08602511" /> + <id start="08600000" end="08600511" /> + <id start="08522000" end="08522511" /> + <id start="08520000" end="08520511" /> + <id start="08518000" end="08518511" /> + <id start="08516000" end="08516511" /> + <id start="08514000" end="08514511" /> + <id start="08512000" end="08512511" /> + <id start="08510000" end="08510511" /> + <id start="08508000" end="08508511" /> + <id start="08506000" end="08506511" /> + <id start="08504000" end="08504511" /> + <id start="08502000" end="08502511" /> + <id start="08500000" end="08500511" /> + <id start="08422000" end="08422511" /> + <id start="08420000" end="08420511" /> + <id start="08418000" end="08418511" /> + <id start="08416000" end="08416511" /> + <id start="08414000" end="08414511" /> + <id start="08412000" end="08412511" /> + <id start="08410000" end="08410511" /> + <id start="08408000" end="08408511" /> + <id start="08406000" end="08406511" /> + <id start="08404000" end="08404511" /> + <id start="08402000" end="08402511" /> + <id start="08400000" end="08400511" /> + <id start="08322000" end="08322511" /> + <id start="08320000" end="08320511" /> + <id start="08318000" end="08318511" /> + <id start="08316000" end="08316511" /> + <id start="08314000" end="08314511" /> + <id start="08312000" end="08312511" /> + <id start="08310000" end="08310511" /> + <id start="08308000" end="08308511" /> + <id start="08306000" end="08306511" /> + <id start="08304000" end="08304511" /> + <id start="08302000" end="08302511" /> + <id start="08300000" end="08300511" /> + <id start="08222000" end="08222511" /> + <id start="08220000" end="08220511" /> + <id start="08218000" end="08218511" /> + <id start="08216000" end="08216511" /> + <id start="08214000" end="08214511" /> + <id start="08212000" end="08212511" /> + <id start="08210000" end="08210511" /> + <id start="08208000" end="08208511" /> + <id start="08206000" end="08206511" /> + <id start="08204000" end="08204511" /> + <id start="08202000" end="08202511" /> + <id start="08200000" end="08200511" /> + <id start="08122000" end="08122511" /> + <id start="08120000" end="08120511" /> + <id start="08118000" end="08118511" /> + <id start="08116000" end="08116511" /> + <id start="08114000" end="08114511" /> + <id start="08112000" end="08112511" /> + <id start="08110000" end="08110511" /> + <id start="08108000" end="08108511" /> + <id start="08106000" end="08106511" /> + <id start="08104000" end="08104511" /> + <id start="08102000" end="08102511" /> + <id start="08100000" end="08100511" /> + </idlist> + <idlist idname="panel07"> + <id start="07707000" end="07707511" /> + <id start="07705000" end="07705511" /> + <id start="07703000" end="07703511" /> + <id start="07701000" end="07701511" /> + <id start="07623000" end="07623511" /> + <id start="07621000" end="07621511" /> + <id start="07619000" end="07619511" /> + <id start="07617000" end="07617511" /> + <id start="07615000" end="07615511" /> + <id start="07613000" end="07613511" /> + <id start="07611000" end="07611511" /> + <id start="07609000" end="07609511" /> + <id start="07607000" end="07607511" /> + <id start="07605000" end="07605511" /> + <id start="07603000" end="07603511" /> + <id start="07601000" end="07601511" /> + <id start="07523000" end="07523511" /> + <id start="07521000" end="07521511" /> + <id start="07519000" end="07519511" /> + <id start="07517000" end="07517511" /> + <id start="07515000" end="07515511" /> + <id start="07513000" end="07513511" /> + <id start="07511000" end="07511511" /> + <id start="07509000" end="07509511" /> + <id start="07507000" end="07507511" /> + <id start="07505000" end="07505511" /> + <id start="07503000" end="07503511" /> + <id start="07501000" end="07501511" /> + <id start="07423000" end="07423511" /> + <id start="07421000" end="07421511" /> + <id start="07419000" end="07419511" /> + <id start="07417000" end="07417511" /> + <id start="07415000" end="07415511" /> + <id start="07413000" end="07413511" /> + <id start="07411000" end="07411511" /> + <id start="07409000" end="07409511" /> + <id start="07407000" end="07407511" /> + <id start="07405000" end="07405511" /> + <id start="07403000" end="07403511" /> + <id start="07401000" end="07401511" /> + <id start="07323000" end="07323511" /> + <id start="07321000" end="07321511" /> + <id start="07319000" end="07319511" /> + <id start="07317000" end="07317511" /> + <id start="07315000" end="07315511" /> + <id start="07313000" end="07313511" /> + <id start="07311000" end="07311511" /> + <id start="07309000" end="07309511" /> + <id start="07307000" end="07307511" /> + <id start="07305000" end="07305511" /> + <id start="07303000" end="07303511" /> + <id start="07301000" end="07301511" /> + <id start="07223000" end="07223511" /> + <id start="07221000" end="07221511" /> + <id start="07219000" end="07219511" /> + <id start="07217000" end="07217511" /> + <id start="07215000" end="07215511" /> + <id start="07213000" end="07213511" /> + <id start="07211000" end="07211511" /> + <id start="07209000" end="07209511" /> + <id start="07207000" end="07207511" /> + <id start="07205000" end="07205511" /> + <id start="07203000" end="07203511" /> + <id start="07201000" end="07201511" /> + <id start="07123000" end="07123511" /> + <id start="07121000" end="07121511" /> + <id start="07119000" end="07119511" /> + <id start="07117000" end="07117511" /> + <id start="07115000" end="07115511" /> + <id start="07113000" end="07113511" /> + <id start="07111000" end="07111511" /> + <id start="07109000" end="07109511" /> + <id start="07107000" end="07107511" /> + <id start="07105000" end="07105511" /> + <id start="07103000" end="07103511" /> + <id start="07101000" end="07101511" /> + <id start="07706000" end="07706511" /> + <id start="07704000" end="07704511" /> + <id start="07702000" end="07702511" /> + <id start="07700000" end="07700511" /> + <id start="07622000" end="07622511" /> + <id start="07620000" end="07620511" /> + <id start="07618000" end="07618511" /> + <id start="07616000" end="07616511" /> + <id start="07614000" end="07614511" /> + <id start="07612000" end="07612511" /> + <id start="07610000" end="07610511" /> + <id start="07608000" end="07608511" /> + <id start="07606000" end="07606511" /> + <id start="07604000" end="07604511" /> + <id start="07602000" end="07602511" /> + <id start="07600000" end="07600511" /> + <id start="07522000" end="07522511" /> + <id start="07520000" end="07520511" /> + <id start="07518000" end="07518511" /> + <id start="07516000" end="07516511" /> + <id start="07514000" end="07514511" /> + <id start="07512000" end="07512511" /> + <id start="07510000" end="07510511" /> + <id start="07508000" end="07508511" /> + <id start="07506000" end="07506511" /> + <id start="07504000" end="07504511" /> + <id start="07502000" end="07502511" /> + <id start="07500000" end="07500511" /> + <id start="07422000" end="07422511" /> + <id start="07420000" end="07420511" /> + <id start="07418000" end="07418511" /> + <id start="07416000" end="07416511" /> + <id start="07414000" end="07414511" /> + <id start="07412000" end="07412511" /> + <id start="07410000" end="07410511" /> + <id start="07408000" end="07408511" /> + <id start="07406000" end="07406511" /> + <id start="07404000" end="07404511" /> + <id start="07402000" end="07402511" /> + <id start="07400000" end="07400511" /> + <id start="07322000" end="07322511" /> + <id start="07320000" end="07320511" /> + <id start="07318000" end="07318511" /> + <id start="07316000" end="07316511" /> + <id start="07314000" end="07314511" /> + <id start="07312000" end="07312511" /> + <id start="07310000" end="07310511" /> + <id start="07308000" end="07308511" /> + <id start="07306000" end="07306511" /> + <id start="07304000" end="07304511" /> + <id start="07302000" end="07302511" /> + <id start="07300000" end="07300511" /> + <id start="07222000" end="07222511" /> + <id start="07220000" end="07220511" /> + <id start="07218000" end="07218511" /> + <id start="07216000" end="07216511" /> + <id start="07214000" end="07214511" /> + <id start="07212000" end="07212511" /> + <id start="07210000" end="07210511" /> + <id start="07208000" end="07208511" /> + <id start="07206000" end="07206511" /> + <id start="07204000" end="07204511" /> + <id start="07202000" end="07202511" /> + <id start="07200000" end="07200511" /> + <id start="07122000" end="07122511" /> + <id start="07120000" end="07120511" /> + <id start="07118000" end="07118511" /> + <id start="07116000" end="07116511" /> + <id start="07114000" end="07114511" /> + <id start="07112000" end="07112511" /> + <id start="07110000" end="07110511" /> + <id start="07108000" end="07108511" /> + <id start="07106000" end="07106511" /> + <id start="07104000" end="07104511" /> + <id start="07102000" end="07102511" /> + <id start="07100000" end="07100511" /> + </idlist> + + </instrument> diff --git a/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py b/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py index fb08324c17132556e012fa9d8edef6fd8dbfd008..cb1067e87fe7b612d7cf14372264996a10b048c8 100644 --- a/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py +++ b/Code/Mantid/scripts/Inelastic/IndirectDataAnalysis.py @@ -76,7 +76,7 @@ def createConvFitFun(options, par, file): ############################################################################## -def getConvFitResult(inputWS, resFile, outNm, ftype, bgd, Verbose): +def getConvFitResult(inputWS, resFile, outNm, ftype, bgd, specMin, specMax, Verbose): options = getConvFitOption(ftype, bgd[:-2], Verbose) params = mtd[outNm+'_Parameters'] A0 = params.column(1) #bgd A0 value @@ -94,8 +94,8 @@ def getConvFitResult(inputWS, resFile, outNm, ftype, bgd, Verbose): H2 = params.column(ip+6) #height2 value C2 = params.column(ip+8) #centre2 value W2 = params.column(ip+10) #width2 value - nHist = mtd[inputWS].getNumberHistograms() - for i in range(nHist): + + for i in range(0,specMax-specMin): paras = [A0[i], A1[i]] if options[1]: paras.append(D1[i]) @@ -112,7 +112,7 @@ def getConvFitResult(inputWS, resFile, outNm, ftype, bgd, Verbose): logger.notice('Fit func : '+func) fitWS = outNm + '_Result_' fout = fitWS + str(i) - Fit(Function=func,InputWorkspace=inputWS,WorkspaceIndex=i,Output=fout,MaxIterations=0) + Fit(Function=func,InputWorkspace=inputWS,WorkspaceIndex=i+specMin,Output=fout,MaxIterations=0) unitx = mtd[fout+'_Workspace'].getAxis(0).setUnit("Label") unitx.setLabel('Time' , 'ns') RenameWorkspace(InputWorkspace=fout+'_Workspace', OutputWorkspace=fout) @@ -213,7 +213,7 @@ def confitSeq(inputWS, func, startX, endX, Save, Plot, ftype, bgd, specMin, spec AddSampleLog(Workspace=wsname, LogName='Lorentzians', LogType='String', LogText=str(options[2])) RenameWorkspace(InputWorkspace=outNm, OutputWorkspace=outNm + "_Parameters") - getConvFitResult(inputWS, resFile, outNm, ftype, bgd, Verbose) + getConvFitResult(inputWS, resFile, outNm, ftype, bgd, specMin, specMax, Verbose) if Save: o_path = os.path.join(workdir, wsname+'.nxs') # path name for nxs file if Verbose: @@ -266,6 +266,7 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, workdir = config['defaultsave.directory'] CheckXrange(eRange,'Energy') tempWS = '__temp' + Range2 = ( len(eRange) == 4 ) if Verbose: range1 = str(eRange[0])+' to '+str(eRange[1]) if ( len(eRange) == 4 ): @@ -363,22 +364,17 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, CreateWorkspace(OutputWorkspace=elfWS, DataX=datTx, DataY=datTy, DataE=datTe, Nspec=nQ, UnitX='Energy', VerticalAxisUnit='MomentumTransfer', VerticalAxisValues=q1) - unitx = mtd[elfWS].getAxis(0).setUnit("Label") - unitx.setLabel(unit[0], unit[1]) DeleteWorkspace('__elf') label = unit[0]+' / '+unit[1] AddSampleLog(Workspace=elfWS, LogName="Vaxis", LogType="String", LogText=label) e1WS = ename+'_eq1' CreateWorkspace(OutputWorkspace=e1WS, DataX=datX1, DataY=datY1, DataE=datE1, Nspec=nr, UnitX='MomentumTransfer', VerticalAxisUnit='Energy', VerticalAxisValues=Taxis) - unity = mtd[e1WS].getAxis(1).setUnit("Label") - unity.setLabel(unit[0], unit[1]) + label = unit[0]+' / '+unit[1] AddSampleLog(Workspace=e1WS, LogName="Vaxis", LogType="String", LogText=label) e2WS = ename+'_eq2' CreateWorkspace(OutputWorkspace=e2WS, DataX=datX2, DataY=datY2, DataE=datE2, Nspec=nr, UnitX='QSquared', VerticalAxisUnit='Energy', VerticalAxisValues=Taxis) - unity = mtd[e2WS].getAxis(1).setUnit("Label") - unity.setLabel(unit[0], unit[1]) AddSampleLog(Workspace=e2WS, LogName="Vaxis", LogType="String", LogText=label) if unit[0] == 'Temperature': @@ -389,16 +385,31 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, else: lo = nT-1 hi = 0 - + text = 'Temperature range : '+str(Tvalue[lo])+' to '+str(Tvalue[hi]) + AddSampleLog(Workspace=e1WS, LogName="Temperature normalise", LogType="String", LogText=str(Normalise)) if Normalise: yval = mtd[e1WS].readY(lo) normFactor = 1.0/yval[0] Scale(InputWorkspace=e1WS, OutputWorkspace=e1WS, Factor=normFactor, Operation='Multiply') + AddSampleLog(Workspace=e1WS, LogName="Temperature value", LogType="Number", LogText=str(Tvalue[0])) if Verbose: text = 'Temperature range : '+str(Tvalue[lo])+' to '+str(Tvalue[hi]) logger.notice(text) logger.notice('Normalised eq1 by scale factor : '+str(normFactor)) + unity = mtd[e1WS].getAxis(1).setUnit("Label") + unity.setLabel(unit[0], unit[1]) + label = unit[0]+' / '+unit[1] + addElwinLogs(e1WS, label, eRange, Range2) + + unity = mtd[e2WS].getAxis(1).setUnit("Label") + unity.setLabel(unit[0], unit[1]) + addElwinLogs(e2WS, label, eRange, Range2) + + unitx = mtd[elfWS].getAxis(0).setUnit("Label") + unitx.setLabel(unit[0], unit[1]) + addElwinLogs(elfWS, label, eRange, Range2) + if Save: e1_path = os.path.join(workdir, e1WS+'.nxs') # path name for nxs file e2_path = os.path.join(workdir, e2WS+'.nxs') # path name for nxs file @@ -419,6 +430,18 @@ def elwin(inputFiles, eRange, log_type='sample', Normalise = False, EndTime('Elwin') return e1WS,e2WS +# Add sample log to each of the workspaces created by Elwin +def addElwinLogs(ws, label, eRange, Range2): + + AddSampleLog(Workspace=ws, LogName="Vaxis", LogType="String", LogText=label) + AddSampleLog(Workspace=ws, LogName="Range1 start", LogType="Number", LogText=str(eRange[0])) + AddSampleLog(Workspace=ws, LogName="Range1 end", LogType="Number", LogText=str(eRange[1])) + AddSampleLog(Workspace=ws, LogName="Two ranges", LogType="String", LogText=str(Range2)) + + if Range2: + AddSampleLog(Workspace=ws, LogName="Range2 start", LogType="Number", LogText=str(eRange[2])) + AddSampleLog(Workspace=ws, LogName="Range2 end", LogType="Number", LogText=str(eRange[3])) + def elwinPlot(eq1,eq2,elf): nhist = mtd[eq1].getNumberHistograms() # no. of hist/groups in sam nBins = mtd[eq1].blocksize() diff --git a/Code/Mantid/scripts/Interface/reduction_gui/reduction/reflectometer/refl_data_script.py b/Code/Mantid/scripts/Interface/reduction_gui/reduction/reflectometer/refl_data_script.py index ab8fa088d311a1eec58da39a08ff8c032995a4f4..b37603308ef40cba446578b19753062ea035db7a 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/reduction/reflectometer/refl_data_script.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/reduction/reflectometer/refl_data_script.py @@ -64,6 +64,10 @@ class DataSets(BaseScriptElement): fourth_column_dq0 = 0.0009 fourth_column_dq_over_q = 0.045 + # how to treat overlap values + overlap_lowest_error = True + overlap_mean_value = False + def __init__(self): super(DataSets, self).__init__() self.reset() @@ -171,7 +175,9 @@ class DataSets(BaseScriptElement): # Q cut xml += "<q_min>%s</q_min>\n" % str(self.q_min) xml += "<q_step>%s</q_step>\n" % str(self.q_step) - xml += "<auto_q_binning>%s</auto_q_binning>" % str(self.auto_q_binning) + xml += "<auto_q_binning>%s</auto_q_binning>\n" % str(self.auto_q_binning) + xml += "<overlap_lowest_error>%s</overlap_lowest_error>\n" % str(self.overlap_lowest_error) + xml += "<overlap_mean_value>%s</overlap_mean_value>\n" % str(self.overlap_mean_value) # Angle offset xml += "<angle_offset>%s</angle_offset>\n" % str(self.angle_offset) @@ -288,6 +294,10 @@ class DataSets(BaseScriptElement): self.q_min = BaseScriptElement.getFloatElement(instrument_dom, "q_min", default=DataSets.q_min) self.q_step = BaseScriptElement.getFloatElement(instrument_dom, "q_step", default=DataSets.q_step) self.auto_q_binning = BaseScriptElement.getBoolElement(instrument_dom, "auto_q_binning", default=False) + + # overlap_lowest_error + self.overlap_lowest_error = BaseScriptElement.getBoolElement(instrument_dom, "overlap_lowest_error", default=True) + self.overlap_mean_value = BaseScriptElement.getBoolElement(instrument_dom, "overlap_mean_value", default=False) # Angle offset self.angle_offset = BaseScriptElement.getFloatElement(instrument_dom, "angle_offset", default=DataSets.angle_offset) @@ -345,6 +355,10 @@ class DataSets(BaseScriptElement): self.q_step = DataSets.q_step self.auto_q_binning = DataSets.auto_q_binning + # overlap_lowest_error + self.overlap_lowest_error = DataSets.overlap_lowest_error + self.overlap_mean_value = DataSets.overlap_mean_value + # Angle offset self.angle_offset = DataSets.angle_offset self.angle_offset_error = DataSets.angle_offset_error diff --git a/Code/Mantid/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py b/Code/Mantid/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py index aacb36e04550fc191ebf29804eeef8ab735f171d..08a7da3669e9911278557b9b3fce28bf89d90a87 100644 --- a/Code/Mantid/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py +++ b/Code/Mantid/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py @@ -60,6 +60,8 @@ class BaseRefWidget(BaseWidget): self._summary.data_to_tof.setValidator(QtGui.QIntValidator(self._summary.data_to_tof)) self._summary.dq0.setValidator(QtGui.QDoubleValidator(self._summary.dq0)) self._summary.dq_over_q.setValidator(QtGui.QDoubleValidator(self._summary.dq_over_q)) +# self._summary.overlapValueMeanRadioButton(QtGui.setChecked(False) +# self._summary.overlapValueLowestErrorRadioButton.setChecked(True) self._summary.x_min_edit.setValidator(QtGui.QDoubleValidator(self._summary.x_min_edit)) self._summary.x_max_edit.setValidator(QtGui.QDoubleValidator(self._summary.x_max_edit)) @@ -175,8 +177,14 @@ class BaseRefWidget(BaseWidget): self.connect(self._summary.dq_over_q, QtCore.SIGNAL("textChanged(QString)"), call_back) call_back = partial(self._edit_event, ctrl=self._summary.fourth_column_switch) self.connect(self._summary.fourth_column_switch, QtCore.SIGNAL("clicked()"), call_back) + + #overlap values + call_back = partial(self._edit_event, ctrl=self._summary.overlapValueMeanRadioButton) + self.connect(self._summary.overlapValueMeanRadioButton, QtCore.SIGNAL("clicked()"), call_back) + call_back = partial(self._edit_event, ctrl=self._summary.overlapValueLowestErrorRadioButton) + self.connect(self._summary.overlapValueLowestErrorRadioButton, QtCore.SIGNAL("clicked()"), call_back) - #name of output file changed + #name of output file changed call_back = partial(self._edit_event, ctrl=self._summary.cfg_scaling_factor_file_name) self.connect(self._summary.cfg_scaling_factor_file_name_browse, QtCore.SIGNAL("clicked()"), call_back) @@ -440,51 +448,61 @@ class BaseRefWidget(BaseWidget): data_e[j] = data_e_i[j] return scaled_ws_list[0]+'_histo' + + def _produce_y_of_same_x_(self, isUsingLessErrorValue): + """ + 2 y values sharing the same x-axis will be average using + the weighted mean + """ + + ws_list = AnalysisDataService.getObjectNames() + scaled_ws_list = [] -# new_x_axis = [] -# new_y_axis = [] -# new_e_axis = [] -# -# sz = len(x_axis) -# i=0 -# while (i < sz-1): -# -# _left_x = x_axis[i] -# _right_x = x_axis[i+1] -# -# _left_y = y_axis[i] -# _left_e = e_axis[i] -# -# if (_left_x == _right_x): -# -# _right_y = y_axis[i+1] -# _right_e = e_axis[i+1] -# -# #calculate weighted mean -# import wks_utility -# [_y_mean, _e_mean] = wks_utility.weightedMean([_left_y, _right_y], [_left_e, _right_e]) -# -# new_x_axis.append(_left_x) -# new_y_axis.append(_y_mean) -# new_e_axis.append(_e_mean) -# -# i+=1 -# -# else: -# -# new_x_axis.append(_left_x) -# new_y_axis.append(_left_y) -# new_e_axis.append(_left_e) -# -# i+=1 -# -# self.x_axis = new_x_axis -# self.y_axis = new_y_axis -# self.e_axis = new_e_axis + # Get the list of scaled histos + for ws in ws_list: + if ws.endswith("_scaled"): + scaled_ws_list.append(ws) + + + # get binning parameters + _from_q = str(self._summary.q_min_edit.text()) + _bin_size = str(self._summary.q_step_edit.text()) + _bin_max = str(2) + binning_parameters = _from_q + ',-' + _bin_size + ',' + _bin_max + + # Convert each histo to histograms and rebin to final binning + for ws in scaled_ws_list: + new_name = "%s_histo" % ws + ConvertToHistogram(InputWorkspace=ws, OutputWorkspace=new_name) + Rebin(InputWorkspace=new_name, Params=binning_parameters, + OutputWorkspace=new_name) + + # Take the first rebinned histo as our output + data_y = mtd[scaled_ws_list[0]+'_histo'].dataY(0) + data_e = mtd[scaled_ws_list[0]+'_histo'].dataE(0) + + # Add in the other histos, averaging the overlaps + for i in range(1, len(scaled_ws_list)): + data_y_i = mtd[scaled_ws_list[i]+'_histo'].dataY(0) + data_e_i = mtd[scaled_ws_list[i]+'_histo'].dataE(0) + for j in range(len(data_y_i)): + if data_y[j]>0 and data_y_i[j]>0: + if isUsingLessErrorValue: + if (data_e[j] > data_e_i[j]): + data_y[j] = data_y_i[j] + data_e[j] = data_e_i[j] + else: + [data_y[j], data_e[j]] = self.weightedMean([data_y[j], data_y_i[j]], [data_e[j], data_e_i[j]]) + + elif (data_y[j] == 0) and (data_y_i[j]>0): + data_y[j] = data_y_i[j] + data_e[j] = data_e_i[j] + + return scaled_ws_list[0]+'_histo' def _create_ascii_clicked(self): """ - Reached by the "Create ASCII" button + Reached by the 'Create ASCII' button """ #make sure there is the right output workspace called ' # if not mtd.workspaceExists('ref_combined'): @@ -526,9 +544,10 @@ class BaseRefWidget(BaseWidget): # OutputWorkspace='ref_combined', # Params=q_binning) - wks_file_name = self._average_y_of_same_x_() - -# + #using mean or value with less error + _overlap_less_error_flag = self._summary.overlapValueLowestErrorRadioButton.isChecked() + wks_file_name = self._produce_y_of_same_x_(_overlap_less_error_flag) + # mt = mtd['ref_combined'] # x_axis = mt.readX(0)[:] # y_axis = mt.readY(0)[:] @@ -542,14 +561,15 @@ class BaseRefWidget(BaseWidget): sz = len(x_axis)-1 for i in range(sz): - _line = str(x_axis[i]) - _line += ' ' + str(y_axis[i]) - _line += ' ' + str(e_axis[i]) - if _with_4th_flag: - _precision = str(dq0 + dq_over_q * x_axis[i]) - _line += ' ' + _precision - - text.append(_line) + # do not display data where R=0 + if (y_axis[i] > 1e-15): + _line = str(x_axis[i]) + _line += ' ' + str(y_axis[i]) + _line += ' ' + str(e_axis[i]) + if _with_4th_flag: + _precision = str(dq0 + dq_over_q * x_axis[i]) + _line += ' ' + _precision + text.append(_line) f=open(file_name,'w') for _line in text: @@ -642,6 +662,8 @@ class BaseRefWidget(BaseWidget): util.set_edited(self._summary.q_step_edit, False) util.set_edited(self._summary.cfg_scaling_factor_file_name, False) util.set_edited(self._summary.incident_medium_combobox, False) + util.set_edited(self._summary.overlapValueLowestErrorRadioButton, False) + util.set_edited(self._summary.overlapValueMeanRadioButton, False) util.set_edited(self._summary.dq0, False) util.set_edited(self._summary.dq_over_q, False) util.set_edited(self._summary.fourth_column_switch, False) @@ -1249,7 +1271,11 @@ class BaseRefWidget(BaseWidget): state.incident_medium_list = [_incident_medium_string] state.incident_medium_index_selected = _incident_medium_index_selected - + + # how to treat overlap values + state.overlap_lowest_error = self._summary.overlapValueLowestErrorRadioButton.isChecked() + state.overlap_mean_value = self._summary.overlapValueMeanRadioButton.isChecked() + #4th column (precision) state.fourth_column_dq0 = self._summary.dq0.text() state.fourth_column_dq_over_q = self._summary.dq_over_q.text() @@ -1275,7 +1301,11 @@ class BaseRefWidget(BaseWidget): _incident_medium_string = (',').join(_incident_medium_list) state.incident_medium_list = [_incident_medium_string] - + + # how to treat overlap values + state.overlap_lowest_error = self._summary.overlapValueLowestErrorRadioButton.isChecked() + state.overlap_mean_value = self._summary.overlapValueMeanRadioButton.isChecked() + state.incident_medium_index_selected = _incident_medium_index_selected item_widget.setData(QtCore.Qt.UserRole, state) @@ -1391,6 +1421,10 @@ class BaseRefWidget(BaseWidget): self._summary.log_scale_chk.setChecked(state.q_step<0) self._summary.q_step_edit.setText(str(math.fabs(state.q_step))) + # overlap ascii values + self._summary.overlapValueLowestErrorRadioButton.setChecked(state.overlap_lowest_error) + self._summary.overlapValueMeanRadioButton.setChecked(state.overlap_mean_value) + # Output directory if hasattr(state, "output_dir"): if len(str(state.output_dir).strip())>0: @@ -1403,7 +1437,7 @@ class BaseRefWidget(BaseWidget): self._use_sf_config_clicked(state.scaling_factor_file_flag) # geomery correction - self._summary.geometry_correction_switch.setChecked(state.geometry_correction_switch) + self._summary.geometry_correction_switch.setChecked(state.geometry_correction_switch) self._reset_warnings() self._summary.data_run_number_edit.setText(str(','.join([str(i) for i in state.data_files]))) diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/data_refl_simple.ui b/Code/Mantid/scripts/Interface/ui/reflectometer/data_refl_simple.ui index 74582472e37034400eb6a4ea971dc2b92e3fe2c7..7f99d0569bb38e3217f7c39a7524ea6a53e175ed 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/data_refl_simple.ui +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/data_refl_simple.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>1608</width> - <height>1178</height> + <width>1630</width> + <height>1343</height> </rect> </property> <property name="windowTitle"> @@ -36,8 +36,8 @@ <rect> <x>0</x> <y>0</y> - <width>1584</width> - <height>1469</height> + <width>1606</width> + <height>1497</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_7"> @@ -4141,6 +4141,66 @@ p, li { white-space: pre-wrap; } </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_35"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>How to treat overlap values </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="overlapValueLowestErrorRadioButton"> + <property name="text"> + <string>use lowest error value</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_29"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QRadioButton" name="overlapValueMeanRadioButton"> + <property name="text"> + <string>use mean value </string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_28"> + <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> <item> <layout class="QHBoxLayout" name="horizontalLayout_29"> <property name="spacing"> diff --git a/Code/Mantid/scripts/Interface/ui/reflectometer/ui_data_refl_simple.py b/Code/Mantid/scripts/Interface/ui/reflectometer/ui_data_refl_simple.py index 27a4fb317af5f0c16bdd9d8f96d672e6d9b5bbe1..17ab1bbad90cd127232e4b504f5530f20fe20544 100644 --- a/Code/Mantid/scripts/Interface/ui/reflectometer/ui_data_refl_simple.py +++ b/Code/Mantid/scripts/Interface/ui/reflectometer/ui_data_refl_simple.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'data_refl_simple.ui' # -# Created: Tue Oct 1 14:03:40 2013 +# Created: Thu Oct 3 16:03:53 2013 # by: PyQt4 UI code generator 4.10.3 # # WARNING! All changes made in this file will be lost! @@ -26,7 +26,7 @@ except AttributeError: class Ui_Frame(object): def setupUi(self, Frame): Frame.setObjectName(_fromUtf8("Frame")) - Frame.resize(1608, 1178) + Frame.resize(1630, 1343) Frame.setFrameShape(QtGui.QFrame.NoFrame) Frame.setFrameShadow(QtGui.QFrame.Raised) self.verticalLayout_5 = QtGui.QVBoxLayout(Frame) @@ -37,7 +37,7 @@ class Ui_Frame(object): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 1584, 1469)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 1606, 1497)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_7 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_7.setObjectName(_fromUtf8("verticalLayout_7")) @@ -1446,6 +1446,24 @@ class Ui_Frame(object): self.outdir_browse_button.setObjectName(_fromUtf8("outdir_browse_button")) self.horizontalLayout_19.addWidget(self.outdir_browse_button) self.verticalLayout_8.addLayout(self.horizontalLayout_19) + self.horizontalLayout_35 = QtGui.QHBoxLayout() + self.horizontalLayout_35.setObjectName(_fromUtf8("horizontalLayout_35")) + self.label_2 = QtGui.QLabel(self.groupBox_4) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.horizontalLayout_35.addWidget(self.label_2) + self.overlapValueLowestErrorRadioButton = QtGui.QRadioButton(self.groupBox_4) + self.overlapValueLowestErrorRadioButton.setChecked(True) + self.overlapValueLowestErrorRadioButton.setObjectName(_fromUtf8("overlapValueLowestErrorRadioButton")) + self.horizontalLayout_35.addWidget(self.overlapValueLowestErrorRadioButton) + spacerItem22 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_35.addItem(spacerItem22) + self.overlapValueMeanRadioButton = QtGui.QRadioButton(self.groupBox_4) + self.overlapValueMeanRadioButton.setChecked(False) + self.overlapValueMeanRadioButton.setObjectName(_fromUtf8("overlapValueMeanRadioButton")) + self.horizontalLayout_35.addWidget(self.overlapValueMeanRadioButton) + spacerItem23 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_35.addItem(spacerItem23) + self.verticalLayout_8.addLayout(self.horizontalLayout_35) self.horizontalLayout_29 = QtGui.QHBoxLayout() self.horizontalLayout_29.setSpacing(0) self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) @@ -1489,8 +1507,8 @@ class Ui_Frame(object): self.dq_over_q.setMaximumSize(QtCore.QSize(60, 16777215)) self.dq_over_q.setObjectName(_fromUtf8("dq_over_q")) self.horizontalLayout_29.addWidget(self.dq_over_q) - spacerItem22 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_29.addItem(spacerItem22) + spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_29.addItem(spacerItem24) self.create_ascii_button = QtGui.QPushButton(self.groupBox_4) self.create_ascii_button.setMinimumSize(QtCore.QSize(150, 0)) self.create_ascii_button.setMaximumSize(QtCore.QSize(150, 16777215)) @@ -1498,13 +1516,13 @@ class Ui_Frame(object): self.horizontalLayout_29.addWidget(self.create_ascii_button) self.verticalLayout_8.addLayout(self.horizontalLayout_29) self.verticalLayout_4.addWidget(self.groupBox_4) - spacerItem23 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_4.addItem(spacerItem23) + spacerItem25 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_4.addItem(spacerItem25) self.horizontalLayout_7 = QtGui.QHBoxLayout() self.horizontalLayout_7.setSpacing(0) self.horizontalLayout_7.setObjectName(_fromUtf8("horizontalLayout_7")) - spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_7.addItem(spacerItem24) + spacerItem26 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_7.addItem(spacerItem26) self.edited_warning_label = QtGui.QLabel(self.scrollAreaWidgetContents) self.edited_warning_label.setTextFormat(QtCore.Qt.RichText) self.edited_warning_label.setObjectName(_fromUtf8("edited_warning_label")) @@ -1529,35 +1547,35 @@ class Ui_Frame(object): self.add_dataset_btn.setFont(font) self.add_dataset_btn.setObjectName(_fromUtf8("add_dataset_btn")) self.horizontalLayout_7.addWidget(self.add_dataset_btn) - spacerItem25 = QtGui.QSpacerItem(9, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_7.addItem(spacerItem25) + spacerItem27 = QtGui.QSpacerItem(9, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_7.addItem(spacerItem27) self.verticalLayout_4.addLayout(self.horizontalLayout_7) - spacerItem26 = QtGui.QSpacerItem(20, 25, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) - self.verticalLayout_4.addItem(spacerItem26) + spacerItem28 = QtGui.QSpacerItem(20, 25, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + self.verticalLayout_4.addItem(spacerItem28) self.auto_reduce_help_label = QtGui.QLabel(self.scrollAreaWidgetContents) self.auto_reduce_help_label.setObjectName(_fromUtf8("auto_reduce_help_label")) self.verticalLayout_4.addWidget(self.auto_reduce_help_label) self.horizontalLayout_13 = QtGui.QHBoxLayout() self.horizontalLayout_13.setSpacing(0) self.horizontalLayout_13.setObjectName(_fromUtf8("horizontalLayout_13")) - spacerItem27 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_13.addItem(spacerItem27) + spacerItem29 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_13.addItem(spacerItem29) self.auto_reduce_tip_label = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setItalic(True) self.auto_reduce_tip_label.setFont(font) self.auto_reduce_tip_label.setObjectName(_fromUtf8("auto_reduce_tip_label")) self.horizontalLayout_13.addWidget(self.auto_reduce_tip_label) - spacerItem28 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_13.addItem(spacerItem28) + spacerItem30 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_13.addItem(spacerItem30) self.auto_reduce_btn = QtGui.QPushButton(self.scrollAreaWidgetContents) self.auto_reduce_btn.setMinimumSize(QtCore.QSize(150, 0)) self.auto_reduce_btn.setMaximumSize(QtCore.QSize(150, 16777215)) self.auto_reduce_btn.setObjectName(_fromUtf8("auto_reduce_btn")) self.horizontalLayout_13.addWidget(self.auto_reduce_btn) self.verticalLayout_4.addLayout(self.horizontalLayout_13) - spacerItem29 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_4.addItem(spacerItem29) + spacerItem31 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_4.addItem(spacerItem31) self.auto_reduce_check = QtGui.QCheckBox(self.scrollAreaWidgetContents) self.auto_reduce_check.setObjectName(_fromUtf8("auto_reduce_check")) self.verticalLayout_4.addWidget(self.auto_reduce_check) @@ -1695,6 +1713,9 @@ class Ui_Frame(object): self.angle_offset_unit_label.setText(_translate("Frame", " degrees", None)) self.outdir_label.setText(_translate("Frame", "Output directory", None)) self.outdir_browse_button.setText(_translate("Frame", "Browse...", None)) + self.label_2.setText(_translate("Frame", "How to treat overlap values ", None)) + self.overlapValueLowestErrorRadioButton.setText(_translate("Frame", "use lowest error value", None)) + self.overlapValueMeanRadioButton.setText(_translate("Frame", "use mean value ", None)) self.fourth_column_switch.setText(_translate("Frame", "4th column (precision)", None)) self.dq0_label.setText(_translate("Frame", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" diff --git a/Code/Mantid/scripts/SANS/SANSUtility.py b/Code/Mantid/scripts/SANS/SANSUtility.py index a564764f8df8e37ba8fe1204635343002bbe0d87..a86d0f0a3cdfb5918adb35f1ed22317aac5b555e 100644 --- a/Code/Mantid/scripts/SANS/SANSUtility.py +++ b/Code/Mantid/scripts/SANS/SANSUtility.py @@ -3,6 +3,7 @@ # SANS data reduction scripts ######################################################## from mantid.simpleapi import * +from mantid.api import IEventWorkspace import math def GetInstrumentDetails(instrum): @@ -380,6 +381,58 @@ class RunDetails(object): ##END REMOVED def getSuffix(self): return self._suffix + +def getWorkspaceReference(ws_pointer): + if isinstance(ws_pointer, str): + ws_pointer = mtd[ws_pointer] + if str(ws_pointer) not in mtd: + raise RuntimeError("Invalid workspace name input: " + str(ws_pointer)) + return ws_pointer + +def isEventWorkspace(ws_reference): + return isinstance(getWorkspaceReference(ws_reference),IEventWorkspace) + +def getBinsBoundariesFromWorkspace(ws_reference): + ws_reference = getWorkspaceReference(ws_reference) + Xvalues = ws_reference.dataX(0) + binning = str(Xvalues[0]) + binGap = Xvalues[1] - Xvalues[0] + binning = binning + ',' + str(binGap) + for j in range(2, len(Xvalues)): + nextBinGap = Xvalues[j] - Xvalues[j-1] + if nextBinGap != binGap: + binGap = nextBinGap + binning = binning + ',' + str(Xvalues[j-1]) + ',' + str(binGap) + binning = binning + "," + str(Xvalues[-1]) + return binning + +def loadMonitorsFromFile(fileName, monitor_ws_name='monitor_ws'): + monitor = LoadNexus(fileName, SpectrumMax=8, OutputWorkspace=monitor_ws_name) + return monitor + +def getFilePathFromWorkspace(ws): + ws_pointer = getWorkspaceReference(ws) + try: + file_path = ws_pointer.getHistory().getAlgorithm(0).getPropertyValue('Filename') + except: + raise RuntimeError("Can not find the file name for workspace " + str(ws)) + return file_path + +def fromEvent2Histogram(ws_event, ws_monitor = None): + if not ws_monitor: + file_path = getFilePathFromWorkspace(ws_event) + ws_monitor = loadMonitorsFromFile(file_path) + + bins_option = getBinsBoundariesFromWorkspace(ws_monitor) + + aux_hist = Rebin(ws_event, bins_option, False) + + monitor_ws_name = ws_monitor.name() + ConjoinWorkspaces(ws_monitor, aux_hist, CheckOverlapping=True) + + ws_hist = RenameWorkspace(monitor_ws_name, OutputWorkspace=str(ws_event)) + + return ws_hist if __name__ == '__main__': diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 36cde9e87086978c2ca5665d019e6f16074605fa..bb30425d5904d9feff0deecfd6973df09fa186b9 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -13,7 +13,9 @@ sanslog = sans_reduction_steps.sanslog from mantid.simpleapi import * from mantid.api import WorkspaceGroup, Workspace -import SANSUtility +from SANSUtility import (GetInstrumentDetails, MaskByBinRange, + isEventWorkspace, fromEvent2Histogram, + getFilePathFromWorkspace, getWorkspaceReference) import isis_instrument import os import math @@ -83,8 +85,7 @@ class LoadRun(object): OutputWorkspace=workspace, **extra_options) - alg = outWs.getHistory().lastAlgorithm() - self._data_file = alg.getPropertyValue("Filename") + self._data_file = getFilePathFromWorkspace(outWs) LoadSampleDetailsFromRaw(InputWorkspace=workspace, Filename=self._data_file) workspace = self._leaveSinglePeriod(workspace, period) @@ -94,8 +95,7 @@ class LoadRun(object): outWs = LoadNexus(Filename=self._data_file, OutputWorkspace=workspace, **extra_options) - alg = outWs.getHistory().lastAlgorithm() - self._data_file = alg.getPropertyValue("Filename") + self._data_file = getFilePathFromWorkspace(outWs) SANS2D_log_file = mtd[workspace] @@ -159,9 +159,9 @@ class LoadRun(object): ws_pointer = self._data_file try: - _file_path = ws_pointer.getHistory().getAlgorithm(0).getPropertyValue("Filename") + _file_path = getFilePathFromWorkspace(ws_pointer) except: - raise RuntimeError("Failed to retrieve information to reloade this workspace " + str(self._data_file)) + raise RuntimeError("Failed to retrieve information to reload this workspace " + str(self._data_file)) self._data_file = _file_path if self._reload: # give to _assignHelper the responsibility of loading this data. @@ -181,6 +181,9 @@ class LoadRun(object): if 'Algorithm: Move' in hist_str or 'Algorithm: Rotate' in hist_str: raise RuntimeError('Moving components needs to be made compatible with not reloading the sample') + if isEventWorkspace(ws_pointer): + ws_pointer = fromEvent2Histogram(ws_pointer) + return True, self._extract_log_info(ws_pointer, reducer.instrument) @@ -208,7 +211,7 @@ class LoadRun(object): spectrum_limits = dict() if self._is_trans: if reducer.instrument.name() == 'SANS2D' and int(self.shortrun_no) < 568: - dimension = SANSUtility.GetInstrumentDetails(reducer.instrument)[0] + dimension = GetInstrumentDetails(reducer.instrument)[0] spec_min = dimension*dimension*2 spectrum_limits = {'SpectrumMin':spec_min, 'SpectrumMax':spec_min + 4} @@ -296,7 +299,8 @@ class LoadRun(object): return numPeriods def _getHistory(self, wk_name): - + ws = getWorkspaceReference(wk_name) + if isinstance(wk_name, Workspace): ws_h = wk_name.getHistory() else: @@ -834,15 +838,15 @@ class Mask_ISIS(sans_reduction_steps.Mask): if detector.isAlias('rear'): self.spec_list = self._ConvertToSpecList(self.spec_mask_r, detector) #Time mask - SANSUtility.MaskByBinRange(workspace,self.time_mask_r) - SANSUtility.MaskByBinRange(workspace,self.time_mask) + MaskByBinRange (workspace,self.time_mask_r) + MaskByBinRange(workspace,self.time_mask) if detector.isAlias('front'): #front specific masking self.spec_list = self._ConvertToSpecList(self.spec_mask_f, detector) #Time mask - SANSUtility.MaskByBinRange(workspace,self.time_mask_f) - SANSUtility.MaskByBinRange(workspace,self.time_mask) + MaskByBinRange(workspace,self.time_mask_f) + MaskByBinRange(workspace,self.time_mask) #reset the xml, as execute can be run more than once self._xml = []