From a21a9bb2759e6b790251053ded70069c8bf82df1 Mon Sep 17 00:00:00 2001 From: Anton Piccardo-Selg <anton.piccardo-selg@tessella.com> Date: Fri, 6 Mar 2015 15:33:15 +0000 Subject: [PATCH] Refs #11053 Add peaks table in splatterplot --- .../PeaksFilter/PeaksFilter.xml | 6 +- .../ScaleWorkspace/vtkScaleWorkspace.h | 3 +- Code/Mantid/Vates/VatesAPI/CMakeLists.txt | 10 + .../CompositePeaksPresenterVsi.h | 41 ++ .../inc/MantidVatesAPI/MetadataJsonManager.h | 4 + .../inc/MantidVatesAPI/PeaksPresenterVsi.h | 3 + .../vtkDataSetToPeaksFilteredDataSet.h | 15 +- .../MantidVatesAPI/vtkEllipsoidTransformer.h | 56 ++ .../inc/MantidVatesAPI/vtkPeakMarkerFactory.h | 9 - .../inc/MantidVatesAPI/vtkSinglePeakMarker.h | 47 ++ .../MantidVatesAPI/vtkSplatterPlotFactory.h | 15 + .../src/CompositePeaksPresenterVsi.cpp | 151 ++++++ .../src/ConcretePeaksPresenterVsi.cpp | 3 + .../src/MDEWInMemoryLoadingPresenter.cpp | 3 + .../src/MDHWInMemoryLoadingPresenter.cpp | 3 + .../VatesAPI/src/MetadataJsonManager.cpp | 31 +- .../src/vtkDataSetToPeaksFilteredDataSet.cpp | 238 +++++--- .../VatesAPI/src/vtkEllipsoidTransformer.cpp | 78 +++ .../VatesAPI/src/vtkPeakMarkerFactory.cpp | 149 +++--- .../VatesAPI/src/vtkSinglePeakMarker.cpp | 76 +++ .../VatesAPI/src/vtkSplatterPlotFactory.cpp | 72 ++- .../test/CompositePeaksPresenterVsiTest.h | 23 + .../test/ConcretePeaksPresenterVsiTest.h | 104 ++++ .../VatesAPI/test/NullPeaksPresenterVsiTest.h | 39 ++ .../vtkDataSetToPeaksFilteredDataSetTest.h | 65 ++- .../test/vtkEllipsoidTransformerTest.h | 252 +++++++++ .../VatesAPI/test/vtkPeakMarkerFactoryTest.h | 29 +- .../test/vtkSplatterPlotFactoryTest.h | 12 + .../VatesSimpleGui/ViewWidgets/CMakeLists.txt | 10 +- .../MdViewerWidget.h | 6 + .../PeaksTabWidget.h | 46 ++ .../PeaksTabWidget.ui | 62 +++ ...kViewerVsi.h => PeaksTableControllerVsi.h} | 30 +- .../PeaksWidget.h | 5 +- .../PeaksWidget.ui | 18 + .../SplatterPlotView.h | 23 +- .../SplatterPlotView.ui | 12 +- .../src/AutoScaleRangeGenerator.cpp | 4 +- .../ViewWidgets/src/MdViewerWidget.cpp | 74 ++- .../ViewWidgets/src/PeakViewerVsi.cpp | 327 ----------- .../ViewWidgets/src/PeaksTabWidget.cpp | 112 ++++ .../src/PeaksTableControllerVsi.cpp | 506 ++++++++++++++++++ .../ViewWidgets/src/PeaksWidget.cpp | 38 +- .../ViewWidgets/src/SplatterPlotView.cpp | 225 ++++++-- 44 files changed, 2431 insertions(+), 604 deletions(-) create mode 100644 Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h create mode 100644 Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkEllipsoidTransformer.h create mode 100644 Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSinglePeakMarker.h create mode 100644 Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp create mode 100644 Code/Mantid/Vates/VatesAPI/src/vtkEllipsoidTransformer.cpp create mode 100644 Code/Mantid/Vates/VatesAPI/src/vtkSinglePeakMarker.cpp create mode 100644 Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h create mode 100644 Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h create mode 100644 Code/Mantid/Vates/VatesAPI/test/NullPeaksPresenterVsiTest.h create mode 100644 Code/Mantid/Vates/VatesAPI/test/vtkEllipsoidTransformerTest.h create mode 100644 Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h create mode 100644 Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.ui rename Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/{PeakViewerVsi.h => PeaksTableControllerVsi.h} (54%) delete mode 100644 Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeakViewerVsi.cpp create mode 100644 Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTabWidget.cpp create mode 100644 Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp diff --git a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/PeaksFilter/PeaksFilter.xml b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/PeaksFilter/PeaksFilter.xml index 835f4ee9bb8..0680db7b147 100644 --- a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/PeaksFilter/PeaksFilter.xml +++ b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/PeaksFilter/PeaksFilter.xml @@ -13,7 +13,7 @@ <DataType value="vtkUnstructuredGrid"/> </DataTypeDomain> </InputProperty> - <StringVectorProperty name="PeaksWorkspace" command="SetPeaksWorkspace" number_of_elements="1"/> + <StringVectorProperty name="PeaksWorkspace" command="SetPeaksWorkspace" number_of_elements="1" panel_visibility="never"/> <DoubleVectorProperty name="RadiusNoShape" command="SetRadiusNoShape" number_of_elements="1" default_values="0.5"> <DoubleRangeDomain name="range" min="0.001" max="10" /> <Documentation> @@ -30,6 +30,10 @@ Set the radius type. </Documentation> </IntVectorProperty> + <StringVectorProperty name="Delimiter" command="SetDelimiter" number_of_elements="1" panel_visibility="never"/> + <DoubleVectorProperty name="MinValue" command="GetMinValue" information_only="1"/> + <DoubleVectorProperty name="MaxValue" command="GetMaxValue" information_only="1"/> + <StringVectorProperty name="Instrument" command="GetInstrument" number_of_elements="1" information_only="1"/> </SourceProxy> </ProxyGroup> <!-- End ScaleWorkspace --> diff --git a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.h b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.h index a4871931124..1a0065a478f 100644 --- a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.h +++ b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.h @@ -18,7 +18,7 @@ public: double GetMinValue(); double GetMaxValue(); const char* GetInstrument(); - + int GetSpecialCoordinates(); protected: vtkScaleWorkspace(); ~vtkScaleWorkspace(); @@ -35,6 +35,7 @@ private: double m_minValue; double m_maxValue; std::string m_instrument; + int m_specialCoordinates; boost::scoped_ptr<Mantid::VATES::MetadataJsonManager> m_metadataJsonManager; boost::scoped_ptr<Mantid::VATES::VatesConfigurations> m_vatesConfigurations; diff --git a/Code/Mantid/Vates/VatesAPI/CMakeLists.txt b/Code/Mantid/Vates/VatesAPI/CMakeLists.txt index f065639971f..927bc9468ec 100644 --- a/Code/Mantid/Vates/VatesAPI/CMakeLists.txt +++ b/Code/Mantid/Vates/VatesAPI/CMakeLists.txt @@ -6,6 +6,7 @@ project( VatesAPI ) set( SRC_FILES src/ADSWorkspaceProvider.cpp src/Common.cpp +src/CompositePeaksPresenterVsi.cpp src/ConcretePeaksPresenterVsi.cpp src/DimensionPresenter.cpp src/EventNexusLoadingPresenter.cpp @@ -42,6 +43,7 @@ src/vtkDataSetToPeaksFilteredDataSet.cpp src/vtkDataSetToScaledDataSet.cpp src/vtkDataSetToWsName.cpp src/vtkDataSetToWsLocation.cpp +src/vtkEllipsoidTransformer.cpp src/vtkMDLineFactory.cpp src/vtkMDQuadFactory.cpp src/vtkNullUnstructuredGrid.cpp @@ -52,12 +54,14 @@ src/vtkMDHistoHexFactory.cpp src/vtkMDHistoLineFactory.cpp src/vtkMDHistoQuadFactory.cpp src/vtkMDHistoHex4DFactory.cpp +src/vtkSinglePeakMarker.cpp src/SQWLoadingPresenter.cpp ) set( INC_FILES inc/MantidVatesAPI/ADSWorkspaceProvider.h inc/MantidVatesAPI/Common.h +inc/MantidVatesAPI/CompositePeaksPresenterVsi.h inc/MantidVatesAPI/ConcretePeaksPresenterVsi.h inc/MantidVatesAPI/DimensionPresenter.h inc/MantidVatesAPI/DimensionView.h @@ -105,6 +109,7 @@ inc/MantidVatesAPI/vtkDataSetToPeaksFilteredDataSet.h inc/MantidVatesAPI/vtkDataSetToScaledDataSet.h inc/MantidVatesAPI/vtkDataSetToWsName.h inc/MantidVatesAPI/vtkDataSetToWsLocation.h +inc/MantidVatesAPI/vtkEllipsoidTransformer.h inc/MantidVatesAPI/vtkMDLineFactory.h inc/MantidVatesAPI/vtkMDQuadFactory.h inc/MantidVatesAPI/vtkMDHexFactory.h @@ -115,6 +120,7 @@ inc/MantidVatesAPI/vtkMDHistoHexFactory.h inc/MantidVatesAPI/vtkMDHistoLineFactory.h inc/MantidVatesAPI/vtkMDHistoQuadFactory.h inc/MantidVatesAPI/vtkMDHistoHex4DFactory.h +inc/MantidVatesAPI/vtkSinglePeakMarker.h inc/MantidVatesAPI/WorkspaceProvider.h ) @@ -163,6 +169,10 @@ test/vtkDataSetToScaledDataSetTest.h test/vtkDataSetToPeaksFilteredDataSetTest.h test/vtkDataSetToNonOrthogonalDataSetTest.h test/vtkNullUnstructuredGridTest.h +test/vtkEllipsoidTransformerTest.h +test/NullPeaksPresenterVsiTest.h +test/ConcretePeaksPresenterVsiTest.h +test/CompositePeaksPresenterVsiTest.h ) include_directories( inc ) diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h new file mode 100644 index 00000000000..7eed20a4094 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h @@ -0,0 +1,41 @@ +#ifndef MANTID_VATES_COMPOSITE_PEAKS_PRESENTER_VSI_H +#define MANTID_VATES_COMPOSITE_PEAKS_PRESENTER_VSI_H + +#include "MantidKernel/System.h" +#include "MantidVatesAPI/PeaksPresenterVsi.h" +#include "MantidAPI/PeakTransform.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidVatesAPI/ViewFrustum.h" +#include "MantidGeometry/Crystal/PeakShape.h" +#include <vector> +#include <string> + +namespace Mantid +{ +namespace VATES +{ +class DLLExport CompositePeaksPresenterVsi : public PeaksPresenterVsi +{ +public: + CompositePeaksPresenterVsi(); + ~CompositePeaksPresenterVsi(); + virtual Mantid::API::IPeaksWorkspace_sptr getPeaksWorkspace(){throw std::runtime_error("The composite peaks presenter has no single peaks workspace.");} + std::vector<Mantid::API::IPeaksWorkspace_sptr> getPeaksWorkspaces(); + virtual std::vector<bool> getViewablePeaks(); + virtual void updateViewFrustum(ViewFrustum frustum); + virtual std::string getFrame(); + virtual std::string getPeaksWorkspaceName(){throw std::runtime_error("The composite peaks presenter has no peaks workspace");} + std::vector<std::string> getPeaksWorkspaceNames(); + virtual void getPeaksInfo(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row, Mantid::Kernel::V3D& position, double& radius); + void addPresenter(PeaksPresenterVsi_sptr presenter); + std::map<std::string, std::vector<bool>> getInitializedViewablePeaks(); + void removePresenter(std::string peaksWorkspaceName); + void updateWorkspaces(std::vector<std::string> peaksWorkspaceNames); + bool CompositePeaksPresenterVsi::hasPeaks(); +private: + /// The list of presenters + std::vector<PeaksPresenterVsi_sptr> m_peaksPresenters; +}; +} +} +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MetadataJsonManager.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MetadataJsonManager.h index f29bc938eb9..ca4d94f18ac 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MetadataJsonManager.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MetadataJsonManager.h @@ -54,12 +54,16 @@ namespace Mantid void setMaxValue(double maxValue); double getMaxValue(); + void setSpecialCoordinates(int specialCoordinates); + int getSpecialCoordinates(); + private: Json::Value metadataContainer; std::string instrument; double minValue; double maxValue; + int specialCoordinates; }; } } diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h index 83df53c721d..5e4e7e92ff9 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h @@ -26,6 +26,9 @@ class DLLExport PeaksPresenterVsi virtual void getPeaksInfo(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row, Mantid::Kernel::V3D& position, double& radius) = 0; }; + +typedef boost::shared_ptr<PeaksPresenterVsi> PeaksPresenterVsi_sptr; +typedef boost::shared_ptr<const PeaksPresenterVsi> PeaksPresenterVsi_const_sptr; } } #endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkDataSetToPeaksFilteredDataSet.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkDataSetToPeaksFilteredDataSet.h index 95c88731d61..d458e48aa2b 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkDataSetToPeaksFilteredDataSet.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkDataSetToPeaksFilteredDataSet.h @@ -4,6 +4,7 @@ #include "MantidKernel/System.h" #include "MantidKernel/V3D.h" #include "MantidAPI/IPeaksWorkspace.h" +#include "MantidVatesAPI/ProgressAction.h" #include <string> class vtkUnstructuredGrid; @@ -45,18 +46,24 @@ namespace VATES vtkDataSetToPeaksFilteredDataSet(vtkUnstructuredGrid *input, vtkUnstructuredGrid *output); virtual ~vtkDataSetToPeaksFilteredDataSet(); /// Set the name of the peaks workspace - void initialize(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, double radiusNoShape, int radiusType); + void initialize(std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksWorkspaces, double radiusNoShape, int radiusType); /// Apply the peak filtering - void execute(); + void execute(ProgressAction& progressUpdating); + /// Get radius of no shape + double vtkDataSetToPeaksFilteredDataSet::getRadiusNoShape(); + /// Get radius factor + double getRadiusFactor(); private: vtkDataSetToPeaksFilteredDataSet& operator=(const vtkDataSetToPeaksFilteredDataSet& other); - std::vector<std::pair<Mantid::Kernel::V3D, double>> getPeaksInfo(); + std::vector<std::pair<Mantid::Kernel::V3D, double>> getPeaksInfo(std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksWorkspaces); + void addSinglePeak(Mantid::API::IPeak* peak, const Mantid::Kernel::SpecialCoordinateSystem coordinateSystem, std::vector<std::pair<Mantid::Kernel::V3D, double>>& peaksInfo, size_t index); vtkUnstructuredGrid *m_inputData; ///< Data to peak filter vtkUnstructuredGrid *m_outputData; ///< Peak filtered data - Mantid::API::IPeaksWorkspace_sptr m_peaksWorkspace; ///< The name of the peaks workspace. + std::vector<Mantid::API::IPeaksWorkspace_sptr> m_peaksWorkspaces; ///< A list of peaks workspace names. bool m_isInitialised; ///<Flag if the filter is initialized double m_radiusNoShape; ///< The radius for peaks with no peak shape. int m_radiusType; + double m_radiusFactor;///< By how much we want to trim the data set. }; } } diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkEllipsoidTransformer.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkEllipsoidTransformer.h new file mode 100644 index 00000000000..954dc56030d --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkEllipsoidTransformer.h @@ -0,0 +1,56 @@ +#ifndef MANTID_VATES_VTKELLIPSOIDTRANSFORMER_H_ +#define MANTID_VATES_VTKELLIPSOIDTRANSFORMER_H_ + +#include "MantidKernel/System.h" +#include <vtkSmartPointer.h> + +class vtkTransform; +namespace Mantid +{ +namespace Kernel +{ + class V3D; +} +} + +namespace Mantid +{ +namespace VATES +{ +/** + * Creates a vtkTransform for ellipsoids to rotate them into the correct direction. + @date 122/02/2015 + + Copyright © 2010 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge National Laboratory & European Spallation Source + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + +class DLLExport vtkEllipsoidTransformer +{ +public: + vtkEllipsoidTransformer(); + ~vtkEllipsoidTransformer(); + vtkSmartPointer<vtkTransform> generateTransform(std::vector<Mantid::Kernel::V3D> directions); +private: + Mantid::Kernel::V3D rotateVector(Mantid::Kernel::V3D original, Mantid::Kernel::V3D rotationAxis, double angle); +}; +} +} +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkPeakMarkerFactory.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkPeakMarkerFactory.h index c0ab1bb9b5e..6f7cba3bbc0 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkPeakMarkerFactory.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkPeakMarkerFactory.h @@ -35,12 +35,8 @@ #include "MantidAPI/IPeaksWorkspace.h" #include "MantidVatesAPI/vtkDataSetFactory.h" -#include <vtkSmartPointer.h> - -class vtkTransform; class vtkPolyData; - namespace Mantid { namespace VATES @@ -94,11 +90,6 @@ protected: virtual void validate() const; private: - - vtkSmartPointer<vtkTransform> vtkPeakMarkerFactory::createEllipsoidTransform(std::vector<Mantid::Kernel::V3D> directions) const; - - Mantid::Kernel::V3D rotateVector(Mantid::Kernel::V3D original, Mantid::Kernel::V3D rotationAxis, double angle) const; - void validateWsNotNull() const; void validateDimensionsPresent() const; diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSinglePeakMarker.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSinglePeakMarker.h new file mode 100644 index 00000000000..a51f32bb1f0 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSinglePeakMarker.h @@ -0,0 +1,47 @@ +#ifndef MANTID_VATES_SINGLEPEAKMARKER_H_ +#define MANTID_VATES_SINGLEPEAKMARKER_H_ + +#include "MantidKernel/System.h" +/** + Creates a single marker at a given position + + @date 23/02/2015 + + Copyright © 2010 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge National Laboratory & European Spallation Source + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + + +class vtkPolyData; + +namespace Mantid +{ +namespace VATES +{ + class DLLExport vtkSinglePeakMarker + { + public: + vtkSinglePeakMarker(); + ~vtkSinglePeakMarker(); + vtkPolyData* createSinglePeakMarker(double x, double y, double z, double radius); + }; +} +} +#endif diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h index 3ad5c3ef481..b793eae000e 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/vtkSplatterPlotFactory.h @@ -9,6 +9,9 @@ #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidVatesAPI/ThresholdRange.h" #include "MantidVatesAPI/vtkDataSetFactory.h" +#include "MantidVatesAPI/MetaDataExtractorUtils.h" +#include "MantidVatesAPI/MetadataJsonManager.h" +#include "MantidVatesAPI/VatesConfigurations.h" #include <vtkPoints.h> #include <boost/shared_ptr.hpp> #include <boost/scoped_ptr.hpp> @@ -91,6 +94,9 @@ public: /// Getter for the instrument virtual const std::string& getInstrument(); + /// Set the appropriate field data + virtual void setMetadata(vtkFieldData* fieldData, vtkDataSet* dataSet); + private: template<typename MDE, size_t nd> @@ -108,6 +114,9 @@ private: /// Template Method pattern to validate the factory before use. virtual void validate() const; + /// Add metadata + void addMetadata() const; + /// Threshold range strategy. ThresholdRange_scptr m_thresholdRange; @@ -158,6 +167,12 @@ private: /// Meta data extractor boost::scoped_ptr<MetaDataExtractorUtils> m_metaDataExtractor; + + /// Meata data json manager + boost::scoped_ptr<MetadataJsonManager> m_metadataJsonManager; + + /// Vates configuration + boost::scoped_ptr<VatesConfigurations> m_vatesConfigurations; }; } diff --git a/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp b/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp new file mode 100644 index 00000000000..c7f4bd1292f --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp @@ -0,0 +1,151 @@ +#include "MantidVatesAPI/CompositePeaksPresenterVsi.h" +#include "MantidVatesAPI/PeaksPresenterVsi.h" +#include "MantidVatesAPI/ViewFrustum.h" +#include "MantidAPI/IPeaksWorkspace.h" + +#include <vector> +#include <map> +namespace Mantid +{ +namespace VATES +{ + /// Constructor + CompositePeaksPresenterVsi::CompositePeaksPresenterVsi(){} + + /// Destructor + CompositePeaksPresenterVsi::~CompositePeaksPresenterVsi(){} + + /** + * Update the view frustum + * @param frustum The view frustum + */ + void CompositePeaksPresenterVsi::updateViewFrustum(ViewFrustum frustum) + { + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + (*it)->updateViewFrustum(frustum); + } + } + + /** + * Get the viewable peaks. Essentially copied from the slice viewer. + * @retruns A vector indicating which of the peaks are viewable. + */ + std::vector<bool> CompositePeaksPresenterVsi::getViewablePeaks() + { + return std::vector<bool>(); + } + + /** + * Get the name of all peaks workspaces as a vector + * @returns A vector of all peaks workspace names. + */ + std::vector<std::string> CompositePeaksPresenterVsi::getPeaksWorkspaceNames() { + std::vector<std::string> peaksWorkspaceNames; + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + peaksWorkspaceNames.push_back((*it)->getPeaksWorkspaceName()); + } + return peaksWorkspaceNames; + } + + /** + * Extract the peak information regarding position and radius of the peak. + * @param peaksWorkspace A pointer to the peaks workspace + * @param position A reference to extract the position. + * @param radius A reference to extract the radius. + */ + void CompositePeaksPresenterVsi::getPeaksInfo(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row, Mantid::Kernel::V3D& position, double& radius) { + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + if ((*it)->getPeaksWorkspace() == peaksWorkspace) { + (*it)->getPeaksInfo(peaksWorkspace, row, position, radius); + } + } + } + + /** + * Get the frame in which the peak workspaces are evaluated. Note that all will have the same frame, so only the first + * workspace needs to be probed. + * @returns The coordinate frame. + */ + std::string CompositePeaksPresenterVsi::getFrame() { + std::string frame; + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + frame = (*it)->getFrame(); + break; + } + return frame; + } + + /** + * Add a new peaks workspace presenter + * @param presenter Add a new presenter to the composite. + */ + void CompositePeaksPresenterVsi::addPresenter(PeaksPresenterVsi_sptr presenter) { + m_peaksPresenters.push_back(presenter); + } + + /** + * Get a vector with peak workspace pointers for which presenters exist. + * @returns A vector with peaks workspace pointers + */ + std::vector<Mantid::API::IPeaksWorkspace_sptr> CompositePeaksPresenterVsi::getPeaksWorkspaces() { + std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksWorkspaces; + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + peaksWorkspaces.push_back((*it)->getPeaksWorkspace()); + } + return peaksWorkspaces; + } + + /** + * Get the initialized viewable peaks. For each presenter return a vector with true for each peak + * @returns A vector of bool-vectors for each peaks presenter. + */ + std::map<std::string, std::vector<bool>> CompositePeaksPresenterVsi::getInitializedViewablePeaks(){ + std::map<std::string, std::vector<bool>> viewablePeaks; + for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { + viewablePeaks.insert(std::pair<std::string, std::vector<bool>>((*it)->getPeaksWorkspace()->getName(), std::vector<bool>((*it)->getPeaksWorkspace()->getNumberPeaks(), true))); + } + return viewablePeaks; + } + + /** + * Remove the presenters which are based on a certain peaks workspace. + * @param peaksWorkspaceName + */ + void CompositePeaksPresenterVsi::removePresenter(std::string peaksWorkspaceName) { + std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); + for (; it != m_peaksPresenters.end();) { + if ((*it)->getPeaksWorkspaceName() == peaksWorkspaceName) { + it = m_peaksPresenters.erase(it); + } else { + ++it; + } + } + } + + /** + * Update the presenters by checking if a presenter is still present, which is not needed any longer. + * @param peaksWorkspaceNames The names of all currently active peak sources. + */ + void CompositePeaksPresenterVsi::updateWorkspaces(std::vector<std::string>peaksWorkspaceNames) { + std::vector<std::string> storedPeaksWorkspaces = getPeaksWorkspaceNames(); + for (std::vector<std::string>::iterator it = storedPeaksWorkspaces.begin(); it != storedPeaksWorkspaces.end(); ++it) { + int count = std::count(peaksWorkspaceNames.begin(), peaksWorkspaceNames.end(), *it); + if (count == 0) { + removePresenter(*it); + } + } + } + + /** + * Check if there are any peaks availble. + * @returns If there are any peaks availbale. + */ + bool CompositePeaksPresenterVsi::hasPeaks(){ + if (m_peaksPresenters.size() > 0) { + return true; + } else { + return false; + } + } +} +} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp b/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp index 64bc505835d..269c5c97b4f 100644 --- a/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp @@ -15,6 +15,8 @@ namespace VATES /** * Constructor * @param peaksWorkspace The peaks workspace. + * @param frustum The view frustum + * @param frame The coordinate frame */ ConcretePeaksPresenterVsi::ConcretePeaksPresenterVsi(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, ViewFrustum frustum, @@ -31,6 +33,7 @@ namespace VATES /** * Update the view frustum + * @param frustum The view frustum. */ void ConcretePeaksPresenterVsi::updateViewFrustum(ViewFrustum frustum) { diff --git a/Code/Mantid/Vates/VatesAPI/src/MDEWInMemoryLoadingPresenter.cpp b/Code/Mantid/Vates/VatesAPI/src/MDEWInMemoryLoadingPresenter.cpp index 97796ff8e70..8eecf215dbb 100644 --- a/Code/Mantid/Vates/VatesAPI/src/MDEWInMemoryLoadingPresenter.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/MDEWInMemoryLoadingPresenter.cpp @@ -118,6 +118,9 @@ namespace Mantid // Set the instrument which is associated with the workspace. m_metadataJsonManager->setInstrument(m_metaDataExtractor->extractInstrument(eventWs)); + + // Set the special coordinates + m_metadataJsonManager->setSpecialCoordinates(m_specialCoords); //Call base-class extraction method. this->extractMetadata(eventWs); diff --git a/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp b/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp index 82023d01a58..961a2baab4a 100644 --- a/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp @@ -120,6 +120,9 @@ namespace Mantid // Set the instrument which is associated with the workspace. m_metadataJsonManager->setInstrument(m_metaDataExtractor->extractInstrument(histoWs)); + // Set the special coordinates + m_metadataJsonManager->setSpecialCoordinates(m_specialCoords); + //Call base-class extraction method. this->extractMetadata(histoWs); } diff --git a/Code/Mantid/Vates/VatesAPI/src/MetadataJsonManager.cpp b/Code/Mantid/Vates/VatesAPI/src/MetadataJsonManager.cpp index 11fba10cb87..b5ac9624ff7 100644 --- a/Code/Mantid/Vates/VatesAPI/src/MetadataJsonManager.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/MetadataJsonManager.cpp @@ -8,7 +8,7 @@ namespace Mantid namespace VATES { // Note that we need to have a non-empty default string - MetadataJsonManager::MetadataJsonManager() : instrument("_EMPTY_"), minValue(0.0), maxValue(1.0) + MetadataJsonManager::MetadataJsonManager() : instrument("_EMPTY_"), minValue(0.0), maxValue(1.0), specialCoordinates(-1) { } @@ -29,6 +29,7 @@ namespace Mantid metadataContainer["instrument"] = instrument; metadataContainer["minValue"] = minValue; metadataContainer["maxValue"] = maxValue; + metadataContainer["specialCoordinates"] = specialCoordinates; return writer.write(metadataContainer); } @@ -75,6 +76,16 @@ namespace Mantid { instrument = "_EMPTY_"; } + + // Set the instrument + if (metadataContainer.isObject() && metadataContainer.isMember("specialCoordinates")) + { + specialCoordinates = metadataContainer["specialCoordinates"].asInt(); + } + else + { + specialCoordinates = -1; + } } } @@ -132,5 +143,23 @@ namespace Mantid { return instrument; } + + /** + * Set the special coordinates. + * @param specialCoordinates. The special coordinates. + */ + void MetadataJsonManager::setSpecialCoordinates(int specialCoordinates) + { + this->specialCoordinates = specialCoordinates; + } + + /** + * Get the special coordinates + * @returns The special coordinates. + */ + int MetadataJsonManager::getSpecialCoordinates() + { + return specialCoordinates; + } } } \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToPeaksFilteredDataSet.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToPeaksFilteredDataSet.cpp index 09a0f16b98c..676291c6877 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToPeaksFilteredDataSet.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkDataSetToPeaksFilteredDataSet.cpp @@ -8,7 +8,7 @@ #include "MantidKernel/SpecialCoordinateSystem.h" #include "MantidKernel/V3D.h" #include "MantidKernel/ReadLock.h" - +#include "MantidVatesAPI/ProgressAction.h" #include <vtkExtractSelection.h> #include <vtkIdTypeArray.h> @@ -18,7 +18,8 @@ #include <vtkSelectionNode.h> #include <vtkSmartPointer.h> #include <vtkUnstructuredGrid.h> - +#include <vtkFieldData.h> +#include <vtkIdList.h> #include <boost/shared_ptr.hpp> #include <stdexcept> @@ -42,8 +43,9 @@ namespace VATES m_inputData(input), m_outputData(output), m_isInitialised(false), - m_radiusNoShape(1.0), - m_radiusType(0) + m_radiusNoShape(0.2), + m_radiusType(0), + m_radiusFactor(1.25) { if (NULL == m_inputData) { @@ -63,13 +65,13 @@ namespace VATES /** * Set the value for the underlying peaks workspace - * @param peaksWorkspaceName : The name of the peaks workspace. + * @param peaksWorkspaces : A list of peak workspace names. * @param radiusNoShape : The peak radius for no shape. * @param radiusType : The type of the radius: Radius(0), Outer Radius(10, Inner Radius(1) */ - void vtkDataSetToPeaksFilteredDataSet::initialize(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, double radiusNoShape, int radiusType) + void vtkDataSetToPeaksFilteredDataSet::initialize(std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksWorkspaces, double radiusNoShape, int radiusType) { - m_peaksWorkspace = peaksWorkspace; + m_peaksWorkspaces = peaksWorkspaces; m_radiusNoShape = radiusNoShape; m_radiusType = radiusType; m_isInitialised = true; @@ -79,8 +81,9 @@ namespace VATES * Process the input data. First, get all the peaks and their associated geometry. Then filter * through the input to find the peaks which lie within a peak. Then apply then to the output data. * Then update the metadata. See http://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/ExtractSelection + * @param progressUpdating The handle for the progress bar. */ - void vtkDataSetToPeaksFilteredDataSet::execute() + void vtkDataSetToPeaksFilteredDataSet::execute(ProgressAction& progressUpdating) { if (!m_isInitialised) { @@ -88,7 +91,7 @@ namespace VATES } // Get the peaks location and the radius information - std::vector<std::pair<Mantid::Kernel::V3D, double>> peaksInfo = getPeaksInfo(); + std::vector<std::pair<Mantid::Kernel::V3D, double>> peaksInfo = getPeaksInfo(m_peaksWorkspaces); // Compare each element of the vtk data set and check which ones to keep vtkPoints *points = m_inputData->GetPoints(); @@ -96,9 +99,11 @@ namespace VATES vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New(); ids->SetNumberOfComponents(1); - //PRAGMA_OMP( parallel for schedule (dynamic) ) + double progressFactor = 1.0/double(points->GetNumberOfPoints()); + for(int i = 0; i < points->GetNumberOfPoints(); i++) { + progressUpdating.eventRaised(double(i)*progressFactor); double point[3]; points->GetPoint(i, point); @@ -123,11 +128,33 @@ namespace VATES } } + // Now we have all ids for the points, we need to retrieve the ids of the cells + std::map<vtkIdType, vtkIdType> uniqueCellTester; + vtkSmartPointer<vtkIdTypeArray> cellIds = vtkSmartPointer<vtkIdTypeArray>::New(); + for (int i = 0; i < ids->GetNumberOfTuples(); i++) { + vtkIdType pId = ids->GetValue(i); + + vtkSmartPointer<vtkIdList> cIdList = vtkSmartPointer<vtkIdList>::New(); + cIdList->Initialize(); + + m_inputData->GetPointCells(pId, cIdList); + + if (cIdList->GetNumberOfIds() == 0) { + continue; + } + + vtkIdType cId = cIdList->GetId(0); + if (uniqueCellTester.count(cId) == 0) { + cellIds->InsertNextValue(cId); + uniqueCellTester.insert(std::pair<vtkIdType, vtkIdType>(cId, cId)); + } + } + // Create the selection node and tell it the type of selection vtkSmartPointer<vtkSelectionNode> selectionNode = vtkSmartPointer<vtkSelectionNode>::New(); selectionNode->SetFieldType(vtkSelectionNode::CELL); selectionNode->SetContentType(vtkSelectionNode::INDICES); - selectionNode->SetSelectionList(ids); + selectionNode->SetSelectionList(cellIds); vtkSmartPointer<vtkSelection> selection = vtkSmartPointer<vtkSelection>::New(); selection->AddNode(selectionNode); @@ -142,100 +169,139 @@ namespace VATES m_outputData->ShallowCopy(extractSelection->GetOutput()); // Update the metadata - + m_outputData->SetFieldData(m_inputData->GetFieldData()); } /** * Get the peaks information which is the position and the largest radius of the peak. - * @returns A list of peaks with position and radius information + * @param A list of peaks workspaces + * @returns A list of pair information which contains the position and the radius. */ - std::vector<std::pair<Mantid::Kernel::V3D, double>> vtkDataSetToPeaksFilteredDataSet::getPeaksInfo() + std::vector<std::pair<Mantid::Kernel::V3D, double>> vtkDataSetToPeaksFilteredDataSet::getPeaksInfo(std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksWorkspaces) { - Mantid::Kernel::ReadLock lock(*m_peaksWorkspace); - const Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = m_peaksWorkspace->getSpecialCoordinateSystem(); - - int numPeaks = m_peaksWorkspace->getNumberPeaks(); - - // Iterate over all peaks and store their information - std::vector<std::pair<Mantid::Kernel::V3D, double>> peaksInfo(numPeaks); + // Get number of peaks + int numberOfPeaks = 0; + for (std::vector<Mantid::API::IPeaksWorkspace_sptr>::iterator it = peaksWorkspaces.begin(); it != peaksWorkspaces.end(); ++it) + { + numberOfPeaks += (*it)->getNumberPeaks(); + } - for (int i = 0; i < numPeaks ; i++) + std::vector<std::pair<Mantid::Kernel::V3D, double>> peaksInfo(numberOfPeaks); + // Iterate over all peaksworkspaces and add the their info to the output vector + for (std::vector<Mantid::API::IPeaksWorkspace_sptr>::iterator it = peaksWorkspaces.begin(); it != peaksWorkspaces.end(); ++it) { - Mantid::API::IPeak* peak = m_peaksWorkspace->getPeakPtr(i); + const Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = (*it)->getSpecialCoordinateSystem(); + int numPeaks = (*it)->getNumberPeaks(); + + // Iterate over all peaks for the workspace + for (int i = 0; i < numPeaks ; i++) + { + Mantid::API::IPeak* peak = (*it)->getPeakPtr(i); - // Get radius, check directly for name and don't cast - double radius; - - const Mantid::Geometry::PeakShape& shape = peak->getPeakShape(); - std::string shapeName = shape.shapeName(); + addSinglePeak(peak, coordinateSystem, peaksInfo, static_cast<size_t>(i)); + } + } + return peaksInfo; + } - if (shapeName == Mantid::DataObjects::PeakShapeSpherical::sphereShapeName()) + /** + * Add information for a single peak to the peakInfo vector. + * @param peak The peak from which the information will be extracted. + * @param coordinateSystem The coordinate system in which the peaks position should be retrieved. + * @param peaksInfo A reference to the vector containing peak information. + * @param index The index of the peak in the peaksInfo vector. + */ + void vtkDataSetToPeaksFilteredDataSet::addSinglePeak(Mantid::API::IPeak* peak, const Mantid::Kernel::SpecialCoordinateSystem coordinateSystem, std::vector<std::pair<Mantid::Kernel::V3D, double>>& peaksInfo, size_t index) + { + double radius; + const Mantid::Geometry::PeakShape& shape = peak->getPeakShape(); + std::string shapeName = shape.shapeName(); + + // Get the radius and the position for the correct peak shape + if (shapeName == Mantid::DataObjects::PeakShapeSpherical::sphereShapeName()) + { + const Mantid::DataObjects::PeakShapeSpherical& sphericalShape = dynamic_cast<const Mantid::DataObjects::PeakShapeSpherical&>(shape); + if (m_radiusType == 0) { - const Mantid::DataObjects::PeakShapeSpherical& sphericalShape = dynamic_cast<const Mantid::DataObjects::PeakShapeSpherical&>(shape); - if (m_radiusType == 0) - { - radius = sphericalShape.radius(); - } - else if (m_radiusType == 1) - { - boost::optional<double> radOut = sphericalShape.backgroundOuterRadius(); - if (radOut) radius = *radOut; - } - else if (m_radiusType == 2) - { - boost::optional<double> radIn = sphericalShape.backgroundInnerRadius(); - if (radIn) radius = *radIn; - } - else - { - throw std::invalid_argument("The shperical peak shape does not have a radius. \n"); - } + radius = sphericalShape.radius(); } - else if (shapeName == Mantid::DataObjects::PeakShapeEllipsoid::ellipsoidShapeName()) + else if (m_radiusType == 1) { - const Mantid::DataObjects::PeakShapeEllipsoid& ellipticalShape = dynamic_cast<const Mantid::DataObjects::PeakShapeEllipsoid&>(shape); - if (m_radiusType == 0) - { - std::vector<double> radii(ellipticalShape.abcRadii()); - radius = *(std::max_element(radii.begin(), radii.end())); - } - else if (m_radiusType == 1) - { - std::vector<double> radii(ellipticalShape.abcRadiiBackgroundOuter()); - radius = *(std::max_element(radii.begin(), radii.end())); - } - else if (m_radiusType == 2) - { - std::vector<double> radii(ellipticalShape.abcRadiiBackgroundInner()); - radius = *(std::max_element(radii.begin(), radii.end())); - } - else - { - throw std::invalid_argument("The ellipsoidal peak shape does not have a radius. \n"); - } + boost::optional<double> radOut = sphericalShape.backgroundOuterRadius(); + if (radOut) radius = *radOut; } - else + else if (m_radiusType == 2) { - radius = m_radiusNoShape; + boost::optional<double> radIn = sphericalShape.backgroundInnerRadius(); + if (radIn) radius = *radIn; } - - // Get position - switch(coordinateSystem) + else { - case(Mantid::Kernel::SpecialCoordinateSystem::HKL): - peaksInfo[i] = std::pair<Mantid::Kernel::V3D, double>(peak->getHKL(), radius); - break; - case(Mantid::Kernel::SpecialCoordinateSystem::QLab): - peaksInfo[i] = std::pair<Mantid::Kernel::V3D, double>(peak->getQLabFrame(), radius); - break; - case(Mantid::Kernel::SpecialCoordinateSystem::QSample): - peaksInfo[i] = std::pair<Mantid::Kernel::V3D, double>(peak->getQSampleFrame(), radius); - break; - default: - throw std::invalid_argument("The special coordinate systems don't match."); + throw std::invalid_argument("The shperical peak shape does not have a radius. \n"); } } - return peaksInfo; + else if (shapeName == Mantid::DataObjects::PeakShapeEllipsoid::ellipsoidShapeName()) + { + const Mantid::DataObjects::PeakShapeEllipsoid& ellipticalShape = dynamic_cast<const Mantid::DataObjects::PeakShapeEllipsoid&>(shape); + if (m_radiusType == 0) + { + std::vector<double> radii(ellipticalShape.abcRadii()); + radius = *(std::max_element(radii.begin(), radii.end())); + } + else if (m_radiusType == 1) + { + std::vector<double> radii(ellipticalShape.abcRadiiBackgroundOuter()); + radius = *(std::max_element(radii.begin(), radii.end())); + } + else if (m_radiusType == 2) + { + std::vector<double> radii(ellipticalShape.abcRadiiBackgroundInner()); + radius = *(std::max_element(radii.begin(), radii.end())); + } + else + { + throw std::invalid_argument("The ellipsoidal peak shape does not have a radius. \n"); + } + } + else + { + radius = m_radiusNoShape; + } + + // Get the position in the correct frame. + switch(coordinateSystem) + { + case(Mantid::Kernel::SpecialCoordinateSystem::HKL): + peaksInfo[index] = std::pair<Mantid::Kernel::V3D, double>(peak->getHKL(), radius*m_radiusFactor); + break; + case(Mantid::Kernel::SpecialCoordinateSystem::QLab): + peaksInfo[index] = std::pair<Mantid::Kernel::V3D, double>(peak->getQLabFrame(), radius*m_radiusFactor); + break; + case(Mantid::Kernel::SpecialCoordinateSystem::QSample): + peaksInfo[index] = std::pair<Mantid::Kernel::V3D, double>(peak->getQSampleFrame(), radius*m_radiusFactor); + break; + default: + throw std::invalid_argument("The special coordinate systems don't match."); + } + } + + /** + * Get the radiys for no shape + * @returns The shape of the radius. + */ + double vtkDataSetToPeaksFilteredDataSet::getRadiusNoShape(){ + return m_radiusNoShape; } + + /** + * Get the radius factor which is used to calculate the radius of the culled data set around each peak + * The culling radius is the radius of the peak times the radius factor. + * @returns The radius factor. + */ + double vtkDataSetToPeaksFilteredDataSet::getRadiusFactor() { + return m_radiusFactor; + } + + } } \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkEllipsoidTransformer.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkEllipsoidTransformer.cpp new file mode 100644 index 00000000000..9ccba009468 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/src/vtkEllipsoidTransformer.cpp @@ -0,0 +1,78 @@ +#define _USE_MATH_DEFINES +#include "MantidVatesAPI/vtkEllipsoidTransformer.h" +#include "MantidKernel/V3D.h" + +#include <vtkSmartPointer.h> +#include <vtkTransform.h> +#include <cmath> + +namespace Mantid +{ +namespace VATES +{ + vtkEllipsoidTransformer::vtkEllipsoidTransformer(){} + + vtkEllipsoidTransformer::~vtkEllipsoidTransformer(){} + + /** + * Generates a transform based on the directions of the ellipsoid + * @param directions The directions of the ellipsoid. + * @returns A transform for the ellipsoid. + */ + vtkSmartPointer<vtkTransform> vtkEllipsoidTransformer::generateTransform(std::vector<Mantid::Kernel::V3D> directions) + { + // The original ellipsoid is set to have its principal axis along the x axis and the first minor axis along the y axis. + Mantid::Kernel::V3D principalAxisOriginal(1.0, 0.0, 0.0); + Mantid::Kernel::V3D principalAxisTransformed(directions[0]); + Mantid::Kernel::V3D minorAxisOriginal(0.0, 1.0, 0.0); + Mantid::Kernel::V3D minorAxisTransformed(directions[1]); + + // Compute the axis of rotation. This is the normal between the original and the transformed direction + Mantid::Kernel::V3D rotationAxis1 = principalAxisOriginal.cross_prod(principalAxisTransformed); + rotationAxis1 = rotationAxis1/rotationAxis1.norm(); + + // Compute the angle of rotation, i.e. the angle between the original and the transformed axis. + double angle1 = acos(principalAxisOriginal.scalar_prod(principalAxisTransformed) + /principalAxisOriginal.norm()/principalAxisTransformed.norm()); + + // After the prinicpal axis is rotated into its right position we need to rotate the (rotated) minor axis + // into its right position. The rotation axis is given by the new prinicipal rotation axis + Mantid::Kernel::V3D minorAxisOriginalRotated(rotateVector(minorAxisOriginal, rotationAxis1, angle1)); + + Mantid::Kernel::V3D rotationAxis2(minorAxisOriginalRotated.cross_prod(minorAxisTransformed)); + rotationAxis2 = rotationAxis2/rotationAxis2.norm(); + double angle2 = acos(minorAxisOriginalRotated.scalar_prod(minorAxisTransformed) + /minorAxisOriginalRotated.norm()/minorAxisTransformed.norm()); + + vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); + + double angle1Degree = angle1*180/M_PI; + double angle2Degree = angle2*180/M_PI; + + // The total transform is T = T_rot2*T_rot1. Note that we need to add the last operation first! + transform->RotateWXYZ(angle2Degree, rotationAxis2[0], rotationAxis2[1], rotationAxis2[2]); + transform->RotateWXYZ(angle1Degree, rotationAxis1[0], rotationAxis1[1], rotationAxis1[2]); + + return transform; + } + + /** + * Rotate the a given vector around a specified axis by a specified angle. See http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula + * @param original The original vector + * @param rotationAxis The axis around which to rotate. + * @param angle The rotation angle. + * @returns The rotated vector. + */ + Mantid::Kernel::V3D vtkEllipsoidTransformer::rotateVector(Mantid::Kernel::V3D original, Mantid::Kernel::V3D rotationAxis, double angle) + { + Mantid::Kernel::V3D cross(rotationAxis.cross_prod(original)); + double scalar = rotationAxis.scalar_prod(original); + double cos = std::cos(angle); + double sin = std::sin(angle); + + Mantid::Kernel::V3D rotated = original*cos + cross*sin + rotationAxis*(scalar)*(1-cos); + + return rotated; + } +} +} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkPeakMarkerFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkPeakMarkerFactory.cpp index c30fe5a21c3..8840b9dd8d1 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkPeakMarkerFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkPeakMarkerFactory.cpp @@ -1,5 +1,6 @@ #include "MantidVatesAPI/vtkPeakMarkerFactory.h" #include "MantidVatesAPI/ProgressAction.h" +#include "MantidVatesAPI/vtkEllipsoidTransformer.h" #include <boost/math/special_functions/fpclassify.hpp> #include "MantidAPI/Workspace.h" #include "MantidAPI/IPeaksWorkspace.h" @@ -27,6 +28,7 @@ #include <vtkPVGlyphFilter.h> #include <vtkSmartPointer.h> +#include <vtkLineSource.h> #include <cmath> using Mantid::API::IPeaksWorkspace; @@ -121,8 +123,9 @@ namespace VATES // Acquire a scoped read-only lock to the workspace (prevent segfault from algos modifying ws) Mantid::Kernel::ReadLock lock(*m_workspace); - const int resolution = 6; + vtkEllipsoidTransformer ellipsoidTransformer; + const int resolution = 8; double progressFactor = 1.0/double(numPeaks); vtkAppendPolyData* appendFilter = vtkAppendPolyData::New(); @@ -142,7 +145,7 @@ namespace VATES // What we'll return vtkUnstructuredGrid *peakDataSet = vtkUnstructuredGrid::New(); - peakDataSet->Allocate(numPeaks); + peakDataSet->Allocate(1); peakDataSet->SetPoints(peakPoint); peakDataSet->GetCellData()->SetScalars(peakSignal); @@ -181,6 +184,12 @@ namespace VATES peakPoint->Squeeze(); peakDataSet->Squeeze(); + //TEST ARENA .............. + double testRadius; + Mantid::Kernel::V3D mainAxis; + std::string json; + // TESTARENA ............... + // Add a glyph and append to the appendFilter const Mantid::Geometry::PeakShape& shape = m_workspace->getPeakPtr(i)->getPeakShape(); std::string name = shape.shapeName(); @@ -199,10 +208,35 @@ namespace VATES else if (shape.shapeName() == Mantid::DataObjects::PeakShapeEllipsoid::ellipsoidShapeName()) { const Mantid::DataObjects::PeakShapeEllipsoid& ellipticalShape = dynamic_cast<const Mantid::DataObjects::PeakShapeEllipsoid&>(shape); - std::vector<double> radii = ellipticalShape.abcRadii(); - std::vector<Mantid::Kernel::V3D> directions = ellipticalShape.directions(); - + std::vector<Mantid::Kernel::V3D> directions; + testRadius = radii[0]; + json = ellipticalShape.toJSON(); + switch (m_dimensionToShow) + { + case Peak_in_Q_lab: + directions = ellipticalShape.directions(); + break; + case Peak_in_Q_sample: + { + Mantid::Kernel::Matrix<double> goniometerMatrix = peak.getGoniometerMatrix(); + if (goniometerMatrix.Invert()) + { + directions = ellipticalShape.getDirectionInSpecificFrame(goniometerMatrix); + } + else + { + directions = ellipticalShape.directions(); + } + } + break; + case Peak_in_HKL: + directions = ellipticalShape.directions(); + break; + default: + directions = ellipticalShape.directions(); + } +#if 1 vtkParametricEllipsoid* ellipsoid = vtkParametricEllipsoid::New(); ellipsoid->SetXRadius(radii[0]); ellipsoid->SetYRadius(radii[1]); @@ -214,16 +248,19 @@ namespace VATES ellipsoidSource->SetVResolution(resolution); ellipsoidSource->SetWResolution(resolution); ellipsoidSource->Update(); - -#if 0 - vtkTransform* transform = vtkTransform::New(); - const double rotationDegrees = 0; - transform->RotateX(rotationDegrees); - transform->RotateY(rotationDegrees); - transform->RotateZ(rotationDegrees); #else - vtkSmartPointer<vtkTransform> transform = createEllipsoidTransform(directions); + vtkLineSource* ellipsoidSource = vtkLineSource::New(); + double point1[3] = {0,0,0}; + double point2[3] = {radii[0], 0, 0}; + + testRadius= radii[0]; + mainAxis = directions[0]; + + ellipsoidSource->SetPoint1(point1); + ellipsoidSource->SetPoint2(point2); #endif + vtkSmartPointer<vtkTransform> transform = ellipsoidTransformer.generateTransform(directions); + vtkTransformPolyDataFilter* transformFilter = vtkTransformPolyDataFilter::New(); transformFilter->SetTransform(transform); transformFilter->SetInputConnection(ellipsoidSource->GetOutputPort()); @@ -255,70 +292,48 @@ namespace VATES glyphFilter->Update(); vtkPolyData *glyphed = glyphFilter->GetOutput(); + // TEST ARENA + double p1[3] = {0.0,0.0,0.0}; + double p2[3] = {0.0,0.0,0.0}; + glyphed->GetPoint(0, p1); + glyphed->GetPoint(1, p2); + + // Evaluate the output + double corr1[3]; + double corr2[3]; + for (int j = 0; j < 3; j++) + { + corr1[j] = 0; + corr2[j] = (p2[j] -p1[j])/testRadius; + } + + bool isEqual = true; + const double tol = 1e-6; + for (int j = 0; j < 3; j++) + { + double diff = abs(corr2[j] - mainAxis[j]); + if (diff > tol) + { + isEqual = false; + } + } + + if (!isEqual) + { + int a= 1; + } + // TEST ARENA END appendFilter->AddInputData(glyphed); } // for each peak appendFilter->Update(); vtkPolyData* polyData = appendFilter->GetOutput(); + return polyData; } vtkPeakMarkerFactory::~vtkPeakMarkerFactory() { } - - /** - * Generates a transform based on the directions of the ellipsoid - * @param directions The directions of the ellipsoid. - * @returns A transform for the ellipsoid. - */ - vtkSmartPointer<vtkTransform> vtkPeakMarkerFactory::createEllipsoidTransform(std::vector<Mantid::Kernel::V3D> directions) const - { - // The original ellipsoid is oriented along the y axis - Mantid::Kernel::V3D principalAxisOriginal(0.0, 1.0, 0.0); - Mantid::Kernel::V3D principalAxisTransformed(directions[0]); - Mantid::Kernel::V3D minorAxisOriginal(1.0, 0.0, 0.0); - Mantid::Kernel::V3D minorAxisTransformed(directions[1]); - - // Compute the axis of rotation. This is the normal between the original and the transformed direction - Mantid::Kernel::V3D rotationAxis1 = principalAxisOriginal.cross_prod(principalAxisTransformed); - // Compute the angle of rotation, i.e. the angle between the original and the transformed axis. - double angle1 = acos(principalAxisOriginal.scalar_prod(principalAxisTransformed)); - - // After the prinicpal axis is rotated into its right position we need to rotate the (rotated) minor axis - // into its right position. The rotation axis is given by the new prinicipal rotation axis - Mantid::Kernel::V3D minorAxisOriginalRotated(rotateVector(minorAxisOriginal, rotationAxis1, angle1)); - - Mantid::Kernel::V3D rotationAxis2(principalAxisTransformed); - double angle2 = acos(minorAxisOriginalRotated.scalar_prod(minorAxisTransformed)); - - vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); - - double angle1Degree = angle1*180/3.1415; - double angle2Degree = angle2*180/3.1415; - transform->RotateWXYZ(angle1Degree, rotationAxis1[0], rotationAxis1[1], rotationAxis1[2]); - transform->RotateWXYZ(angle2Degree, rotationAxis2[0], rotationAxis2[1], rotationAxis2[2]); - - return transform; - } - - /** - * Rotate the a given vector around a specified axis by a specified angle. See http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula - * @param original The original vector - * @param rotationAxis The axis around which to rotate. - * @param angle The rotation angle. - * @returns The rotated vector. - */ - Mantid::Kernel::V3D vtkPeakMarkerFactory::rotateVector(Mantid::Kernel::V3D original, Mantid::Kernel::V3D rotationAxis, double angle) const - { - Mantid::Kernel::V3D cross(rotationAxis.cross_prod(original)); - double scalar = rotationAxis.scalar_prod(original); - double cos = std::cos(angle); - double sin = std::sin(angle); - - Mantid::Kernel::V3D rotated = original*cos + cross*sin + rotationAxis*(scalar)*(1-cos); - - return rotated; - } } } diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkSinglePeakMarker.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkSinglePeakMarker.cpp new file mode 100644 index 00000000000..9b4ae5ba2c9 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/src/vtkSinglePeakMarker.cpp @@ -0,0 +1,76 @@ +#include "MantidVatesAPI/vtkSinglePeakMarker.h" +#include <vtkPolyData.h> +#include "vtkFloatArray.h" +#include "vtkPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVertex.h" +#include "vtkPVGlyphFilter.h" +#include "vtkCellData.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" +#include "vtkTransformPolyDataFilter.h" + +namespace Mantid +{ +namespace VATES +{ + vtkSinglePeakMarker::vtkSinglePeakMarker(){ + } + + vtkSinglePeakMarker::~vtkSinglePeakMarker(){ + } + + vtkPolyData* vtkSinglePeakMarker::createSinglePeakMarker(double x, double y, double z, double radius){ + + // Point + vtkPoints *peakPoint = vtkPoints::New(); + peakPoint->Allocate(1); + + vtkFloatArray * peakSignal = vtkFloatArray::New(); + peakSignal->Allocate(1); + peakSignal->SetName("signal"); + peakSignal->SetNumberOfComponents(1); + + // What we'll return + vtkUnstructuredGrid *peakDataSet = vtkUnstructuredGrid::New(); + peakDataSet->Allocate(1); + peakDataSet->SetPoints(peakPoint); + peakDataSet->GetCellData()->SetScalars(peakSignal); + + // One point per peak + vtkVertex * vertex = vtkVertex::New(); + vtkIdType id_xyz = peakPoint->InsertNextPoint(x,y,z); + vertex->GetPointIds()->SetId(0, id_xyz); + + peakDataSet->InsertNextCell(VTK_VERTEX, vertex->GetPointIds()); + + // The integrated intensity = the signal on that point. + peakSignal->InsertNextValue(static_cast<float>(1.0)); + peakPoint->Squeeze(); + peakDataSet->Squeeze(); + + //Get the position info and create the glyph which is to be displayed. + vtkSphereSource* sphere = vtkSphereSource::New(); + const int resolution = 16; + sphere->SetRadius(radius); + sphere->SetPhiResolution(resolution); + sphere->SetThetaResolution(resolution); + + vtkTransform* transform = vtkTransform::New(); + transform->Translate(0, 0, 0); + + vtkTransformPolyDataFilter* transformFilter = vtkTransformPolyDataFilter::New(); + transformFilter->SetTransform(transform); + transformFilter->SetInputConnection(sphere->GetOutputPort()); + transformFilter->Update(); + + vtkPVGlyphFilter *glyphFilter = vtkPVGlyphFilter::New(); + glyphFilter->SetInputData(peakDataSet); + glyphFilter->SetSourceConnection(transformFilter->GetOutputPort()); + glyphFilter->Update(); + vtkPolyData *glyphed = glyphFilter->GetOutput(); + + return glyphed; + } +} +} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp index 91606a69525..55f0a77cf74 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp @@ -9,6 +9,12 @@ #include "MantidGeometry/MDGeometry/MDHistoDimension.h" #include "MantidVatesAPI/ProgressAction.h" #include "MantidVatesAPI/Common.h" +#include "MantidVatesAPI/MetadataToFieldData.h" +#include "MantidVatesAPI/FieldDataToMetadata.h" +#include "MantidVatesAPI/MetaDataExtractorUtils.h" +#include "MantidVatesAPI/MetadataJsonManager.h" +#include "MantidVatesAPI/VatesConfigurations.h" +#include "MantidVatesAPI/VatesXMLDefinitions.h" #include <vtkCellData.h> #include <vtkFloatArray.h> @@ -59,7 +65,9 @@ namespace VATES m_buildSortedList(true), m_wsName(""), dataSet(NULL), slice(false), sliceMask(NULL), sliceImplicitFunction(NULL), m_time(0.0), - m_metaDataExtractor(new MetaDataExtractorUtils()) + m_metaDataExtractor(new MetaDataExtractorUtils()), + m_metadataJsonManager(new MetadataJsonManager()), + m_vatesConfigurations(new VatesConfigurations()) { } @@ -576,6 +584,9 @@ namespace VATES delete this->sliceImplicitFunction; } + // Add metadata in json format + this->addMetadata(); + // The macro does not allow return calls, so we used a member variable. return this->dataSet; } @@ -618,6 +629,65 @@ namespace VATES } } + /** + * Add meta data to the visual data set. + */ + void vtkSplatterPlotFactory::addMetadata() const { + const double defaultValue = 0.1; + + if (this->dataSet) + { + double* range = NULL; + range = dataSet->GetScalarRange(); + + if (range) + { + m_minValue = range[0]; + m_maxValue = range[1]; + } + else + { + m_minValue = defaultValue; + m_maxValue = defaultValue; + } + + m_metadataJsonManager->setMinValue(m_minValue); + m_metadataJsonManager->setMaxValue(m_maxValue); + m_metadataJsonManager->setInstrument(m_metaDataExtractor->extractInstrument(m_workspace)); + + // Append metadata + std::string jsonString = m_metadataJsonManager->getSerializedJson(); + vtkFieldData* outputFD = vtkFieldData::New(); + + //Add metadata to dataset. + MetadataToFieldData convert; + convert(outputFD, jsonString, m_vatesConfigurations->getMetadataIdJson().c_str()); + dataSet->SetFieldData(outputFD); + + outputFD->Delete(); + } + } + + /** + * Write the xml metadata from the underlying source into the vktArray of the + * @param fieldData The field data from the underlying source + * @param dataSet The splatterplot data set. + */ + void vtkSplatterPlotFactory::setMetadata(vtkFieldData* fieldData, vtkDataSet* dataSet) { + // Extract the xml-metadata part of the fieldData and the json-metadata from the dataset + FieldDataToMetadata convertFtoM; + std::string xmlString = convertFtoM(fieldData, XMLDefinitions::metaDataId()); + std::string jsonString = convertFtoM(dataSet->GetFieldData(), m_vatesConfigurations->getMetadataIdJson().c_str()); + + // Create a new field data array + MetadataToFieldData convertMtoF; + vtkFieldData* outputFD = vtkFieldData::New(); + convertMtoF(outputFD, xmlString, XMLDefinitions::metaDataId().c_str()); + convertMtoF(outputFD, jsonString, m_vatesConfigurations->getMetadataIdJson().c_str()); + dataSet->SetFieldData(outputFD); + outputFD->Delete(); + } + /** * Sets the number of points to show * @param points : The total number of points to plot. diff --git a/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h b/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h new file mode 100644 index 00000000000..6e3dfa2a34b --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h @@ -0,0 +1,23 @@ +#ifndef COMOPOSITE_PEAKS_PRESENTER_VSI_TEST_H_ +#define COMOPOSITE_PEAKS_PRESENTER_VSI_TEST_H_ + +#include <cxxtest/TestSuite.h> +#include "MantidVatesAPI/CompositePeaksPresenterVsi.h" + + +#include "MockObjects.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> + + +#include <string> + + +class CompositePeaksPresenterVsiTest : public CxxTest::TestSuite { +public: + void testSetupPresenterCorrectly() { + + } +}; + +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h b/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h new file mode 100644 index 00000000000..2107ee4b8e4 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h @@ -0,0 +1,104 @@ +#ifndef CONCRETE_PEAKS_PRESENTER_VSI_TEST_H_ +#define CONCRETE_PEAKS_PRESENTER_VSI_TEST_H_ + +#include "MantidVatesAPI/ConcretePeaksPresenterVsi.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidVatesAPI/ViewFrustum.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidGeometry/Crystal/PeakShape.h" +#include "MantidDataObjects/PeakShapeSpherical.h" +#include "MantidDataObjects/PeakShapeEllipsoid.h" +#include "MantidDataObjects/NoShape.h" +#include "MantidKernel/V3D.h" +#include "MockObjects.h" +#include <boost/shared_ptr.hpp> + +#include <cxxtest/TestSuite.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> + + +#include <string> + +using namespace ::testing; +using namespace Mantid::VATES; + +class MockPeak : public Mantid::DataObjects::Peak +{ +public: + MOCK_CONST_METHOD0(getHKL, Mantid::Kernel::V3D (void)); + MOCK_CONST_METHOD0(getQLabFrame, Mantid::Kernel::V3D (void)); + MOCK_CONST_METHOD0(getQSampleFrame, Mantid::Kernel::V3D (void)); +}; + +class MockPeaksWorkspace : public Mantid::DataObjects::PeaksWorkspace +{ +public: + MOCK_CONST_METHOD0(getSpecialCoordinateSystem, Mantid::Kernel::SpecialCoordinateSystem()); + MOCK_CONST_METHOD0(getNumberPeaks, int()); + MOCK_METHOD1(getPeak, Mantid::DataObjects::Peak & (int peakNum)); + MOCK_CONST_METHOD2(createPeak, Mantid::API::IPeak* (Mantid::Kernel::V3D QLabFrame, double detectorDistance)); +}; + +class ConcretePeaksPresenterVsiTest : public CxxTest::TestSuite { +public: + void testSetupPresenterCorrectly() { + // Arrange + std::string frame = "testFrame"; + std::string name = "name"; + + LeftPlane left(1.0, 0.0, 0.0, 1.0); + + RightPlane right(-1.0, 0.0, 0.0, 1.0); + BottomPlane bottom(0.0, 1.0, 0.0, 1.0); + TopPlane top(0.0, -1.0, 0.0, 1.0); + FarPlane farPlane(0.0, 0.0, 1.0, 1.0); + NearPlane nearPlane(0.0, 0.0, -1.0,1.0); + ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + + boost::shared_ptr<MockPeaksWorkspace> pw_ptr(new MockPeaksWorkspace()); + MockPeaksWorkspace & pw = *pw_ptr; + // Act + ConcretePeaksPresenterVsi presenter(pw_ptr, frustum, frame); + + // Assert + TSM_ASSERT_EQUALS("Should have recorded the frame", presenter.getFrame(), frame); + } + + void testCorrectPeaksInfoIsExtractedForValidRow() { + // Arrange + std::string frame = "Q_LAB"; + + LeftPlane left(1.0, 0.0, 0.0, 1.0); + RightPlane right(-1.0, 0.0, 0.0, 1.0); + BottomPlane bottom(0.0, 1.0, 0.0, 1.0); + TopPlane top(0.0, -1.0, 0.0, 1.0); + FarPlane farPlane(0.0, 0.0, 1.0, 1.0); + NearPlane nearPlane(0.0, 0.0, -1.0,1.0); + ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + + Mantid::Kernel::V3D coordinate(1,0,0); + double peakRadius = 10; + Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = Mantid::Kernel::SpecialCoordinateSystem::QSample; + Mantid::Geometry::PeakShape_sptr shape(new Mantid::DataObjects::PeakShapeSpherical(peakRadius, coordinateSystem, "test", 1)); + MockPeak peak; + peak.setPeakShape(shape); + EXPECT_CALL(peak, getQLabFrame()).WillOnce(Return(coordinate)); + EXPECT_CALL(peak, getHKL()).Times(0); + EXPECT_CALL(peak, getQSampleFrame()).Times(0); + + + boost::shared_ptr<MockPeaksWorkspace> pw_ptr(new MockPeaksWorkspace()); + MockPeaksWorkspace & pw = *pw_ptr; + EXPECT_CALL(pw, getSpecialCoordinateSystem()).WillOnce(Return(coordinateSystem)); + EXPECT_CALL(pw, getPeak(_)).WillOnce(ReturnRef(peak)); + + // Act + ConcretePeaksPresenterVsi presenter(pw_ptr, frustum, frame); + double radius = 0;; + Mantid::Kernel::V3D coord(0,0,0); + presenter.getPeaksInfo(pw_ptr,0,coord, radius); + } +}; + +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/test/NullPeaksPresenterVsiTest.h b/Code/Mantid/Vates/VatesAPI/test/NullPeaksPresenterVsiTest.h new file mode 100644 index 00000000000..cade331b0d3 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/test/NullPeaksPresenterVsiTest.h @@ -0,0 +1,39 @@ +#ifndef NULL_PEAKS_PRESENTER_VSI_TEST_H_ +#define NULL_PEAKS_PRESENTER_VSI_TEST_H_ + +#include <cxxtest/TestSuite.h> +#include "MantidVatesAPI/NullPeaksPresenterVsi.h" +#include "MantidKernel/V3D.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include <stdexcept> + +using namespace Mantid::VATES; + +class NullPeaksPresenterVsiTest : public CxxTest::TestSuite +{ +public: + void testGettingPeaksWorkspaceThrows() { + NullPeaksPresenterVsi presenter; + TSM_ASSERT_THROWS("Should not implement this method", presenter.getPeaksWorkspace(), std::runtime_error); + } + + void testGettingUsablePeaksThrows() { + NullPeaksPresenterVsi presenter; + TSM_ASSERT_THROWS("Should not implement this method", presenter.getViewablePeaks(), std::runtime_error); + } + + void testGettingPeaksWorkspaceNameThrows() { + NullPeaksPresenterVsi presenter; + TSM_ASSERT_THROWS("Should not implement this method", presenter.getViewablePeaks(), std::runtime_error); + } + + void testGettingPeaksInfoThrows() { + NullPeaksPresenterVsi presenter; + int row = 0; + double radius; + Mantid::Kernel::V3D position; + Mantid::API::IPeaksWorkspace_sptr peaksWorkspace; + TSM_ASSERT_THROWS("Should not implement this method", presenter.getPeaksInfo(peaksWorkspace,row,position,radius), std::runtime_error); + } +}; +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/test/vtkDataSetToPeaksFilteredDataSetTest.h b/Code/Mantid/Vates/VatesAPI/test/vtkDataSetToPeaksFilteredDataSetTest.h index d55a478370b..b7f4629560b 100644 --- a/Code/Mantid/Vates/VatesAPI/test/vtkDataSetToPeaksFilteredDataSetTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/vtkDataSetToPeaksFilteredDataSetTest.h @@ -15,6 +15,7 @@ #include "MantidGeometry/Crystal/PeakShape.h" #include "MantidDataObjects/PeakShapeSpherical.h" #include "MantidDataObjects/PeakShapeEllipsoid.h" +#include "MantidDataObjects/NoShape.h" #include "MantidKernel/V3D.h" #include "MockObjects.h" #include <gmock/gmock.h> @@ -71,7 +72,7 @@ public: static vtkDataSetToPeaksFilteredDataSetTest *createSuite() { return new vtkDataSetToPeaksFilteredDataSetTest(); } static void destroySuite( vtkDataSetToPeaksFilteredDataSetTest *suite ) { delete suite; } - void do_test_peak_inSphere(vtkPoints* points,int numberOfPoints, double radius, Mantid::Kernel::V3D position, int& inside, int& outside, bool testingOutput) + void do_test_peak_inSphere(vtkPoints* points,int numberOfPoints, double radius, Mantid::Kernel::V3D position, int& inside, int& outside, bool testingOutput, double radiusFactor) { for (int i = 0; i < numberOfPoints; i++) { @@ -85,7 +86,7 @@ public: diffSquared += (position[k]-point[k])*(position[k]-point[k]); } - bool isInSphere = ((radius*radius - diffSquared) >= 0) ? true : false; + bool isInSphere = ((radius*radius*radiusFactor*radiusFactor - diffSquared) >= 0) ? true : false; isInSphere ? (inside++) : (outside++); // We expect only for the output, that all points are within the sphere @@ -96,21 +97,24 @@ public: } } - void do_test_peaks(vtkUnstructuredGrid* in, vtkUnstructuredGrid* out, Mantid::Kernel::V3D position, double radius) + void do_test_peaks(vtkUnstructuredGrid* in, vtkUnstructuredGrid* out, Mantid::Kernel::V3D position, double radius, double radiusFactor) { vtkPoints* inPoints = in->GetPoints(); vtkPoints* outPoints = out->GetPoints(); - + int numberOfInPoints = inPoints->GetNumberOfPoints(); int numberOfOutPoints = outPoints->GetNumberOfPoints(); + int numCellsIn = in->GetNumberOfCells(); + int numCellsOut = out->GetNumberOfCells(); + int insideSphereInput = 0; int outsideSphereInput = 0; - do_test_peak_inSphere(inPoints, numberOfInPoints, radius, position, insideSphereInput , outsideSphereInput, false); + do_test_peak_inSphere(inPoints, numberOfInPoints, radius, position, insideSphereInput , outsideSphereInput, false, radiusFactor); int insideSphereOutput = 0; int outsideSphereOutput = 0; - do_test_peak_inSphere(outPoints, numberOfOutPoints, radius, position, insideSphereOutput , outsideSphereOutput, true); + do_test_peak_inSphere(outPoints, numberOfOutPoints, radius, position, insideSphereOutput , outsideSphereOutput, true, radiusFactor); TSM_ASSERT("The number of elements inside the sphere should be the same for input and output.", insideSphereInput == insideSphereOutput); } @@ -143,12 +147,16 @@ public: boost::shared_ptr<MockPeaksWorkspace> pw_ptr(new MockPeaksWorkspace()); MockPeaksWorkspace & pw = *pw_ptr; - EXPECT_CALL(pw, getNumberPeaks()).WillOnce(Return(1)); + EXPECT_CALL(pw, getNumberPeaks()).Times(2).WillRepeatedly(Return(1)); EXPECT_CALL(pw, getPeak(_)).WillOnce(ReturnRef(peak)); EXPECT_CALL(pw, getSpecialCoordinateSystem()).WillOnce(Return(coordinateSystem)); - peaksFilter.initialize(pw_ptr, 0.5, 0); - TSM_ASSERT_THROWS_NOTHING("Should execute regularly.", peaksFilter.execute()); + std::vector<Mantid::API::IPeaksWorkspace_sptr> peaksContainer; + peaksContainer.push_back(pw_ptr); + + peaksFilter.initialize(peaksContainer, 0.5, 0); + FakeProgressAction updateProgress; + TSM_ASSERT_THROWS_NOTHING("Should execute regularly.", peaksFilter.execute(updateProgress)); } void testThrowIfInputNull() @@ -170,7 +178,8 @@ public: vtkUnstructuredGrid *in = vtkUnstructuredGrid::New(); vtkUnstructuredGrid *out = vtkUnstructuredGrid::New(); vtkDataSetToPeaksFilteredDataSet peaksFilter(in, out); - TS_ASSERT_THROWS(peaksFilter.execute(), std::runtime_error); + FakeProgressAction updateProgress; + TS_ASSERT_THROWS(peaksFilter.execute(updateProgress), std::runtime_error); } void testExecutionWithSingleSphericalPeakInQSample() @@ -181,7 +190,9 @@ public: vtkDataSetToPeaksFilteredDataSet peaksFilter(in, out); Mantid::Kernel::V3D coordinate(0,0,0); - double peakRadius = 10; + // Note that the peak radius is not a 1-1 measure for which peaks will be culled and which not. + // The actual radius is multiplied by the radius factor. + double peakRadius = 5; Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = Mantid::Kernel::SpecialCoordinateSystem::QSample; Mantid::Geometry::PeakShape_sptr shape(new Mantid::DataObjects::PeakShapeSpherical(peakRadius, coordinateSystem, "test", 1)); MockPeak peak; @@ -191,7 +202,7 @@ public: do_test_execute(peaksFilter, peak, coordinate, coordinateSystem); // Assert - do_test_peaks(in, out, coordinate, peakRadius); + do_test_peaks(in, out, coordinate, peakRadius, peaksFilter.getRadiusFactor()); in->Delete(); out->Delete(); @@ -205,11 +216,11 @@ public: vtkDataSetToPeaksFilteredDataSet peaksFilter(in, out); Mantid::Kernel::V3D coordinate(0,0,0); - double peakRadiusMax = 10; + double peakRadiusMax = 7; std::vector<double> radii; radii.push_back(peakRadiusMax); - radii.push_back(9); radii.push_back(6); + radii.push_back(5); std::vector<Mantid::Kernel::V3D> directions; directions.push_back(Mantid::Kernel::V3D(0.0,1.0,0.0)); @@ -225,17 +236,35 @@ public: do_test_execute(peaksFilter, peak, coordinate, coordinateSystem); // Assert - do_test_peaks(in, out, coordinate, peakRadiusMax); + do_test_peaks(in, out, coordinate, peakRadiusMax, peaksFilter.getRadiusFactor()); in->Delete(); out->Delete(); } - void testJsonMetadataExtractionFromScaledDataSet() + void testExecutionWithSingleNoShapePeakInQSample() { + // Arrange + vtkUnstructuredGrid *in = makeSplatterSourceGrid(); + vtkUnstructuredGrid *out = vtkUnstructuredGrid::New(); + vtkDataSetToPeaksFilteredDataSet peaksFilter(in, out); - } -}; + Mantid::Kernel::V3D coordinate(0,0,0); + Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = Mantid::Kernel::SpecialCoordinateSystem::QSample; + double radius = peaksFilter.getRadiusNoShape(); + Mantid::Geometry::PeakShape_sptr shape(new Mantid::DataObjects::NoShape()); + MockPeak peak; + peak.setPeakShape(shape); + + // Act + do_test_execute(peaksFilter, peak, coordinate, coordinateSystem); + + // Assert + do_test_peaks(in, out, coordinate, radius, peaksFilter.getRadiusFactor()); + in->Delete(); + out->Delete(); + } +}; #endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/test/vtkEllipsoidTransformerTest.h b/Code/Mantid/Vates/VatesAPI/test/vtkEllipsoidTransformerTest.h new file mode 100644 index 00000000000..680e75fac56 --- /dev/null +++ b/Code/Mantid/Vates/VatesAPI/test/vtkEllipsoidTransformerTest.h @@ -0,0 +1,252 @@ +#ifndef VTK_VATES_API_ELLIPSOIDTRANSFORMER_TEST +#define VTK_VATES_API_ELLIPSOIDTRANSFORMER_TEST + +#include <cxxtest/TestSuite.h> +#include "MantidVatesAPI/vtkEllipsoidTransformer.h" + +#include "MantidVatesAPI/vtkEllipsoidTransformer.h" +#include "MantidKernel/V3D.h" + +#include "MockObjects.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <vtkTransform.h> +#include <vtkSmartPointer.h> +#include <vtkLineSource.h> +#include <vtkTransformPolyDataFilter.h> +#include <vector> +#include <cmath> + +using namespace Mantid::VATES; + +class vtkEllipsoidTransformerTest : public CxxTest::TestSuite +{ +public: + void do_test(std::vector<Mantid::Kernel::V3D> directions, + std::vector<std::vector<double>> majorAxis, + std::vector<std::vector<double>> minorAxis, + std::vector<std::vector<double>> majorExpected, + std::vector<std::vector<double>> minorExpected) + { + // Arrange + vtkSmartPointer<vtkLineSource> major = vtkSmartPointer<vtkLineSource>::New(); + double majorPoint1[3] = {majorAxis[0][0], majorAxis[0][1], majorAxis[0][2]}; + double majorPoint2[3] = {majorAxis[1][0], majorAxis[1][1], majorAxis[1][2]}; + major->SetPoint1(majorPoint1); + major->SetPoint2(majorPoint2); + major->Update(); + + vtkSmartPointer<vtkLineSource> minor = vtkSmartPointer<vtkLineSource>::New(); + double minorPoint1[3] = {minorAxis[0][0], minorAxis[0][1], minorAxis[0][2]}; + double minorPoint2[3] = {minorAxis[1][0], minorAxis[1][1], minorAxis[1][2]}; + minor->SetPoint1(minorPoint1); + minor->SetPoint2(minorPoint2); + minor->Update(); + + // Act + vtkEllipsoidTransformer transformer; + vtkSmartPointer<vtkTransform> transform = transformer.generateTransform(directions); + + vtkTransformPolyDataFilter* transformFilter = vtkTransformPolyDataFilter::New(); + + transformFilter->SetTransform(transform); + transformFilter->SetInputConnection(major->GetOutputPort()); + transformFilter->Update(); + vtkPolyData* out = transformFilter->GetOutput(); + + double majorPoint1Rotated[3] = {0.0,0.0,0.0}; + double majorPoint2Rotated[3] = {0.0,0.0,0.0}; + out->GetPoint(0, majorPoint1Rotated); + out->GetPoint(1, majorPoint2Rotated); + + transformFilter->SetInputConnection(minor->GetOutputPort()); + transformFilter->Update(); + out = transformFilter->GetOutput(); + double minorPoint1Rotated[3] = {0.0,0.0,0.0}; + double minorPoint2Rotated[3] = {0.0,0.0,0.0}; + out->GetPoint(0, minorPoint1Rotated); + out->GetPoint(1, minorPoint2Rotated); + + // Assert + const double delta = 1e-5; + + TSM_ASSERT_DELTA("Point 1 of the major axis should not change", majorPoint1Rotated[0], majorExpected[0][0], delta); + TSM_ASSERT_DELTA("Point 1 of the major axis should not change", majorPoint1Rotated[1], majorExpected[0][1], delta); + TSM_ASSERT_DELTA("Point 1 of the major axis should not change", majorPoint1Rotated[2], majorExpected[0][2], delta); + + TSM_ASSERT_DELTA("Point 2 of the major axis should have changed", majorPoint2Rotated[0], majorExpected[1][0], delta); + TSM_ASSERT_DELTA("Point 2 of the major axis should have changed", majorPoint2Rotated[1], majorExpected[1][1], delta); + TSM_ASSERT_DELTA("Point 2 of the major axis should have changed", majorPoint2Rotated[2], majorExpected[1][2], delta); + + TSM_ASSERT_DELTA("Point 1 of the minor axis should not change", minorPoint1Rotated[0], minorExpected[0][0], delta); + TSM_ASSERT_DELTA("Point 1 of the minor axis should not change", minorPoint1Rotated[1], minorExpected[0][1], delta); + TSM_ASSERT_DELTA("Point 1 of the minor axis should not change", minorPoint1Rotated[2], minorExpected[0][2], delta); + + TSM_ASSERT_DELTA("Point 2 of the minor axis should have changed", minorPoint2Rotated[0], minorExpected[1][0], delta); + TSM_ASSERT_DELTA("Point 2 of the minor axis should have changed", minorPoint2Rotated[1], minorExpected[1][1], delta); + TSM_ASSERT_DELTA("Point 2 of the minor axis should have changed", minorPoint2Rotated[2], minorExpected[1][2], delta); + } + + void testGenerateTransformTiltedByNinetyDegrees() + { + // Arrange + Mantid::Kernel::V3D axis1(0.0,1.0,0.0); + Mantid::Kernel::V3D axis2(-1.0,0.0,0.0); + Mantid::Kernel::V3D axis3(0.0,0.0,1.0); + + std::vector<Mantid::Kernel::V3D> directions; + directions.push_back(axis1); + directions.push_back(axis2); + directions.push_back(axis3); + + // Major Axis + std::vector<double> point1Major; + point1Major.push_back(0.0); + point1Major.push_back(0.0); + point1Major.push_back(0.0); + + std::vector<double> point2Major; + point2Major.push_back(1.0); + point2Major.push_back(0.0); + point2Major.push_back(0.0); + + std::vector<std::vector<double>> major; + major.push_back(point1Major); + major.push_back(point2Major); + + // Minor Axis + std::vector<double> point1Minor; + point1Minor.push_back(0.0); + point1Minor.push_back(0.0); + point1Minor.push_back(0.0); + + std::vector<double> point2Minor; + point2Minor.push_back(0.0); + point2Minor.push_back(1.0); + point2Minor.push_back(0.0); + + std::vector<std::vector<double>> minor; + minor.push_back(point1Minor); + minor.push_back(point2Minor); + + std::vector<double> point1MajorExpected; + point1MajorExpected.push_back(0.0); + point1MajorExpected.push_back(0.0); + point1MajorExpected.push_back(0.0); + + std::vector<double> point2MajorExpected; + point2MajorExpected.push_back(0.0); + point2MajorExpected.push_back(1.0); + point2MajorExpected.push_back(0.0); + + std::vector<std::vector<double>> majorExpected; + majorExpected.push_back(point1MajorExpected); + majorExpected.push_back(point2MajorExpected); + + // Minor Axis + std::vector<double> point1MinorExpected; + point1MinorExpected.push_back(0.0); + point1MinorExpected.push_back(0.0); + point1MinorExpected.push_back(0.0); + + std::vector<double> point2MinorExpected; + point2MinorExpected.push_back(-1.0); + point2MinorExpected.push_back(0.0); + point2MinorExpected.push_back(0.0); + + std::vector<std::vector<double>> minorExpected; + minorExpected.push_back(point1MinorExpected); + minorExpected.push_back(point2MinorExpected); + + // Act + Assert + do_test(directions, major, minor, majorExpected, minorExpected); + } + + void testGenerateTransformInRandomDirection() + { + // Arrange + double xMajor = 1.3/sqrt(1.3*1.3 + 1.1*1.1 + 0.5*0.5); + double yMajor = -1.1/sqrt(1.3*1.3 + 1.1*1.1 + 0.5*0.5); + double zMajor = 0.5/sqrt(1.3*1.3 + 1.1*1.1 + 0.5*0.5); + + double xMinor = 1.1/1.3/sqrt(1*1 + (1.1/1.3)*(1.1/1.3)); + double yMinor = 1.0/sqrt(1*1 + (1.1/1.3)*(1.1/1.3)); + double zMinor = 0.0; + + Mantid::Kernel::V3D axis1(xMajor, yMajor, zMajor); + Mantid::Kernel::V3D axis2(xMinor,yMinor, zMinor); + // The third direction is not valid, but we don't need it for our calculations. + Mantid::Kernel::V3D axis3(0.0,0.0,1.0); + + std::vector<Mantid::Kernel::V3D> directions; + directions.push_back(axis1); + directions.push_back(axis2); + directions.push_back(axis3); + + // Major Axis + std::vector<double> point1Major; + point1Major.push_back(0.0); + point1Major.push_back(0.0); + point1Major.push_back(0.0); + + std::vector<double> point2Major; + point2Major.push_back(1.0); + point2Major.push_back(0.0); + point2Major.push_back(0.0); + + std::vector<std::vector<double>> major; + major.push_back(point1Major); + major.push_back(point2Major); + + // Minor Axis + std::vector<double> point1Minor; + point1Minor.push_back(0.0); + point1Minor.push_back(0.0); + point1Minor.push_back(0.0); + + std::vector<double> point2Minor; + point2Minor.push_back(0.0); + point2Minor.push_back(1.0); + point2Minor.push_back(0.0); + + std::vector<std::vector<double>> minor; + minor.push_back(point1Minor); + minor.push_back(point2Minor); + + std::vector<double> point1MajorExpected; + point1MajorExpected.push_back(0.0); + point1MajorExpected.push_back(0.0); + point1MajorExpected.push_back(0.0); + + std::vector<double> point2MajorExpected; + point2MajorExpected.push_back(xMajor); + point2MajorExpected.push_back(yMajor); + point2MajorExpected.push_back(zMajor); + + std::vector<std::vector<double>> majorExpected; + majorExpected.push_back(point1MajorExpected); + majorExpected.push_back(point2MajorExpected); + + // Minor Axis + std::vector<double> point1MinorExpected; + point1MinorExpected.push_back(0.0); + point1MinorExpected.push_back(0.0); + point1MinorExpected.push_back(0.0); + + std::vector<double> point2MinorExpected; + point2MinorExpected.push_back(xMinor); + point2MinorExpected.push_back(yMinor); + point2MinorExpected.push_back(zMinor); + + std::vector<std::vector<double>> minorExpected; + minorExpected.push_back(point1MinorExpected); + minorExpected.push_back(point2MinorExpected); + + // Act + Assert + do_test(directions, major, minor, majorExpected, minorExpected); + } +}; + + +#endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/test/vtkPeakMarkerFactoryTest.h b/Code/Mantid/Vates/VatesAPI/test/vtkPeakMarkerFactoryTest.h index 00e6be9ac4b..331c695831d 100644 --- a/Code/Mantid/Vates/VatesAPI/test/vtkPeakMarkerFactoryTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/vtkPeakMarkerFactoryTest.h @@ -5,6 +5,9 @@ #include "MantidDataObjects/PeaksWorkspace.h" #include "MantidVatesAPI/vtkPeakMarkerFactory.h" #include "MockObjects.h" + +#include <vtkPolyData.h> + #include <cxxtest/TestSuite.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -29,14 +32,14 @@ class MockPeaksWorkspace : public PeaksWorkspace { public: MOCK_METHOD1(setInstrument, void (Mantid::Geometry::Instrument_const_sptr inst)); - MOCK_CONST_METHOD0(getInstrument, Mantid::Geometry::Instrument_const_sptr ()); + MOCK_METHOD0(getInstrument, Mantid::Geometry::Instrument_const_sptr ()); MOCK_CONST_METHOD0(clone, Mantid::DataObjects::PeaksWorkspace*()); MOCK_CONST_METHOD0(getNumberPeaks, int()); MOCK_METHOD1(removePeak, void (int peakNum) ); MOCK_METHOD1(addPeak, void (const IPeak& ipeak)); MOCK_METHOD1(getPeak, Mantid::DataObjects::Peak & (int peakNum)); MOCK_CONST_METHOD1(getPeak, const Mantid::DataObjects::Peak & (int peakNum)); - MOCK_CONST_METHOD2(createPeak, Mantid::API::IPeak* (Mantid::Kernel::V3D QLabFrame, boost::optional<double> detectorDistance)); + MOCK_CONST_METHOD2(createPeak, Mantid::API::IPeak* (Mantid::Kernel::V3D QLabFrame, double detectorDistance)); }; //===================================================================================== @@ -49,7 +52,6 @@ public: void do_test(MockPeak & peak1, vtkPeakMarkerFactory::ePeakDimensions dims) { -#if 0 FakeProgressAction updateProgress; boost::shared_ptr<MockPeaksWorkspace> pw_ptr(new MockPeaksWorkspace()); MockPeaksWorkspace & pw = *pw_ptr; @@ -60,22 +62,26 @@ public: vtkPeakMarkerFactory factory("signal", dims); factory.initialize(pw_ptr); - vtkDataSet * set = factory.create(updateProgress); + vtkPolyData * set = factory.create(updateProgress); + + int num = set->GetNumberOfPoints(); + + // As the marker type are three axes(2 points), we expect 5*2*3 points + // The angle is 45degrees and the size is 0.3 + TS_ASSERT(set); - TS_ASSERT_EQUALS(set->GetNumberOfPoints(), 5); - TS_ASSERT_EQUALS(set->GetPoint(0)[0], 1.0); - TS_ASSERT_EQUALS(set->GetPoint(0)[1], 2.0); - TS_ASSERT_EQUALS(set->GetPoint(0)[2], 3.0); + TS_ASSERT_EQUALS(set->GetNumberOfPoints(), 30); + //TS_ASSERT_EQUALS(set->GetPoint(0)[0], 1.0); + //TS_ASSERT_EQUALS(set->GetPoint(0)[1], 2.0); + //TS_ASSERT_EQUALS(set->GetPoint(0)[2], 3.0); TS_ASSERT(testing::Mock::VerifyAndClearExpectations(&pw)); TS_ASSERT(testing::Mock::VerifyAndClearExpectations(&peak1)); set->Delete(); -#endif } void test_progress_updates() { -#if 0 MockPeak peak1; EXPECT_CALL( peak1, getQLabFrame()).WillRepeatedly( Return( V3D(1,2,3) )); EXPECT_CALL( peak1, getHKL()).Times(AnyNumber()); @@ -94,11 +100,10 @@ public: vtkPeakMarkerFactory factory("signal", vtkPeakMarkerFactory::Peak_in_Q_lab); factory.initialize(pw_ptr); - vtkDataSet * set = factory.create(mockProgress); + vtkPolyData * set = factory.create(mockProgress); set->Delete(); TSM_ASSERT("Progress Updates not used as expected.", Mock::VerifyAndClearExpectations(&mockProgress)); -#endif } void test_q_lab() diff --git a/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h b/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h index 58c4a57432c..318a7d263e9 100644 --- a/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/vtkSplatterPlotFactoryTest.h @@ -161,6 +161,18 @@ public: product->Delete(); } + void test_MetadataIsAddedCorrectly() + { + FakeProgressAction progressUpdate; + Mantid::MDEvents::MDEventWorkspace3Lean::sptr ws = MDEventsTestHelper::makeMDEW<3>(10, 0.0, 10.0, 1); + vtkSplatterPlotFactory factory(ThresholdRange_scptr(new UserDefinedThresholdRange(0, 1)), "signal"); + factory.initialize(ws); + vtkDataSet* product = NULL; + + TS_ASSERT_THROWS_NOTHING(product = factory.create(progressUpdate)); + + + } }; #endif diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/CMakeLists.txt b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/CMakeLists.txt index 38021689a82..278a8015e40 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/CMakeLists.txt +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/CMakeLists.txt @@ -12,8 +12,9 @@ set( INCLUDE_FILES inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h inc/MantidVatesSimpleGuiViewWidgets/MultisliceView.h inc/MantidVatesSimpleGuiViewWidgets/RebinAlgorithmDialogProvider.h - inc/MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h + inc/MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h + inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h inc/MantidVatesSimpleGuiViewWidgets/SaveScreenshotReaction.h inc/MantidVatesSimpleGuiViewWidgets/RebinnedSourcesManager.h inc/MantidVatesSimpleGuiViewWidgets/StandardView.h @@ -34,7 +35,8 @@ set( SOURCE_FILES src/MdViewerWidget.cpp src/MultisliceView.cpp src/RebinAlgorithmDialogProvider.cpp - src/PeakViewerVsi.cpp + src/PeaksTableControllerVsi.cpp + src/PeaksTabWidget.cpp src/PeaksWidget.cpp src/SaveScreenshotReaction.cpp src/RebinnedSourcesManager.cpp @@ -55,8 +57,9 @@ qt4_wrap_cpp( MOC_SOURCES inc/MantidVatesSimpleGuiViewWidgets/ColorSelectionWidget.h inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h inc/MantidVatesSimpleGuiViewWidgets/MultisliceView.h - inc/MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h + inc/MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h + inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h inc/MantidVatesSimpleGuiViewWidgets/SaveScreenshotReaction.h inc/MantidVatesSimpleGuiViewWidgets/RebinnedSourcesManager.h inc/MantidVatesSimpleGuiViewWidgets/StandardView.h @@ -73,6 +76,7 @@ qt4_wrap_ui( UI_BUILT_SOURCES inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.ui inc/MantidVatesSimpleGuiViewWidgets/MultisliceView.ui inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.ui + inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.ui inc/MantidVatesSimpleGuiViewWidgets/StandardView.ui inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.ui inc/MantidVatesSimpleGuiViewWidgets/ThreesliceView.ui diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h index 425e7c13285..bba6727a9a7 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h @@ -208,6 +208,12 @@ private: void removeAllRebinning(ModeControlWidget::Views view); /// Sets a listener for when sources are being destroyed void setDestroyedListener(); + /// Undo visibiltiy listener + void removeVisibilityListener(); + /// Destroy all sources and filters + void destroyAllSourcesAndFilters(); + /// Destroy a single linear pipeline + void destroySinglePipeline(pqPipelineSource * source); }; } // SimpleGui diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h new file mode 100644 index 00000000000..dcc786f156b --- /dev/null +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h @@ -0,0 +1,46 @@ +#ifndef VSI_PEAKSTABWIDGET_H +#define VSI_PEAKSTABWIDGET_H + +#include "ui_PeaksTabWidget.h" +#include "MantidVatesSimpleGuiViewWidgets/WidgetDllOption.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include <QWidget> +#include <string> +#include <vector> +#include <map> + +namespace Mantid +{ +namespace Vates +{ +namespace SimpleGui +{ + class EXPORT_OPT_MANTIDVATES_SIMPLEGUI_VIEWWIDGETS PeaksTabWidget : public QWidget + { + Q_OBJECT + public: + PeaksTabWidget(std::vector<Mantid::API::IPeaksWorkspace_sptr> ws, const std::string& coordinateSystem, QWidget *parent = 0); + ~PeaksTabWidget(); + void setupMvc(std::map<std::string, std::vector<bool>> visiblePeaks); + void addNewPeaksWorkspace(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, std::vector<bool> visiblePeaks); + void updateTabs(std::map<std::string, std::vector<bool>> visiblePeaks); + signals: + void zoomToPeak(Mantid::API::IPeaksWorkspace_sptr ws, int row); + public slots: + void onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr ws, int row); + private: + /// Update a certain tab. + void updateTab(std::vector<bool> visiblePeaks, int index); + /// Adds a new tab to the tab widget. + void PeaksTabWidget::addNewTab(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, std::string tabName, std::vector<bool> visiblePeaks); + /// Auto-generated UI controls. + Ui::PeaksTabWidget ui; + /// Peaks workspace to view. + std::vector<Mantid::API::IPeaksWorkspace_sptr> m_ws; + /// Coordinate system. + const std::string m_coordinateSystem; + }; +} //namespace +} +} +#endif // PEAKSWORKSPACEWIDGET_H diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.ui b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.ui new file mode 100644 index 00000000000..85322c8384f --- /dev/null +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.ui @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PeaksTabWidget</class> + <widget class="QWidget" name="PeaksTabWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>200</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="tabLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>-1</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h similarity index 54% rename from Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h rename to Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h index abdcbaf4541..6642b2bfa18 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h @@ -1,10 +1,10 @@ -#ifndef PEAKSVIEWERVSI_H_ -#define PEAKSVIEWERVSI_H_ +#ifndef PeaksTableControllerVSI_H_ +#define PeaksTableControllerVSI_H_ #include "MantidVatesSimpleGuiViewWidgets/WidgetDllOption.h" #include "MantidVatesSimpleGuiViewWidgets/CameraManager.h" -#include "MantidVatesSimpleGuiViewWidgets/PeaksWidget.h" -#include "MantidVatesAPI/PeaksPresenterVsi.h" +#include "MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h" +#include "MantidVatesAPI/CompositePeaksPresenterVsi.h" #include "MantidAPI/PeakTransformSelector.h" #include "MantidGeometry/Crystal/PeakShape.h" #include <QWidget> @@ -19,33 +19,41 @@ namespace Vates { namespace SimpleGui { -class EXPORT_OPT_MANTIDVATES_SIMPLEGUI_VIEWWIDGETS PeaksViewerVsi : public QWidget +class EXPORT_OPT_MANTIDVATES_SIMPLEGUI_VIEWWIDGETS PeaksTableControllerVsi : public QWidget { Q_OBJECT public: - PeaksViewerVsi(boost::shared_ptr<CameraManager> cameraManager, QWidget *parent=0); - void addWorkspace(pqPipelineSource* source, QPointer<pqPipelineSource> splatSource); + PeaksTableControllerVsi(boost::shared_ptr<CameraManager> cameraManager, QWidget *parent=0); + ~PeaksTableControllerVsi(); std::vector<bool> getViewablePeaks(); bool hasPeaks(); void showTable(); void showFullTable(); void removeTable(); - std::string getPeaksWorkspaceName(); + std::string getConcatenatedWorkspaceNames(std::string delimiter); + void updatePeaksWorkspaces(QList<QPointer<pqPipelineSource>> peakSources, pqPipelineSource* splatSource); +signals: + void setRotationToPoint(double x, double y, double z); public slots: void updateViewableArea(); void onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row); - + void destroySinglePeakSource(); + void onPeakMarkerDestroyed(); private: + void addWorkspace(pqPipelineSource* source, QPointer<pqPipelineSource> splatSource); std::vector<std::string> extractFrameFromSource(QPointer<pqPipelineSource> splatSource); + void generateSinglePeaksSource(double position1, double position2, double position3, double radius); + void resetSinglePeaksSource(double position1, double position2, double position3, double radius); bool checkMatchingSources(pqPipelineSource* source, QPointer<pqPipelineSource> splatSource); double getMaxRadius(Mantid::Geometry::PeakShape_sptr shape); void removeLayout(QWidget *widget); void createTable(bool full); boost::shared_ptr<CameraManager> m_cameraManager; - boost::shared_ptr<Mantid::VATES::PeaksPresenterVsi> m_presenter; + boost::shared_ptr<Mantid::VATES::CompositePeaksPresenterVsi> m_presenter; /// Object for choosing a PeakTransformFactory based on the workspace type. Mantid::API::PeakTransformSelector m_peakTransformSelector; - PeaksWidget* m_peaksWidget; + PeaksTabWidget* m_peaksTabWidget; + pqPipelineSource* m_peakMarker; }; } diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h index c91ccd61155..d973e1a3620 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.h @@ -6,6 +6,8 @@ #include "MantidAPI/IPeaksWorkspace.h" #include <QWidget> #include <string> +#include <vector> +#include <map> namespace Mantid { @@ -18,7 +20,8 @@ namespace SimpleGui Q_OBJECT public: PeaksWidget(Mantid::API::IPeaksWorkspace_sptr ws, const std::string& coordinateSystem, QWidget *parent = 0); - void PeaksWidget::setupMvc(std::vector<bool> visiblePeaks); + void setupMvc(std::vector<bool> visiblePeaks); + void updateModel(std::vector<bool> visiblePeaks); signals: void zoomToPeak(Mantid::API::IPeaksWorkspace_sptr ws, int row); public slots: diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.ui b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.ui index 30cda706d49..4c1aa03e838 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.ui +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/PeaksWidget.ui @@ -26,6 +26,18 @@ <string>Form</string> </property> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="1"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <layout class="QHBoxLayout" name="tableLayout"> <item> @@ -33,6 +45,12 @@ <property name="enabled"> <bool>true</bool> </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="autoScrollMargin"> + <number>7</number> + </property> <property name="alternatingRowColors"> <bool>true</bool> </property> diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h index f73787ca949..0414f33840e 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h @@ -5,9 +5,10 @@ #include "MantidVatesSimpleGuiViewWidgets/ViewBase.h" #include "MantidVatesSimpleGuiViewWidgets/WidgetDllOption.h" #include "MantidVatesSimpleGuiViewWidgets/CameraManager.h" -#include "MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h" +#include "MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h" #include <boost/shared_ptr.hpp> +#include <string> #include <QList> #include <QPointer> @@ -100,9 +101,9 @@ public slots: /// Check the coordinates for the peaks overlay if necessary void checkPeaksCoordinates(); /// Show the visible peaks table. - void onShowVisiblePeaksTable(); + void onShowPeaksTable(); /// Remove the visible peaks table. - void onRemoveVisiblePeaksTable(); + void onRemovePeaksTable(); /// Show all peaks in table. void onShowAllPeaksTable(); @@ -115,6 +116,10 @@ protected slots: * Create and apply a threshold filter to the data. */ void onThresholdButtonClicked(); + /// On peaks source destroyed + void onPeakSourceDestroyed(QObject*); + /// On peaks filter destroyed + void onPeaksFilterDestroyed(); private: Q_DISABLE_COPY(SplatterPlotView) @@ -131,6 +136,15 @@ private: void setupVisiblePeaksButtons(); /// Create the peaks filter void createPeaksFilter(); + /// Set the state of the peak button + void setPeakButton(bool state); + /// Set the frame for the peaks + void setPeakSourceFrame(pqPipelineSource* source); + /// Check if a peaks workspace is already part of the recorded peaks sources. + bool checkIfPeaksWorkspaceIsAlreadyBeingTracked(pqPipelineSource* source); + /// Update the peaks filter + void updatePeaksFilter(pqPipelineSource* filter); + bool noOverlay; ///< Flag to respond to overlay situation correctly QList<QPointer<pqPipelineSource> > peaksSource; ///< A list of peaks sources @@ -142,10 +156,11 @@ private: Ui::SplatterPlotView ui; ///< The splatter plot view'a UI form QPointer<pqRenderView> view; ///< The main view area boost::shared_ptr<CameraManager> m_cameraManager; ///< The camera manager - PeaksViewerVsi* m_peaksViewer; ///< The peaks presenter + PeaksTableControllerVsi* m_peaksTableController; ///< The peaks table controller QAction* m_allPeaksAction;///<The action for showing all peaks in the table. QAction* m_removePeaksAction; ///<The action for removing the peaks table. QAction* m_visiblePeaksAction; ///<The action for adding the visible peaks table. + std::string m_peaksWorkspaceNameDelimiter;///<Delimiter for peaks workspace strings. }; } // SimpleGui diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.ui b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.ui index c36e32e40d1..49505fefb1c 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.ui +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/SplatterPlotView.ui @@ -14,6 +14,15 @@ <string>Form</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>9</number> + </property> + <property name="rightMargin"> + <number>9</number> + </property> + <property name="bottomMargin"> + <number>9</number> + </property> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> @@ -118,9 +127,6 @@ </property> </widget> </item> - <item> - <layout class="QHBoxLayout" name="tableLayout"/> - </item> </layout> </widget> <resources/> diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp index 82101590b1b..4b6773c50b9 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp @@ -201,7 +201,9 @@ namespace SimpleGui // Check if source is custom filter if (QString(proxy->GetXMLName()).contains("MantidParaViewScaleWorkspace") || QString(proxy->GetXMLName()).contains("MDEWRebinningCutter") || - QString(proxy->GetXMLName()).contains("MantidParaViewSplatterPlot")) + QString(proxy->GetXMLName()).contains("MantidParaViewSplatterPlot") || + QString(proxy->GetXMLName()).contains("MantidParaViewPeaksFilter")) + { minValue = vtkSMPropertyHelper(proxy,"MinValue").GetAsDouble(); maxValue = vtkSMPropertyHelper(proxy,"MaxValue").GetAsDouble(); diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp index c03869729a2..5e360715d9d 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp @@ -1089,9 +1089,7 @@ bool MdViewerWidget::eventFilter(QObject *obj, QEvent *ev) this->ui.colorSelectionWidget->reset(); this->currentView->setColorScaleState(this->ui.colorSelectionWidget); - pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); - builder->destroySources(); - + destroyAllSourcesAndFilters(); this->currentView->updateSettings(); this->currentView->hide(); @@ -1376,6 +1374,9 @@ void MdViewerWidget::preDeleteHandle(const std::string &wsName, removeRebinning(src, true); return; } + + // Remove all visibility listeners + removeVisibilityListener(); emit this->requestClose(); } @@ -1452,7 +1453,74 @@ void MdViewerWidget::setVisibilityListener() } } +/** + * Disconnects the visibility listener connection for all sources + */ +void MdViewerWidget::removeVisibilityListener() { + // Set the connection to listen to a visibility change of the representation. + pqServer *server = pqActiveObjects::instance().activeServer(); + pqServerManagerModel *smModel = pqApplicationCore::instance()->getServerManagerModel(); + QList<pqPipelineSource *> sources; + sources = smModel->findItems<pqPipelineSource *>(server); + // Attach the visibilityChanged signal for all sources. + for (QList<pqPipelineSource *>::iterator source = sources.begin(); source != sources.end(); ++source) + { + QObject::disconnect((*source), SIGNAL(visibilityChanged(pqPipelineSource*, pqDataRepresentation*)), + this->currentView, SLOT(onVisibilityChanged(pqPipelineSource*, pqDataRepresentation*))); + } +} + + +/** + * Destroy all sources and filters and take into account that + * destruction needs to start from the end of the pipeline. + */ +void MdViewerWidget::destroyAllSourcesAndFilters() { + pqServer *server = pqActiveObjects::instance().activeServer(); + pqServerManagerModel *smModel = pqApplicationCore::instance()->getServerManagerModel(); + QList<pqPipelineSource *> sources = smModel->findItems<pqPipelineSource *>(server); + + // Out of all pqPipelineSources, find the "true" sources, which were + // created by a Source Plugin, i.e. MDEW Source, MDHW Source, PeakSource + QList<pqPipelineSource*> trueSources; + for (QList<pqPipelineSource *>::iterator source = sources.begin(); source != sources.end(); ++source) { + if (!qobject_cast<pqPipelineFilter*>(*source)) { + trueSources.push_back(*source); + } + } + + // For each true source, go to the end of the pipeline and destroy it on the way back + // to the start. This assumes linear pipelines. + for (QList<pqPipelineSource *>::iterator trueSource = trueSources.begin(); trueSource != trueSources.end(); ++trueSource) { + destroySinglePipeline(*trueSource); + } +} + +/** + * Destroy a single, linear pipeline + * @param source A true pqPiplineSource, i.e. not a filter. + */ +void MdViewerWidget::destroySinglePipeline(pqPipelineSource * source) { + + pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); + + // Move to the end of the pipeline + pqPipelineSource *sourceBuffer = source; + while(sourceBuffer->getNumberOfConsumers() > 0) { + sourceBuffer = sourceBuffer->getConsumer(0); + } + + // Now destroy the pipeline coming back again + pqPipelineFilter* filter = qobject_cast<pqPipelineFilter*>(sourceBuffer); + while(filter) { + sourceBuffer = filter->getInput(0); + builder->destroy(filter); + filter = qobject_cast<pqPipelineFilter*>(sourceBuffer); + } + + builder->destroy(sourceBuffer); +} } // namespace SimpleGui } // namespace Vates } // namespace Mantid diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeakViewerVsi.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeakViewerVsi.cpp deleted file mode 100644 index 59f913fe3ef..00000000000 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeakViewerVsi.cpp +++ /dev/null @@ -1,327 +0,0 @@ -#include "MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h" -#include "MantidVatesSimpleGuiViewWidgets/PeaksWidget.h" -#include "MantidVatesSimpleGuiViewWidgets/CameraManager.h" -#include "MantidAPI/IPeaksWorkspace.h" -#include "MantidAPI/IMDEventWorkspace.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/PeakTransformHKL.h" -#include "MantidAPI/PeakTransformQSample.h" -#include "MantidAPI/PeakTransformQLab.h" -#include "MantidKernel/V3D.h" - -#include "MantidVatesAPI/PeaksPresenterVsi.h" -#include "MantidVatesAPI/NullPeaksPresenterVsi.h" -#include "MantidVatesAPI/ConcretePeaksPresenterVsi.h" -#include "MantidQtAPI/PlotAxis.h" -#include "MantidGeometry/MDGeometry/IMDDimension.h" - -#include "MantidKernel/Logger.h" - -#include <boost/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <stdexcept> -#include <algorithm> - -// Have to deal with ParaView warnings and Intel compiler the hard way. -#if defined(__INTEL_COMPILER) - #pragma warning disable 1170 -#endif - -#include <vtkSMPropertyHelper.h> -#include <pqPipelineSource.h> -#include <pqPipelineFilter.h> - -#include <QString> -#include <QPointer> -#include <QVBoxLayout> -#include <QLayout> -#include <QLayoutItem> - -namespace Mantid -{ -namespace Vates -{ -namespace SimpleGui -{ - -namespace -{ - Mantid::Kernel::Logger g_log("PeakViewerVsi"); -} - - /** - * Constructor - * @param cameraManager A cameraManager pointer. - * @param parent A pointer to a QWidget parent. - */ - PeaksViewerVsi::PeaksViewerVsi(boost::shared_ptr<CameraManager> cameraManager, QWidget *parent) : QWidget(parent), - m_cameraManager(cameraManager), - m_presenter(new Mantid::VATES::NullPeaksPresenterVsi()), - m_peaksWidget(NULL) - { - m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformHKLFactory>()); - m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformQSampleFactory>()); - m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformQLabFactory>()); - } - - /** - * Check for viewable peaks. - * @returns A vector of the peak indices which are visible and which are not visible. - */ - std::vector<bool> PeaksViewerVsi::getViewablePeaks() - { - std::vector<bool> viewablePeaks; - if (m_presenter) - { - // Get the up to date area - updateViewableArea(); - - //Get a list with viewable peak coordinates - try - { - viewablePeaks = m_presenter->getViewablePeaks(); - } - catch(...) - { - g_log.warning() << "The viewable peaks could not be retrieved. \n"; - } - } - return viewablePeaks; - } - - /** - * Add a new workspace - * @param source A new peaks source - * @param splatSource A pointer to the splatter source - */ - void PeaksViewerVsi::addWorkspace(pqPipelineSource* source, QPointer<pqPipelineSource> splatSource) - { - try - { - if (!source || !splatSource) - { - throw std::invalid_argument("The pqPipelineSource of the peaks workspace does not exist."); - } - - // Get the pointer to the peaks workspace - std::string wsName(vtkSMPropertyHelper(source->getProxy(), "WorkspaceName", true).GetAsString()); - std::string peaksFrame(vtkSMPropertyHelper(source->getProxy(), "Peak Dimensions", true).GetAsString()); - - // Get dimensions from splattersource - std::vector<std::string> dimInfo = extractFrameFromSource(splatSource); - if (dimInfo.size() < 2) - { - throw std::invalid_argument("The workspace needs to have at least two dimensions"); - } - - std::string dimCompare = dimInfo[0]; - std::transform(dimCompare.begin(), dimCompare.end(),dimCompare.begin(), ::toupper); - std::transform(peaksFrame.begin(), peaksFrame.end(),peaksFrame.begin(), ::toupper); - // Check if frames match - if (dimCompare.find(peaksFrame) == std::string::npos) - { - throw std::runtime_error("The workspaces do not match."); - } - - Mantid::API::IPeaksWorkspace_sptr peaksWorkspace = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::IPeaksWorkspace>(wsName); - - Mantid::API::PeakTransformFactory_sptr transformFactory = m_peakTransformSelector.makeChoice(dimInfo[0], dimInfo[1]); - Mantid::API::PeakTransform_sptr transform = transformFactory->createTransform(dimInfo[0], dimInfo[1]); - std::string frame = transform->getFriendlyName(); - - m_presenter = boost::make_shared<Mantid::VATES::ConcretePeaksPresenterVsi>(peaksWorkspace, m_cameraManager->getCurrentViewFrustum(), frame); - } - catch(Mantid::Kernel::Exception::NotFoundError&) - { - g_log.warning() << "Could not retrieve the peaks workspace.\n"; - } - catch(std::invalid_argument &ex) - { - g_log.warning() << ex.what(); - } - catch(std::runtime_error &ex) - { - g_log.warning() << ex.what(); - } - } - - /** - * Update the view region for the presenters - */ - void PeaksViewerVsi::updateViewableArea() - { - Mantid::VATES::ViewFrustum frustum = m_cameraManager->getCurrentViewFrustum(); - m_presenter->updateViewFrustum(frustum); - } - - /** - * Extrac the frame from the source - * @param splatSource A pointer to a splatter plot source. - */ - std::vector<std::string> PeaksViewerVsi::extractFrameFromSource(QPointer<pqPipelineSource> splatSource) - { - pqPipelineFilter* filter = qobject_cast<pqPipelineFilter*>(splatSource); - - if (!filter) - { - throw std::invalid_argument("The splatter source is not a filter"); - } - - pqPipelineSource* originalSource = filter->getInput(0); - - if (!originalSource) - { - throw std::invalid_argument("The original source cannot be found"); - } - - std::string wsName(vtkSMPropertyHelper(originalSource->getProxy(), "WorkspaceName", true).GetAsString()); - Mantid::API::IMDEventWorkspace_sptr eventWorkspace = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::IMDEventWorkspace>(wsName); - - std::vector<std::string> dimensionInfo; - for (size_t i = 0; i < eventWorkspace->getNumDims(); i++) - { - dimensionInfo.push_back(MantidQt::API::PlotAxis(*(eventWorkspace->getDimension(i))).title().toStdString()); - } - - return dimensionInfo; - } - - /** - * Check if the peaks viewer has a peaks workspace loaded. - * @returns If the a peaks workspace is loaded. - */ - bool PeaksViewerVsi::hasPeaks() - { - if (!m_presenter) - { - return false; - } - else if (boost::dynamic_pointer_cast<Mantid::VATES::NullPeaksPresenterVsi>(m_presenter)) - { - return false; - } - else - { - return true; - } - } - - /** - * Show the table with the visible peaks - */ - void PeaksViewerVsi::showTable() - { - createTable(false); - } - - /** - * Show all peaks in the table. - */ - void PeaksViewerVsi::showFullTable() - { - createTable(true); - } - - /** - * Create the table - * @param full If the full table is to be displayed or only visible peaks. - */ - void PeaksViewerVsi::createTable(bool full) - { - // Create the table if it does not exist - if (hasPeaks()) - { - if (layout()) - { - removeLayout(this); - } - - // Create new widget - try - { - this->setLayout(new QVBoxLayout); - PeaksWidget* widget = new PeaksWidget(m_presenter->getPeaksWorkspace(), m_presenter->getFrame(), this); - QObject::connect(widget, SIGNAL(zoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int)), - this, SLOT(onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int))); - - // Initialize the viewablePeaks to be true - std::vector<bool> viewablePeaks(m_presenter->getPeaksWorkspace()->getNumberPeaks(),true); - - if (!full) - { - viewablePeaks = getViewablePeaks(); - } - - widget->setupMvc(viewablePeaks); - layout()->addWidget(widget); - } - catch(std::runtime_error &ex) - { - g_log.warning() << "Could not setup the the peaks widget for the splatterplot: " << ex.what() << "\n"; - } - catch(...) - { - g_log.warning() << "Could not setup the the peaks widget for the splatterplot.\n"; - } - } - } - - /** - * Remove the layout - * @param widget - */ - void PeaksViewerVsi::removeLayout(QWidget *widget) { - QLayout *layout = widget->layout(); - if (layout != 0) { - QLayoutItem *item; - while ((item = layout->takeAt(0)) != 0){ - layout->removeItem(item); - delete item->widget(); - } - delete layout; - } - } - - /** - * Remvove the table. - */ - void PeaksViewerVsi::removeTable() - { - if (layout()) { - removeLayout(this); - } - } - - /** - * Zoom to a specific peak - * @param peaksWorkspace The peaksworkspace which is currently being displayed. - * @param row The selected row. - */ - void PeaksViewerVsi::onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row) - { - try - { - double radius; - Mantid::Kernel::V3D position; - m_presenter->getPeaksInfo(peaksWorkspace, row, position, radius); - - // Reset camera - m_cameraManager->setCameraToPeak(position[0], position[1], position[2], radius); - } - catch (std::invalid_argument &ex) - { - g_log.warning() << ex.what(); - } - } - - /** - * Get the name of the peaks workspace - * @returns The name of the peaks workspace - */ - std::string PeaksViewerVsi::getPeaksWorkspaceName() - { - return m_presenter->getPeaksWorkspaceName(); - } -} -} -} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTabWidget.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTabWidget.cpp new file mode 100644 index 00000000000..59fdbc25d16 --- /dev/null +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTabWidget.cpp @@ -0,0 +1,112 @@ +#include "MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h" + +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidQtSliceViewer/QPeaksTableModel.h" +#include "MantidVatesSimpleGuiViewWidgets/PeaksWidget.h" +#include <QWidget> +#include <QItemSelectionModel> +#include <QModelIndex> +#include <vector> +#include <string> +#include <map> + +namespace Mantid +{ +namespace Vates +{ +namespace SimpleGui +{ +/** +Constructor + +@param ws : Peaks Workspace (MODEL) +@param coordinateSystem : Name of coordinate system used +@param parent : parent widget +*/ +PeaksTabWidget::PeaksTabWidget(std::vector<Mantid::API::IPeaksWorkspace_sptr> ws, const std::string &coordinateSystem, QWidget *parent) : QWidget(parent), m_ws(ws), m_coordinateSystem(coordinateSystem){ + ui.setupUi(this); +} + +/// Destructor +PeaksTabWidget::~PeaksTabWidget(){ +} + +/** + * Setup the Table model + * @param visiblePeaks : A vector of lists of visible peaks for each peak workspace + */ +void PeaksTabWidget::setupMvc(std::map<std::string, std::vector<bool>> visiblePeaks) +{ + for (std::vector<Mantid::API::IPeaksWorkspace_sptr>::iterator it = m_ws.begin(); it != m_ws.end(); ++it) { + // Create new tab + std::string name((*it)->getName().c_str()); + + // Get visible peaks + if (visiblePeaks.count((*it)->getName()) > 0) { + addNewTab(*it, name, visiblePeaks[(*it)->getName()]); + } + } +} + +void PeaksTabWidget::addNewTab(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, std::string tabName, std::vector<bool> visiblePeaks) { + PeaksWidget* widget = new PeaksWidget(peaksWorkspace, m_coordinateSystem, this); + widget->setupMvc(visiblePeaks); + + // Connect to the output of the widget + QObject::connect(widget, SIGNAL(zoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int)), + this, SLOT(onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int))); + + // Add as a new tab + this->ui.tabWidget->addTab(widget, QString(tabName.c_str())); +} + +/** + * Zoom to the peak of interest + * @param ws The workspace pointer. + * @param row The row in the table. + */ +void PeaksTabWidget::onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr ws, int row){ + emit zoomToPeak(ws, row); +} + +/** + * Update the models and remove the model if it is not required anymore. + * @param visiblePeaks A map with visible peaks for each workspace. + */ +void PeaksTabWidget::updateTabs(std::map<std::string, std::vector<bool>> visiblePeaks) { + // Iterate over all tabs + for (int i = 0; i < this->ui.tabWidget->count(); i++) { + QString label = this->ui.tabWidget->label(i); + + // Check if the peaks workspace still exists, if it does update, else delete the tab. + if (visiblePeaks.count(label.toStdString()) > 0) { + updateTab(visiblePeaks[label.toStdString()], i); + } + else + { + this->ui.tabWidget->removeTab(i); + } + } +} + +/** + * Update the tab + * @param visbiblePeaks Vector which determines which peaks are visible. + * @param index The tab index. + */ +void PeaksTabWidget::updateTab(std::vector<bool> visiblePeaks, int index) { + PeaksWidget* widget = qobject_cast<PeaksWidget*>(this->ui.tabWidget->widget(index)); + widget->updateModel(visiblePeaks); +} + +/** + * Add a new tabs widget + * @param peaksWorkspace A pointer to a peaksWorkspace + */ +void PeaksTabWidget::addNewPeaksWorkspace(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, std::vector<bool> visiblePeaks) { + m_ws.push_back(peaksWorkspace); + addNewTab(peaksWorkspace, peaksWorkspace->getName(), visiblePeaks); +} +} +} // namespace +} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp new file mode 100644 index 00000000000..80508388a0e --- /dev/null +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp @@ -0,0 +1,506 @@ +#include "MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h" + +#include <boost/make_shared.hpp> +#include <boost/shared_ptr.hpp> +#include <stdexcept> +#include <algorithm> +#include <map> +#include <sstream> + +#include "MantidVatesSimpleGuiViewWidgets/PeaksTabWidget.h" +#include "MantidVatesSimpleGuiViewWidgets/CameraManager.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidAPI/IMDEventWorkspace.h" +#include "MantidAPI/AnalysisDataService.h" +#include "MantidAPI/PeakTransformHKL.h" +#include "MantidAPI/PeakTransformQSample.h" +#include "MantidAPI/PeakTransformQLab.h" +#include "MantidKernel/V3D.h" +#include "MantidVatesAPI/PeaksPresenterVsi.h" +#include "MantidVatesAPI/NullPeaksPresenterVsi.h" +#include "MantidVatesAPI/ConcretePeaksPresenterVsi.h" +#include "MantidVatesAPI/CompositePeaksPresenterVsi.h" +#include "MantidQtAPI/PlotAxis.h" +#include "MantidGeometry/MDGeometry/IMDDimension.h" +#include "MantidKernel/Logger.h" + +// Have to deal with ParaView warnings and Intel compiler the hard way. +#if defined(__INTEL_COMPILER) + #pragma warning disable 1170 +#endif +#include <pqActiveObjects.h> +#include <pqApplicationCore.h> +#include <pqObjectBuilder.h> +#include <pqPipelineSource.h> +#include <pqPipelineFilter.h> +#include <pqServer.h> +#include <vtkSMSourceProxy.h> +#include <vtkSMPropertyHelper.h> +#include <vtkSMProxy.h> + +#include <QString> +#include <QPointer> +#include <QVBoxLayout> +#include <QLayout> +#include <QLayoutItem> + +namespace Mantid +{ +namespace Vates +{ +namespace SimpleGui +{ + +namespace +{ + Mantid::Kernel::Logger g_log("PeakViewerVsi"); +} + + /** + * Constructor + * @param cameraManager A cameraManager pointer. + * @param parent A pointer to a QWidget parent. + */ + PeaksTableControllerVsi::PeaksTableControllerVsi(boost::shared_ptr<CameraManager> cameraManager, QWidget *parent) : QWidget(parent), + m_cameraManager(cameraManager), + m_presenter(new Mantid::VATES::CompositePeaksPresenterVsi()), + m_peaksTabWidget(NULL), + m_peakMarker(NULL) + { + m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformHKLFactory>()); + m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformQSampleFactory>()); + m_peakTransformSelector.registerCandidate(boost::make_shared<Mantid::API::PeakTransformQLabFactory>()); + } + + PeaksTableControllerVsi::~PeaksTableControllerVsi() + { + destroySinglePeakSource(); + } + + /** + * Check for viewable peaks. + * @returns A vector of the peak indices which are visible and which are not visible. + */ + std::vector<bool> PeaksTableControllerVsi::getViewablePeaks() + { + std::vector<bool> viewablePeaks; + if (m_presenter) + { + // Get the up to date area + updateViewableArea(); + + //Get a list with viewable peak coordinates + try + { + viewablePeaks = m_presenter->getViewablePeaks(); + } + catch(...) + { + g_log.warning() << "The viewable peaks could not be retrieved. \n"; + } + } + return viewablePeaks; + } + + /** + * Add a new workspace + * @param source A new peaks source + * @param splatSource A pointer to the splatter source + */ + void PeaksTableControllerVsi::addWorkspace(pqPipelineSource* source, QPointer<pqPipelineSource> splatSource) + { + try + { + if (!source || !splatSource) + { + throw std::invalid_argument("The pqPipelineSource of the peaks workspace does not exist."); + } + + // Get the pointer to the peaks workspace + std::string wsName(vtkSMPropertyHelper(source->getProxy(), "WorkspaceName", true).GetAsString()); + std::string peaksFrame(vtkSMPropertyHelper(source->getProxy(), "Peak Dimensions", true).GetAsString()); + + // Get dimensions from splattersource + std::vector<std::string> dimInfo = extractFrameFromSource(splatSource); + if (dimInfo.size() < 2) + { + throw std::invalid_argument("The workspace needs to have at least two dimensions"); + } + + std::string dimCompare = dimInfo[0]; + std::transform(dimCompare.begin(), dimCompare.end(),dimCompare.begin(), ::toupper); + std::transform(peaksFrame.begin(), peaksFrame.end(),peaksFrame.begin(), ::toupper); + // Check if frames match + if (dimCompare.find(peaksFrame) == std::string::npos) + { + throw std::runtime_error("The workspaces do not match."); + } + + Mantid::API::IPeaksWorkspace_sptr peaksWorkspace = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::IPeaksWorkspace>(wsName); + + Mantid::API::PeakTransformFactory_sptr transformFactory = m_peakTransformSelector.makeChoice(dimInfo[0], dimInfo[1]); + Mantid::API::PeakTransform_sptr transform = transformFactory->createTransform(dimInfo[0], dimInfo[1]); + std::string frame = transform->getFriendlyName(); + + m_presenter->addPresenter(boost::make_shared<Mantid::VATES::ConcretePeaksPresenterVsi>(peaksWorkspace, m_cameraManager->getCurrentViewFrustum(), frame)); + + // If the tab widget is visible, then update it + if (m_peaksTabWidget) { + std::map<std::string, std::vector<bool>> viewablePeaks = m_presenter->getInitializedViewablePeaks(); + m_peaksTabWidget->addNewPeaksWorkspace(peaksWorkspace, viewablePeaks[peaksWorkspace->getName()]); + m_peaksTabWidget->updateTabs(viewablePeaks); + } + } + catch(Mantid::Kernel::Exception::NotFoundError&) + { + g_log.warning() << "Could not retrieve the peaks workspace.\n"; + throw; + } + catch(std::invalid_argument &ex) + { + g_log.warning() << ex.what(); + throw; + } + catch(std::runtime_error &ex) + { + g_log.warning() << ex.what(); + throw; + } + } + + /** + * Update the view region for the presenters + */ + void PeaksTableControllerVsi::updateViewableArea() + { + Mantid::VATES::ViewFrustum frustum = m_cameraManager->getCurrentViewFrustum(); + m_presenter->updateViewFrustum(frustum); + } + + /** + * Extract the frame from the source + * @param splatSource A pointer to a splatter plot source. + */ + std::vector<std::string> PeaksTableControllerVsi::extractFrameFromSource(QPointer<pqPipelineSource> splatSource) + { + pqPipelineFilter* filter = qobject_cast<pqPipelineFilter*>(splatSource); + + if (!filter) + { + throw std::invalid_argument("The splatter source is not a filter."); + } + + // Check the original source + pqPipelineSource* originalSource = filter->getInput(0); + if (!originalSource) + { + throw std::invalid_argument("The original source cannot be found."); + } + + std::string xmlName(originalSource->getProxy()->GetXMLName()); + if (!(xmlName.find("MDEW") != std::string::npos)) + { + throw std::invalid_argument("The original source cannot be found."); + } + + std::string wsName(vtkSMPropertyHelper(originalSource->getProxy(), "WorkspaceName", true).GetAsString()); + Mantid::API::IMDEventWorkspace_sptr eventWorkspace = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::IMDEventWorkspace>(wsName); + + std::vector<std::string> dimensionInfo; + for (size_t i = 0; i < eventWorkspace->getNumDims(); i++) + { + dimensionInfo.push_back(MantidQt::API::PlotAxis(*(eventWorkspace->getDimension(i))).title().toStdString()); + } + + return dimensionInfo; + } + + /** + * Check if the peaks viewer has a peaks workspace loaded. + * @returns If the a peaks workspace is loaded. + */ + bool PeaksTableControllerVsi::hasPeaks() + { + if (!m_presenter || !m_presenter->hasPeaks()) + { + return false; + } + else + { + return true; + } + } + + /** + * Show the table with the visible peaks + */ + void PeaksTableControllerVsi::showTable() + { + createTable(false); + } + + /** + * Show all peaks in the table. + */ + void PeaksTableControllerVsi::showFullTable() + { + createTable(true); + } + + /** + * Create the table + * @param full If the full table is to be displayed or only visible peaks. + */ + void PeaksTableControllerVsi::createTable(bool full) + { + // Create the table if it does not exist + if (hasPeaks()) + { + if (layout()) + { + removeLayout(this); + } + + // Create new widget + try + { + // Set the layout of the table + this->setLayout(new QVBoxLayout); + + PeaksTabWidget* widget = new PeaksTabWidget(m_presenter->getPeaksWorkspaces(), m_presenter->getFrame(), this); + QObject::connect(widget, SIGNAL(zoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int)), + this, SLOT(onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr, int))); + + // Initialize the viewablePeaks to be true + std::map<std::string, std::vector<bool>> viewablePeaks = m_presenter->getInitializedViewablePeaks(); + + if (!full) + { + //viewablePeaks = getViewablePeaks(); + } + + widget->setupMvc(viewablePeaks); + layout()->addWidget(widget); + m_peaksTabWidget = widget; + } + catch(std::runtime_error &ex) + { + g_log.warning() << "Could not setup the the peaks widget for the splatterplot: " << ex.what() << "\n"; + } + catch(...) + { + g_log.warning() << "Could not setup the the peaks widget for the splatterplot.\n"; + } + } + } + + /** + * Remove the layout + * @param widget + */ + void PeaksTableControllerVsi::removeLayout(QWidget *widget) { + QLayout *layout = widget->layout(); + if (layout != 0) { + QLayoutItem *item; + while ((item = layout->takeAt(0)) != 0){ + layout->removeItem(item); + delete item->widget(); + } + delete layout; + } + } + + /** + * Remove the table. + */ + void PeaksTableControllerVsi::removeTable() + { + destroySinglePeakSource(); + if (m_peaksTabWidget) { + m_peaksTabWidget->deleteLater(); + } + m_peaksTabWidget = NULL; + } + + /** + * Zoom to a specific peak + * @param peaksWorkspace The peaksworkspace which is currently being displayed. + * @param row The selected row. + */ + void PeaksTableControllerVsi::onZoomToPeak(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, int row) + { + try + { + double radius; + Mantid::Kernel::V3D position; + m_presenter->getPeaksInfo(peaksWorkspace, row, position, radius); + + // Reset camera + m_cameraManager->setCameraToPeak(position[0], position[1], position[2], radius); + + // Place a marker glyph at the position + if (!m_peakMarker) + { + generateSinglePeaksSource(position[0], position[1], position[2], radius); + } + else + { + resetSinglePeaksSource(position[0], position[1], position[2], radius); + } + + emit setRotationToPoint(position[0], position[1], position[2]); + } + catch (std::invalid_argument &ex) + { + g_log.warning() << ex.what(); + } + } + + /** + * Generate a single peak glyph + * @param position1 Position 1 of the glyph. + * @param position2 Position 2 of the glyph. + * @param position3 Position 3 of the glyph. + * @param radius The radius of the peak. + */ + void PeaksTableControllerVsi::generateSinglePeaksSource(double position1, double position2, double position3, double radius) + { + // Create the source from the plugin + pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); + pqServer *server = pqActiveObjects::instance().activeServer(); + pqPipelineSource *src = builder->createSource("sources", "SinglePeakMarkerSource", server); + vtkSMPropertyHelper(src->getProxy(), "Position1").Set(position1); + vtkSMPropertyHelper(src->getProxy(), "Position2").Set(position2); + vtkSMPropertyHelper(src->getProxy(), "Position3").Set(position3); + vtkSMPropertyHelper(src->getProxy(), "RadiusMarker").Set(radius); + + vtkSMSourceProxy *srcProxy = vtkSMSourceProxy::SafeDownCast(src->getProxy()); + srcProxy->UpdateVTKObjects(); + srcProxy->Modified(); + srcProxy->UpdatePipelineInformation(); + src->updatePipeline(); + + pqDataRepresentation *drep = builder->createDataRepresentation(src->getOutputPort(0), pqActiveObjects::instance().activeView()); + vtkSMPropertyHelper(drep->getProxy(), "Representation").Set("Surface"); + srcProxy->UpdateVTKObjects(); + srcProxy->Modified(); + srcProxy->UpdatePipelineInformation(); + src->updatePipeline(); + + pqActiveObjects::instance().activeView()->forceRender(); + + m_peakMarker = src; + + //We need to make sure we detect when the source is destroyed, as the user can delete it in the pipeline browser + QObject::connect(m_peakMarker, SIGNAL(destroyed()), + this, SLOT(onPeakMarkerDestroyed())); + + } + + /** + * Destroy a single peaks source. + */ + void PeaksTableControllerVsi::destroySinglePeakSource() + { + if (m_peakMarker) + { + pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); + builder->destroy(m_peakMarker); + + m_peakMarker = NULL; + } + } + + /** + * On Single Peak Marker destroyed + */ + void PeaksTableControllerVsi::onPeakMarkerDestroyed() + { + m_peakMarker = NULL; + } + + /** + * Reset the single peak source + * @param position1 Position 1 of the glyph. + * @param position2 Position 2 of the glyph. + * @param position3 Position 3 of the glyph. + * @param radius The radius of the peak. + */ + void PeaksTableControllerVsi::resetSinglePeaksSource(double position1, double position2, double position3, double radius) + { + vtkSMPropertyHelper(m_peakMarker->getProxy(), "Position1").Set(position1); + vtkSMPropertyHelper(m_peakMarker->getProxy(), "Position2").Set(position2); + vtkSMPropertyHelper(m_peakMarker->getProxy(), "Position3").Set(position3); + vtkSMPropertyHelper(m_peakMarker->getProxy(), "RadiusMarker").Set(radius); + + vtkSMSourceProxy *srcProxy = vtkSMSourceProxy::SafeDownCast(m_peakMarker->getProxy()); + srcProxy->UpdateVTKObjects(); + srcProxy->Modified(); + srcProxy->UpdatePipelineInformation(); + m_peakMarker->updatePipeline(); + + pqActiveObjects::instance().activeView()->forceRender(); + } + + /** + * Get the workspace names as a concatenated string + * @param delimiter The delimiter to concatenate workspace names. + * @returns The concatenated workspace names. + */ + std::string PeaksTableControllerVsi::getConcatenatedWorkspaceNames(std::string delimiter) { + std::vector<std::string> peaksWorkspaceNames = m_presenter->getPeaksWorkspaceNames(); + std::stringstream stream; + for (size_t i = 0; i < peaksWorkspaceNames.size(); i++) { + stream << peaksWorkspaceNames[i]; + // Don't add a delimiter after the last element + if (i != (peaksWorkspaceNames.size()-1)) { + stream << delimiter; + } + } + return stream.str(); + } + + /** + * Update the presenters with the available peak workspaces + * @param peakSources A list with available peak sources + * @param splatSource The splatterplot source + */ + void PeaksTableControllerVsi::updatePeaksWorkspaces(QList<QPointer<pqPipelineSource>> peakSources, pqPipelineSource* splatSource) { + // Check if the which presenters exist and which need to be added + std::vector<std::string> peaksWorkspaceNames; + + std::vector<pqPipelineSource*> nonTrackedWorkspaces; + std::vector<std::string> trackedWorkspaceNames = m_presenter->getPeaksWorkspaceNames(); + for (QList<QPointer<pqPipelineSource>>::Iterator it = peakSources.begin(); it != peakSources.end(); ++it) { + std::string workspaceName(vtkSMPropertyHelper((*it)->getProxy(), "WorkspaceName").GetAsString()); + + peaksWorkspaceNames.push_back(workspaceName); + + int count = std::count(trackedWorkspaceNames.begin(), trackedWorkspaceNames.end(), workspaceName); + + if (count == 0) { + nonTrackedWorkspaces.push_back(*it); + } + } + + if (splatSource) { + // Add the workspaces which are missing in the presenter + for (std::vector<pqPipelineSource*>::iterator it = nonTrackedWorkspaces.begin(); it != nonTrackedWorkspaces.end(); ++it) { + addWorkspace(*it, splatSource); + } + } + + // Now update all the presenter + m_presenter->updateWorkspaces(peaksWorkspaceNames); + if (!peakSources.empty() && m_peaksTabWidget) { + m_peaksTabWidget->updateTabs(m_presenter->getInitializedViewablePeaks()); + } + + // If there are no presenters left, we want to destroy the table + if (!hasPeaks()) { + removeTable(); + } + } +} +} +} \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp index e66af49ae62..8331f024f51 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp @@ -4,6 +4,9 @@ #include <QWidget> #include <QItemSelectionModel> #include <QModelIndex> +#include <vector> +#include <string> +#include <map> namespace Mantid { @@ -24,11 +27,12 @@ PeaksWidget::PeaksWidget(Mantid::API::IPeaksWorkspace_sptr ws, const std::string /** * Setup the Table model - * @param visiblePeaks : A list of visible peaks + * @param visiblePeaks : A vector of lists of visible peaks for each peak workspace */ void PeaksWidget::setupMvc(std::vector<bool> visiblePeaks) { - MantidQt::SliceViewer::QPeaksTableModel* model = new MantidQt::SliceViewer::QPeaksTableModel(this->m_ws); + // Create new table view + MantidQt::SliceViewer::QPeaksTableModel* model = new MantidQt::SliceViewer::QPeaksTableModel(m_ws); ui.tblPeaks->setModel(model); const std::vector<int> hideCols = model->defaultHideCols(); for (auto it = hideCols.begin(); it != hideCols.end(); ++it) @@ -49,19 +53,16 @@ void PeaksWidget::setupMvc(std::vector<bool> visiblePeaks) ui.tblPeaks->horizontalHeader()->resizeSection(i, static_cast<int>(width)); } - // Hide the rows which are invisible - for (int i = 0; i < ui.tblPeaks->model()->rowCount(); i++) - { - if (visiblePeaks[i]) - { + // Set the visible rows + for (int i = 0; i < visiblePeaks.size(); i++) { + if (visiblePeaks[i]){ ui.tblPeaks->showRow(i); } else { ui.tblPeaks->hideRow(i); - } + } } - QItemSelectionModel* selectionModel = ui.tblPeaks->selectionModel(); connect(selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(onCurrentChanged(QModelIndex, QModelIndex))); } @@ -74,9 +75,26 @@ void PeaksWidget::onCurrentChanged(QModelIndex current, QModelIndex) { if (current.isValid()) { - emit zoomToPeak(this->m_ws, current.row()); + emit zoomToPeak(m_ws, current.row()); + } +} + +/** + * Update the visibility of the underlying model + * @param visiblePeaks A vector indicating which peaks are visible. + */ +void PeaksWidget::updateModel(std::vector<bool> visiblePeaks) { + for (int i = 0; i < visiblePeaks.size(); i++) { + if (visiblePeaks[i]){ + ui.tblPeaks->showRow(i); + } + else + { + ui.tblPeaks->hideRow(i); + } } } + } // namespace } } diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp index 4e175ab402a..edbc01a5933 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/SplatterPlotView.cpp @@ -1,6 +1,6 @@ #include "MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h" #include "MantidVatesSimpleGuiViewWidgets/CameraManager.h" -#include "MantidVatesSimpleGuiViewWidgets/PeakViewerVsi.h" +#include "MantidVatesSimpleGuiViewWidgets/PeaksTableControllerVsi.h" #include "MantidAPI/IMDEventWorkspace.h" #include "MantidQtAPI/SelectionNotificationService.h" #include "MantidVatesAPI/ADSWorkspaceProvider.h" @@ -57,17 +57,20 @@ namespace SplatterPlotView::SplatterPlotView(QWidget *parent) : ViewBase(parent), m_cameraManager(boost::make_shared<CameraManager>()), - m_peaksViewer(NULL) - + m_peaksTableController(NULL), + m_peaksWorkspaceNameDelimiter(";") { this->noOverlay = false; this->ui.setupUi(this); - m_peaksViewer = new PeaksViewerVsi(m_cameraManager, this); - m_peaksViewer->setMaximumHeight(150); - this->ui.tableLayout->addWidget(m_peaksViewer); - m_peaksViewer->setVisible(true); - + // Setup the peaks viewer + m_peaksTableController = new PeaksTableControllerVsi(m_cameraManager, this); + m_peaksTableController->setMaximumHeight(150); + //this->ui.tableLayout->addWidget(m_peaksTableController); + this->ui.verticalLayout->addWidget(m_peaksTableController); + m_peaksTableController->setVisible(true); + QObject::connect(m_peaksTableController, SIGNAL(setRotationToPoint(double, double, double)), + this, SLOT(onResetCenterToPoint(double, double, double))); // Set the threshold button to create a threshold filter on data QObject::connect(this->ui.thresholdButton, SIGNAL(clicked()), @@ -190,8 +193,23 @@ void SplatterPlotView::render() } else { + // We don't want to load the same peak workspace twice into the splatterplot mode + if (checkIfPeaksWorkspaceIsAlreadyBeingTracked(src)) { + QMessageBox::warning(this, QApplication::tr("Duplicate Peaks Workspace"), + QApplication::tr("You cannot load the same "\ + "Peaks Workpsace multiple times.")); + builder->destroy(src); + pqActiveObjects::instance().setActiveSource(this->splatSource); + return; + } + this->peaksSource.append(src); + setPeakSourceFrame(src); renderType = "Wireframe"; + // Start listening if the source was destroyed + QObject::connect(src, SIGNAL(destroyed(QObject*)), + this, SLOT(onPeakSourceDestroyed(QObject*))); + setPeakButton(true); } // Show the data @@ -221,16 +239,21 @@ void SplatterPlotView::render() this->renderAll(); } - // Add peaksSource to peaksViewer, currently only one + // Add peaksSource to the peak controller and the peak filter if (isPeaksWorkspace) { try { - m_peaksViewer->addWorkspace(src, this->splatSource); + m_peaksTableController->updatePeaksWorkspaces(this->peaksSource, this->splatSource); + + if (m_peaksFilter) + { + updatePeaksFilter(m_peaksFilter); + } } catch (...) { - // Log the error + setPeakButton(false); } } @@ -337,7 +360,7 @@ void SplatterPlotView::resetCamera() void SplatterPlotView::destroyPeakSources() { // First remove the peaks table, since it makes use of the peaks workspace. - onRemoveVisiblePeaksTable(); + onRemovePeaksTable(); pqServer *server = pqActiveObjects::instance().activeServer(); pqObjectBuilder *builder = pqApplicationCore::instance()->getObjectBuilder(); @@ -414,29 +437,30 @@ void SplatterPlotView::setupVisiblePeaksButtons() this->ui.peaksButton->setPopupMode(QToolButton::InstantPopup); this->ui.peaksButton->setMenu(peaksMenu); + setPeakButton(false); QObject::connect(m_allPeaksAction, SIGNAL(triggered()), this, SLOT(onShowAllPeaksTable()), Qt::QueuedConnection); QObject::connect(m_visiblePeaksAction, SIGNAL(triggered()), - this, SLOT(onShowVisiblePeaksTable()), Qt::QueuedConnection); + this, SLOT(onShowPeaksTable()), Qt::QueuedConnection); QObject::connect(m_removePeaksAction, SIGNAL(triggered()), - this, SLOT(onRemoveVisiblePeaksTable()), Qt::QueuedConnection); + this, SLOT(onRemovePeaksTable()), Qt::QueuedConnection); } /** * Show the visible peaks table. */ -void SplatterPlotView::onShowVisiblePeaksTable() +void SplatterPlotView::onShowPeaksTable() { // Create a peaks filter createPeaksFilter(); - if (m_peaksViewer->hasPeaks()) + if (m_peaksTableController->hasPeaks()) { - m_peaksViewer->showTable(); - m_peaksViewer->show(); + m_peaksTableController->showTable(); + m_peaksTableController->show(); } } @@ -447,10 +471,10 @@ void SplatterPlotView::onShowAllPeaksTable() { createPeaksFilter(); - if (m_peaksViewer->hasPeaks()) + if (m_peaksTableController->hasPeaks()) { - m_peaksViewer->showFullTable(); - m_peaksViewer->show(); + m_peaksTableController->showFullTable(); + m_peaksTableController->show(); } } @@ -458,19 +482,17 @@ void SplatterPlotView::onShowAllPeaksTable() /** * Remove the visible peaks table. */ -void SplatterPlotView::onRemoveVisiblePeaksTable() +void SplatterPlotView::onRemovePeaksTable() { - if (m_peaksViewer->hasPeaks()) + if (m_peaksTableController->hasPeaks()) { - //m_peaksViewer->removeTable(); - m_peaksViewer->hide(); + m_peaksTableController->removeTable(); } if (m_peaksFilter) { pqObjectBuilder *builder = pqApplicationCore::instance()->getObjectBuilder(); builder->destroy(m_peaksFilter); - m_peaksFilter = NULL; } } @@ -487,7 +509,7 @@ void SplatterPlotView::createPeaksFilter() } // If the there is no peaks workspace, then stay idle. - if (peaksSource.empty()) + if (peaksSource.isEmpty()) { return; } @@ -495,40 +517,161 @@ void SplatterPlotView::createPeaksFilter() // Create the peak filter pqObjectBuilder *builder = pqApplicationCore::instance()->getObjectBuilder(); - pqPipelineSource* filter = builder->createFilter("filters","MantidParaViewPeaksFilter", this->splatSource); + pqPipelineSource* filter = NULL; // Set the peaks workspace name. We need to trigger accept in order to log the workspace in the filter try { - std::string workspaceName = m_peaksViewer->getPeaksWorkspaceName(); - - if (workspaceName.empty()) - { - throw std::runtime_error("The peaks viewer does not contain a valid peaks workspace."); - } + m_peaksFilter = builder->createFilter("filters","MantidParaViewPeaksFilter", this->splatSource); + QObject::connect(m_peaksFilter, SIGNAL(destroyed()), + this, SLOT(onPeaksFilterDestroyed())); - vtkSMPropertyHelper(filter->getProxy(), "PeaksWorkspace").Set(workspaceName.c_str()); - emit this->triggerAccept(); - filter->updatePipeline(); + // Setup the peaks filter + updatePeaksFilter(m_peaksFilter); // Create point representation of the source and set the point size - pqDataRepresentation *dataRepresentation = filter->getRepresentation(this->view); + const double pointSize = 4; + pqDataRepresentation *dataRepresentation = m_peaksFilter->getRepresentation(this->view); vtkSMPropertyHelper(dataRepresentation->getProxy(), "Representation").Set("Points"); - vtkSMPropertyHelper(dataRepresentation->getProxy(), "PointSize").Set(4); + vtkSMPropertyHelper(dataRepresentation->getProxy(), "PointSize").Set(pointSize); dataRepresentation->getProxy()->UpdateVTKObjects(); pqPipelineRepresentation *pipelineRepresentation = qobject_cast<pqPipelineRepresentation*>(dataRepresentation); pipelineRepresentation->colorByArray("signal", vtkDataObject::FIELD_ASSOCIATION_CELLS); this->resetDisplay(); this->renderAll(); - - m_peaksFilter = filter; } catch(std::runtime_error &ex) { + // Destroy peak filter + if (m_peaksFilter) + { + builder->destroy(m_peaksFilter); + } g_log.warning() << ex.what(); } } +/* On peaks source destroyed + * @param source The reference to the destroyed source + */ +void SplatterPlotView::onPeakSourceDestroyed(QObject* source) +{ + // For each peak Source check if there is a "true" source available. + // If it is not availble then remove it from the peakSource storage. + for (QList<QPointer<pqPipelineSource>>::Iterator it = peaksSource.begin(); it != peaksSource.end();) { + pqServer *server = pqActiveObjects::instance().activeServer(); + pqServerManagerModel *smModel = pqApplicationCore::instance()->getServerManagerModel(); + QList<pqPipelineSource *> sources; + sources = smModel->findItems<pqPipelineSource *>(server); + + bool foundSource = false; + for (QList<pqPipelineSource *>::iterator src = sources.begin(); src != sources.end(); ++src) { + if ((*src) == (*it)) { + foundSource = true; + } + } + + if (!foundSource) { + it = peaksSource.erase(it); + } + else { + ++it; + } + } + + if (peaksSource.isEmpty()) + { + setPeakButton(false); + } + + // Update the availbale peaksTableController with the available workspaces + m_peaksTableController->updatePeaksWorkspaces(peaksSource, splatSource); + + // Update the peaks filter + try + { + updatePeaksFilter(m_peaksFilter); + } + catch(std::runtime_error &ex) + { + g_log.warning() << ex.what(); + } +} + +/** + * Sets the visibility of the peak button. + * @param state The visibility state of the peak button. + */ +void SplatterPlotView::setPeakButton(bool state) +{ + this->ui.peaksButton->setEnabled(state); +} + +/** + * Set the frame of the peak source + * @param source The peak source + */ +void SplatterPlotView::setPeakSourceFrame(pqPipelineSource* source) +{ + int peakViewCoords = vtkSMPropertyHelper(this->origSrc->getProxy(), "SpecialCoordinates").GetAsInt(); + peakViewCoords--; + vtkSMPropertyHelper(source->getProxy(), "Peak Dimensions").Set(peakViewCoords); +} + +/** + * Check if a peaks workspace is already tracked by the peaksSource list. + */ +bool SplatterPlotView::checkIfPeaksWorkspaceIsAlreadyBeingTracked(pqPipelineSource* source) { + bool isContained = false; + std::string sourceName(vtkSMPropertyHelper(source->getProxy(), "WorkspaceName").GetAsString()); + for (QList<QPointer<pqPipelineSource>>::Iterator it = peaksSource.begin(); it != peaksSource.end(); ++it) { + std::string trackedName(vtkSMPropertyHelper((*it)->getProxy(), "WorkspaceName").GetAsString()); + if ((*it == source) || (sourceName == trackedName)) { + isContained = true; + break; + } + } + return isContained; +} + +/** + * Updates the peaks filter, i.e. supplies the filter with a list of peaks workspaces and delimiter + * @param filter The peaks filter. + */ +void SplatterPlotView::updatePeaksFilter(pqPipelineSource* filter) { + if (!filter){ + return; + } + + // If there are no peaks, then destroy the filter, else update it. + if (peaksSource.isEmpty()) { + pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); + builder->destroy(filter); + } + else { + std::string workspaceNamesConcatentated = m_peaksTableController->getConcatenatedWorkspaceNames(m_peaksWorkspaceNameDelimiter); + if (workspaceNamesConcatentated.empty()) + { + throw std::runtime_error("The peaks viewer does not contain a valid peaks workspace."); + } + + vtkSMPropertyHelper(filter->getProxy(), "PeaksWorkspace").Set(workspaceNamesConcatentated.c_str()); + vtkSMPropertyHelper(filter->getProxy(), "Delimiter").Set(m_peaksWorkspaceNameDelimiter.c_str()); + emit this->triggerAccept(); + filter->updatePipeline(); + } +} + +/** + * Reacts to a destroyed peaks filter, mainly for setting the peak filter pointer to NULL. + * We need to do this, since PV can destroy the filter in a general destorySources command. + */ +void SplatterPlotView::onPeaksFilterDestroyed() { + m_peaksFilter = NULL; +} + + + } // SimpleGui } // Vates } // Mantid -- GitLab